| File: | Tip.c |
| Location: | line 255, column 19 |
| Description: | Access to field 'fid' results in a dereference of a null pointer (loaded from field 'font') |
| 1 | /* | |||
| 2 | * Copyright (c) 1999 by The XFree86 Project, Inc. | |||
| 3 | * | |||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | |||
| 5 | * copy of this software and associated documentation files (the "Software"), | |||
| 6 | * to deal in the Software without restriction, including without limitation | |||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | |||
| 9 | * Software is furnished to do so, subject to the following conditions: | |||
| 10 | * | |||
| 11 | * The above copyright notice and this permission notice shall be included in | |||
| 12 | * all copies or substantial portions of the Software. | |||
| 13 | * | |||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| 17 | * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |||
| 18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF | |||
| 19 | * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| 20 | * SOFTWARE. | |||
| 21 | * | |||
| 22 | * Except as contained in this notice, the name of the XFree86 Project shall | |||
| 23 | * not be used in advertising or otherwise to promote the sale, use or other | |||
| 24 | * dealings in this Software without prior written authorization from the | |||
| 25 | * XFree86 Project. | |||
| 26 | * | |||
| 27 | * Author: Paulo César Pereira de Andrade | |||
| 28 | */ | |||
| 29 | ||||
| 30 | #ifdef HAVE_CONFIG_H1 | |||
| 31 | #include <config.h> | |||
| 32 | #endif | |||
| 33 | #include <X11/IntrinsicP.h> | |||
| 34 | #include <X11/StringDefs.h> | |||
| 35 | #include <X11/Xos.h> | |||
| 36 | #include <X11/Xaw/TipP.h> | |||
| 37 | #include <X11/Xaw/XawInit.h> | |||
| 38 | #include <X11/Xmu/Converters.h> | |||
| 39 | #include "Private.h" | |||
| 40 | ||||
| 41 | #define TIP_EVENT_MASK((1L<<2) | (1L<<3) | (1L<<6) | (1L<<13 ) | (1L<<0) | (1L<<1) | (1L<<4) | (1L<< 5)) (ButtonPressMask(1L<<2) | \ | |||
| 42 | ButtonReleaseMask(1L<<3) | \ | |||
| 43 | PointerMotionMask(1L<<6) | \ | |||
| 44 | ButtonMotionMask(1L<<13) | \ | |||
| 45 | KeyPressMask(1L<<0) | \ | |||
| 46 | KeyReleaseMask(1L<<1) | \ | |||
| 47 | EnterWindowMask(1L<<4) | \ | |||
| 48 | LeaveWindowMask(1L<<5)) | |||
| 49 | ||||
| 50 | /* | |||
| 51 | * Types | |||
| 52 | */ | |||
| 53 | typedef struct _XawTipInfo { | |||
| 54 | Screen *screen; | |||
| 55 | TipWidget tip; | |||
| 56 | Widget widget; | |||
| 57 | Boolint mapped; | |||
| 58 | struct _XawTipInfo *next; | |||
| 59 | } XawTipInfo; | |||
| 60 | ||||
| 61 | /* | |||
| 62 | * Class Methods | |||
| 63 | */ | |||
| 64 | static void XawTipClassInitialize(void); | |||
| 65 | static void XawTipInitialize(Widget, Widget, ArgList, Cardinal*); | |||
| 66 | static void XawTipDestroy(Widget); | |||
| 67 | static void XawTipExpose(Widget, XEvent*, Region); | |||
| 68 | static void XawTipRealize(Widget, Mask*, XSetWindowAttributes*); | |||
| 69 | static Boolean XawTipSetValues(Widget, Widget, Widget, ArgList, Cardinal*); | |||
| 70 | ||||
| 71 | /* | |||
| 72 | * Prototypes | |||
| 73 | */ | |||
| 74 | static void TipEventHandler(Widget, XtPointer, XEvent*, Boolean*); | |||
| 75 | static void TipShellEventHandler(Widget, XtPointer, XEvent*, Boolean*); | |||
| 76 | static XawTipInfo *CreateTipInfo(Widget); | |||
| 77 | static XawTipInfo *FindTipInfo(Widget); | |||
| 78 | static void ResetTip(XawTipInfo*, Boolint); | |||
| 79 | static void TipTimeoutCallback(XtPointer, XtIntervalId*); | |||
| 80 | static void TipLayout(XawTipInfo*); | |||
| 81 | static void TipPosition(XawTipInfo*); | |||
| 82 | ||||
| 83 | /* | |||
| 84 | * Initialization | |||
| 85 | */ | |||
| 86 | #define offset(field) XtOffsetOf(TipRec, tip.field)__builtin_offsetof(TipRec, tip.field) | |||
| 87 | static XtResource resources[] = { | |||
| 88 | { | |||
| 89 | XtNforeground((char*)&XtStrings[214]), | |||
| 90 | XtCForeground((char*)&XtStrings[1022]), | |||
| 91 | XtRPixel((char*)&XtStrings[1754]), | |||
| 92 | sizeof(Pixel), | |||
| 93 | offset(foreground), | |||
| 94 | XtRString((char*)&XtStrings[1797]), | |||
| 95 | XtDefaultForeground"XtDefaultForeground", | |||
| 96 | }, | |||
| 97 | { | |||
| 98 | XtNfont((char*)&XtStrings[199]), | |||
| 99 | XtCFont((char*)&XtStrings[1017]), | |||
| 100 | XtRFontStruct((char*)&XtStrings[1666]), | |||
| 101 | sizeof(XFontStruct*), | |||
| 102 | offset(font), | |||
| 103 | XtRString((char*)&XtStrings[1797]), | |||
| 104 | XtDefaultFont"XtDefaultFont" | |||
| 105 | }, | |||
| 106 | { | |||
| 107 | XtNfontSet((char*)&XtStrings[2018]), | |||
| 108 | XtCFontSet((char*)&XtStrings[2034]), | |||
| 109 | XtRFontSet((char*)&XtStrings[2026]), | |||
| 110 | sizeof(XFontSet), | |||
| 111 | offset(fontset), | |||
| 112 | XtRString((char*)&XtStrings[1797]), | |||
| 113 | XtDefaultFontSet"XtDefaultFontSet" | |||
| 114 | }, | |||
| 115 | { | |||
| 116 | XtNtopMargin"topMargin", | |||
| 117 | XtCVerticalMargins"VerticalMargins", | |||
| 118 | XtRDimension((char*)&XtStrings[1618]), | |||
| 119 | sizeof(Dimension), | |||
| 120 | offset(top_margin), | |||
| 121 | XtRImmediate((char*)&XtStrings[1695]), | |||
| 122 | (XtPointer)2 | |||
| 123 | }, | |||
| 124 | { | |||
| 125 | XtNbottomMargin"bottomMargin", | |||
| 126 | XtCVerticalMargins"VerticalMargins", | |||
| 127 | XtRDimension((char*)&XtStrings[1618]), | |||
| 128 | sizeof(Dimension), | |||
| 129 | offset(bottom_margin), | |||
| 130 | XtRImmediate((char*)&XtStrings[1695]), | |||
| 131 | (XtPointer)2 | |||
| 132 | }, | |||
| 133 | { | |||
| 134 | XtNleftMargin"leftMargin", | |||
| 135 | XtCHorizontalMargins"HorizontalMargins", | |||
| 136 | XtRDimension((char*)&XtStrings[1618]), | |||
| 137 | sizeof(Dimension), | |||
| 138 | offset(left_margin), | |||
| 139 | XtRImmediate((char*)&XtStrings[1695]), | |||
| 140 | (XtPointer)6 | |||
| 141 | }, | |||
| 142 | { | |||
| 143 | XtNrightMargin"rightMargin", | |||
| 144 | XtCHorizontalMargins"HorizontalMargins", | |||
| 145 | XtRDimension((char*)&XtStrings[1618]), | |||
| 146 | sizeof(Dimension), | |||
| 147 | offset(right_margin), | |||
| 148 | XtRImmediate((char*)&XtStrings[1695]), | |||
| 149 | (XtPointer)6 | |||
| 150 | }, | |||
| 151 | { | |||
| 152 | XtNbackingStore"backingStore", | |||
| 153 | XtCBackingStore"BackingStore", | |||
| 154 | XtRBackingStore"BackingStore", | |||
| 155 | sizeof(int), | |||
| 156 | offset(backing_store), | |||
| 157 | XtRImmediate((char*)&XtStrings[1695]), | |||
| 158 | (XtPointer)(Always2 + WhenMapped1 + NotUseful0) | |||
| 159 | }, | |||
| 160 | { | |||
| 161 | XtNtimeout"timeout", | |||
| 162 | XtCTimeout"Timeout", | |||
| 163 | XtRInt((char*)&XtStrings[1718]), | |||
| 164 | sizeof(int), | |||
| 165 | offset(timeout), | |||
| 166 | XtRImmediate((char*)&XtStrings[1695]), | |||
| 167 | (XtPointer)500 | |||
| 168 | }, | |||
| 169 | { | |||
| 170 | XawNdisplayList"displayList", | |||
| 171 | XawCDisplayList"DisplayList", | |||
| 172 | XawRDisplayList"XawDisplayList", | |||
| 173 | sizeof(XawDisplayList*), | |||
| 174 | offset(display_list), | |||
| 175 | XtRImmediate((char*)&XtStrings[1695]), | |||
| 176 | NULL((void*)0) | |||
| 177 | }, | |||
| 178 | }; | |||
| 179 | #undef offset | |||
| 180 | ||||
| 181 | TipClassRec tipClassRec = { | |||
| 182 | /* core */ | |||
| 183 | { | |||
| 184 | (WidgetClass)&widgetClassRec, /* superclass */ | |||
| 185 | "Tip", /* class_name */ | |||
| 186 | sizeof(TipRec), /* widget_size */ | |||
| 187 | XawTipClassInitialize, /* class_initialize */ | |||
| 188 | NULL((void*)0), /* class_part_initialize */ | |||
| 189 | False0, /* class_inited */ | |||
| 190 | XawTipInitialize, /* initialize */ | |||
| 191 | NULL((void*)0), /* initialize_hook */ | |||
| 192 | XawTipRealize, /* realize */ | |||
| 193 | NULL((void*)0), /* actions */ | |||
| 194 | 0, /* num_actions */ | |||
| 195 | resources, /* resources */ | |||
| 196 | XtNumber(resources)((Cardinal) (sizeof(resources) / sizeof(resources[0]))), /* num_resources */ | |||
| 197 | NULLQUARK((XrmQuark) 0), /* xrm_class */ | |||
| 198 | True1, /* compress_motion */ | |||
| 199 | True1, /* compress_exposure */ | |||
| 200 | True1, /* compress_enterleave */ | |||
| 201 | False0, /* visible_interest */ | |||
| 202 | XawTipDestroy, /* destroy */ | |||
| 203 | NULL((void*)0), /* resize */ | |||
| 204 | XawTipExpose, /* expose */ | |||
| 205 | XawTipSetValues, /* set_values */ | |||
| 206 | NULL((void*)0), /* set_values_hook */ | |||
| 207 | XtInheritSetValuesAlmost((XtAlmostProc) _XtInherit), /* set_values_almost */ | |||
| 208 | NULL((void*)0), /* get_values_hook */ | |||
| 209 | NULL((void*)0), /* accept_focus */ | |||
| 210 | XtVersion(11 * 1000 + 6), /* version */ | |||
| 211 | NULL((void*)0), /* callback_private */ | |||
| 212 | NULL((void*)0), /* tm_table */ | |||
| 213 | XtInheritQueryGeometry((XtGeometryHandler) _XtInherit), /* query_geometry */ | |||
| 214 | XtInheritDisplayAccelerator((XtStringProc) _XtInherit), /* display_accelerator */ | |||
| 215 | NULL((void*)0), /* extension */ | |||
| 216 | }, | |||
| 217 | /* tip */ | |||
| 218 | { | |||
| 219 | NULL((void*)0), /* extension */ | |||
| 220 | }, | |||
| 221 | }; | |||
| 222 | ||||
| 223 | WidgetClass tipWidgetClass = (WidgetClass)&tipClassRec; | |||
| 224 | ||||
| 225 | static XawTipInfo *first_tip; | |||
| 226 | ||||
| 227 | /* | |||
| 228 | * Implementation | |||
| 229 | */ | |||
| 230 | static void | |||
| 231 | XawTipClassInitialize(void) | |||
| 232 | { | |||
| 233 | XawInitializeWidgetSet(); | |||
| 234 | XtAddConverter(XtRString((char*)&XtStrings[1797]), XtRBackingStore"BackingStore", XmuCvtStringToBackingStore, | |||
| 235 | NULL((void*)0), 0); | |||
| 236 | XtSetTypeConverter(XtRBackingStore"BackingStore", XtRString((char*)&XtStrings[1797]), XmuCvtBackingStoreToString, | |||
| 237 | NULL((void*)0), 0, XtCacheNone0x001, NULL((void*)0)); | |||
| 238 | } | |||
| 239 | ||||
| 240 | /*ARGSUSED*/ | |||
| 241 | static void | |||
| 242 | XawTipInitialize(Widget req, Widget w, ArgList args, Cardinal *num_args) | |||
| 243 | { | |||
| 244 | TipWidget tip = (TipWidget)w; | |||
| 245 | XGCValues values; | |||
| 246 | ||||
| 247 | if (!tip->tip.font) XtError("Aborting: no font found\n"); | |||
| ||||
| 248 | if (tip->tip.international && !tip->tip.fontset) | |||
| 249 | XtError("Aborting: no fontset found\n"); | |||
| 250 | ||||
| 251 | tip->tip.timer = 0; | |||
| 252 | ||||
| 253 | values.foreground = tip->tip.foreground; | |||
| 254 | values.background = tip->core.background_pixel; | |||
| 255 | values.font = tip->tip.font->fid; | |||
| ||||
| 256 | values.graphics_exposures = False0; | |||
| 257 | ||||
| 258 | tip->tip.gc = XtAllocateGC(w, 0, GCForeground(1L<<2) | GCBackground(1L<<3) | GCFont(1L<<14) | | |||
| 259 | GCGraphicsExposures(1L<<16), &values, GCFont(1L<<14), 0); | |||
| 260 | } | |||
| 261 | ||||
| 262 | static void | |||
| 263 | XawTipDestroy(Widget w) | |||
| 264 | { | |||
| 265 | XawTipInfo *info = FindTipInfo(w); | |||
| 266 | TipWidget tip = (TipWidget)w; | |||
| 267 | ||||
| 268 | if (tip->tip.timer) | |||
| 269 | XtRemoveTimeOut(tip->tip.timer); | |||
| 270 | ||||
| 271 | XtReleaseGC(w, tip->tip.gc); | |||
| 272 | ||||
| 273 | XtRemoveEventHandler(XtParent(w)((w)->core.parent), KeyPressMask(1L<<0), False0, TipShellEventHandler, | |||
| 274 | (XtPointer)NULL((void*)0)); | |||
| 275 | if (info == first_tip) | |||
| 276 | first_tip = first_tip->next; | |||
| 277 | else { | |||
| 278 | XawTipInfo *p = first_tip; | |||
| 279 | ||||
| 280 | while (p && p->next != info) | |||
| 281 | p = p->next; | |||
| 282 | if (p) | |||
| 283 | p->next = info->next; | |||
| 284 | } | |||
| 285 | XtFree((char*)info); | |||
| 286 | } | |||
| 287 | ||||
| 288 | static void | |||
| 289 | XawTipRealize(Widget w, Mask *mask, XSetWindowAttributes *attr) | |||
| 290 | { | |||
| 291 | TipWidget tip = (TipWidget)w; | |||
| 292 | ||||
| 293 | if (tip->tip.backing_store == Always2 || | |||
| 294 | tip->tip.backing_store == NotUseful0 || | |||
| 295 | tip->tip.backing_store == WhenMapped1) { | |||
| 296 | *mask |= CWBackingStore(1L<<6); | |||
| 297 | attr->backing_store = tip->tip.backing_store; | |||
| 298 | } | |||
| 299 | else | |||
| 300 | *mask &= ~CWBackingStore(1L<<6); | |||
| 301 | *mask |= CWOverrideRedirect(1L<<9); | |||
| 302 | attr->override_redirect = True1; | |||
| 303 | ||||
| 304 | XtWindow(w)((w)->core.window) = XCreateWindow(DisplayOfScreen(XtScreen(w))((((w)->core.screen))->display), | |||
| 305 | RootWindowOfScreen(XtScreen(w))((((w)->core.screen))->root), | |||
| 306 | XtX(w)(((RectObj)w)->rectangle.x), XtY(w)(((RectObj)w)->rectangle.y), | |||
| 307 | XtWidth(w)(((RectObj)w)->rectangle.width) ? XtWidth(w)(((RectObj)w)->rectangle.width) : 1, | |||
| 308 | XtHeight(w)(((RectObj)w)->rectangle.height) ? XtHeight(w)(((RectObj)w)->rectangle.height) : 1, | |||
| 309 | XtBorderWidth(w)(((RectObj)w)->rectangle.border_width), | |||
| 310 | DefaultDepthOfScreen(XtScreen(w))((((w)->core.screen))->root_depth), | |||
| 311 | InputOutput1, | |||
| 312 | (Visual *)CopyFromParent0L, | |||
| 313 | *mask, attr); | |||
| 314 | } | |||
| 315 | ||||
| 316 | static void | |||
| 317 | XawTipExpose(Widget w, XEvent *event, Region region) | |||
| 318 | { | |||
| 319 | TipWidget tip = (TipWidget)w; | |||
| 320 | GC gc = tip->tip.gc; | |||
| 321 | char *nl, *label = tip->tip.label; | |||
| 322 | Position y = tip->tip.top_margin + tip->tip.font->max_bounds.ascent; | |||
| 323 | int len; | |||
| 324 | ||||
| 325 | if (tip->tip.display_list) | |||
| 326 | XawRunDisplayList(w, tip->tip.display_list, event, region); | |||
| 327 | ||||
| 328 | if (tip->tip.international == True1) { | |||
| 329 | Position ksy = tip->tip.top_margin; | |||
| 330 | XFontSetExtents *ext = XExtentsOfFontSet(tip->tip.fontset); | |||
| 331 | ||||
| 332 | ksy += XawAbs(ext->max_ink_extent.y)((ext->max_ink_extent.y) < 0 ? -(ext->max_ink_extent .y) : (ext->max_ink_extent.y)); | |||
| 333 | ||||
| 334 | while ((nl = index(label, '\n')) != NULL((void*)0)) { | |||
| 335 | XmbDrawString(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), tip->tip.fontset, | |||
| 336 | gc, tip->tip.left_margin, ksy, label, | |||
| 337 | (int)(nl - label)); | |||
| 338 | ksy += ext->max_ink_extent.height; | |||
| 339 | label = nl + 1; | |||
| 340 | } | |||
| 341 | len = strlen(label); | |||
| 342 | if (len) | |||
| 343 | XmbDrawString(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), tip->tip.fontset, gc, | |||
| 344 | tip->tip.left_margin, ksy, label, len); | |||
| 345 | } | |||
| 346 | else { | |||
| 347 | while ((nl = index(label, '\n')) != NULL((void*)0)) { | |||
| 348 | if (tip->tip.encoding) | |||
| 349 | XDrawString16(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), gc, | |||
| 350 | tip->tip.left_margin, y, | |||
| 351 | (XChar2b*)label, (int)(nl - label) >> 1); | |||
| 352 | else | |||
| 353 | XDrawString(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), gc, | |||
| 354 | tip->tip.left_margin, y, label, (int)(nl - label)); | |||
| 355 | y += tip->tip.font->max_bounds.ascent + | |||
| 356 | tip->tip.font->max_bounds.descent; | |||
| 357 | label = nl + 1; | |||
| 358 | } | |||
| 359 | len = strlen(label); | |||
| 360 | if (len) { | |||
| 361 | if (tip->tip.encoding) | |||
| 362 | XDrawString16(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), gc, | |||
| 363 | tip->tip.left_margin, y, (XChar2b*)label, len >> 1); | |||
| 364 | else | |||
| 365 | XDrawString(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), gc, | |||
| 366 | tip->tip.left_margin, y, label, len); | |||
| 367 | } | |||
| 368 | } | |||
| 369 | } | |||
| 370 | ||||
| 371 | /*ARGSUSED*/ | |||
| 372 | static Boolean | |||
| 373 | XawTipSetValues(Widget current, Widget request, Widget cnew, | |||
| 374 | ArgList args, Cardinal *num_args) | |||
| 375 | { | |||
| 376 | TipWidget curtip = (TipWidget)current; | |||
| 377 | TipWidget newtip = (TipWidget)cnew; | |||
| 378 | Boolean redisplay = False0; | |||
| 379 | ||||
| 380 | if (curtip->tip.font->fid != newtip->tip.font->fid || | |||
| 381 | curtip->tip.foreground != newtip->tip.foreground) { | |||
| 382 | XGCValues values; | |||
| 383 | ||||
| 384 | values.foreground = newtip->tip.foreground; | |||
| 385 | values.background = newtip->core.background_pixel; | |||
| 386 | values.font = newtip->tip.font->fid; | |||
| 387 | values.graphics_exposures = False0; | |||
| 388 | XtReleaseGC(cnew, curtip->tip.gc); | |||
| 389 | newtip->tip.gc = XtAllocateGC(cnew, 0, GCForeground(1L<<2) | GCBackground(1L<<3) | | |||
| 390 | GCFont(1L<<14) | GCGraphicsExposures(1L<<16), &values, | |||
| 391 | GCFont(1L<<14), 0); | |||
| 392 | redisplay = True1; | |||
| 393 | } | |||
| 394 | if (curtip->tip.display_list != newtip->tip.display_list) | |||
| 395 | redisplay = True1; | |||
| 396 | ||||
| 397 | return (redisplay); | |||
| 398 | } | |||
| 399 | ||||
| 400 | static void | |||
| 401 | TipLayout(XawTipInfo *info) | |||
| 402 | { | |||
| 403 | XFontStruct *fs = info->tip->tip.font; | |||
| 404 | int width = 0, height; | |||
| 405 | char *nl, *label = info->tip->tip.label; | |||
| 406 | ||||
| 407 | if (info->tip->tip.international == True1) { | |||
| 408 | XFontSet fset = info->tip->tip.fontset; | |||
| 409 | XFontSetExtents *ext = XExtentsOfFontSet(fset); | |||
| 410 | ||||
| 411 | height = ext->max_ink_extent.height; | |||
| 412 | if ((nl = index(label, '\n')) != NULL((void*)0)) { | |||
| 413 | /*CONSTCOND*/ | |||
| 414 | while (True1) { | |||
| 415 | int w = XmbTextEscapement(fset, label, (int)(nl - label)); | |||
| 416 | ||||
| 417 | if (w > width) | |||
| 418 | width = w; | |||
| 419 | if (*nl == '\0') | |||
| 420 | break; | |||
| 421 | label = nl + 1; | |||
| 422 | if (*label) | |||
| 423 | height += ext->max_ink_extent.height; | |||
| 424 | if ((nl = index(label, '\n')) == NULL((void*)0)) | |||
| 425 | nl = index(label, '\0'); | |||
| 426 | } | |||
| 427 | } | |||
| 428 | else | |||
| 429 | width = XmbTextEscapement(fset, label, strlen(label)); | |||
| 430 | } | |||
| 431 | else { | |||
| 432 | height = fs->max_bounds.ascent + fs->max_bounds.descent; | |||
| 433 | if ((nl = index(label, '\n')) != NULL((void*)0)) { | |||
| 434 | /*CONSTCOND*/ | |||
| 435 | while (True1) { | |||
| 436 | int w = info->tip->tip.encoding ? | |||
| 437 | XTextWidth16(fs, (XChar2b*)label, (int)(nl - label) >> 1) : | |||
| 438 | XTextWidth(fs, label, (int)(nl - label)); | |||
| 439 | if (w > width) | |||
| 440 | width = w; | |||
| 441 | if (*nl == '\0') | |||
| 442 | break; | |||
| 443 | label = nl + 1; | |||
| 444 | if (*label) | |||
| 445 | height += fs->max_bounds.ascent + fs->max_bounds.descent; | |||
| 446 | if ((nl = index(label, '\n')) == NULL((void*)0)) | |||
| 447 | nl = index(label, '\0'); | |||
| 448 | } | |||
| 449 | } | |||
| 450 | else | |||
| 451 | width = info->tip->tip.encoding ? | |||
| 452 | XTextWidth16(fs, (XChar2b*)label, strlen(label) >> 1) : | |||
| 453 | XTextWidth(fs, label, strlen(label)); | |||
| 454 | } | |||
| 455 | XtWidth(info->tip)(((RectObj)info->tip)->rectangle.width) = width + info->tip->tip.left_margin + | |||
| 456 | info->tip->tip.right_margin; | |||
| 457 | XtHeight(info->tip)(((RectObj)info->tip)->rectangle.height) = height + info->tip->tip.top_margin + | |||
| 458 | info->tip->tip.bottom_margin; | |||
| 459 | } | |||
| 460 | ||||
| 461 | #define DEFAULT_TIP_Y_OFFSET12 12 | |||
| 462 | static void | |||
| 463 | TipPosition(XawTipInfo *info) | |||
| 464 | { | |||
| 465 | Window r, c; | |||
| 466 | int rx, ry, wx, wy; | |||
| 467 | unsigned mask; | |||
| 468 | Position x, y; | |||
| 469 | ||||
| 470 | XQueryPointer(XtDisplay((Widget)info->tip)((((Widget)info->tip)->core.screen)->display), XtWindow((Widget)info->tip)(((Widget)info->tip)->core.window), | |||
| 471 | &r, &c, &rx, &ry, &wx, &wy, &mask); | |||
| 472 | x = rx - (XtWidth(info->tip)(((RectObj)info->tip)->rectangle.width) >> 1); | |||
| 473 | y = ry + DEFAULT_TIP_Y_OFFSET12; | |||
| 474 | ||||
| 475 | if (x >= 0) { | |||
| 476 | int scr_width = WidthOfScreen(XtScreen(info->tip))((((info->tip)->core.screen))->width); | |||
| 477 | ||||
| 478 | if (x + XtWidth(info->tip)(((RectObj)info->tip)->rectangle.width) + XtBorderWidth(info->tip)(((RectObj)info->tip)->rectangle.border_width) > scr_width) | |||
| 479 | x = scr_width - XtWidth(info->tip)(((RectObj)info->tip)->rectangle.width) - XtBorderWidth(info->tip)(((RectObj)info->tip)->rectangle.border_width); | |||
| 480 | } | |||
| 481 | if (x < 0) | |||
| 482 | x = 0; | |||
| 483 | if (y >= 0) { | |||
| 484 | int scr_height = HeightOfScreen(XtScreen(info->tip))((((info->tip)->core.screen))->height); | |||
| 485 | ||||
| 486 | if (y + XtHeight(info->tip)(((RectObj)info->tip)->rectangle.height) + XtBorderWidth(info->tip)(((RectObj)info->tip)->rectangle.border_width) > scr_height) | |||
| 487 | y -= XtHeight(info->tip)(((RectObj)info->tip)->rectangle.height) + XtBorderWidth(info->tip)(((RectObj)info->tip)->rectangle.border_width) + | |||
| 488 | (DEFAULT_TIP_Y_OFFSET12 << 1); | |||
| 489 | } | |||
| 490 | if (y < 0) | |||
| 491 | y = 0; | |||
| 492 | ||||
| 493 | XMoveResizeWindow(XtDisplay(info->tip)(((info->tip)->core.screen)->display), XtWindow(info->tip)((info->tip)->core.window), | |||
| 494 | (int)(XtX(info->tip)(((RectObj)info->tip)->rectangle.x) = x), (int)(XtY(info->tip)(((RectObj)info->tip)->rectangle.y) = y), | |||
| 495 | (unsigned)XtWidth(info->tip)(((RectObj)info->tip)->rectangle.width), (unsigned)XtHeight(info->tip)(((RectObj)info->tip)->rectangle.height)); | |||
| 496 | } | |||
| 497 | ||||
| 498 | static XawTipInfo * | |||
| 499 | CreateTipInfo(Widget w) | |||
| 500 | { | |||
| 501 | XawTipInfo *info = XtNew(XawTipInfo)((XawTipInfo *) XtMalloc((unsigned) sizeof(XawTipInfo))); | |||
| 502 | Widget shell = w; | |||
| 503 | ||||
| 504 | info->screen = XtScreen(w)((w)->core.screen); | |||
| 505 | ||||
| 506 | while (XtParent(shell)((shell)->core.parent)) | |||
| 507 | shell = XtParent(shell)((shell)->core.parent); | |||
| 508 | ||||
| 509 | info->tip = (TipWidget)XtCreateWidget("tip", tipWidgetClass, shell, NULL((void*)0), 0); | |||
| 510 | XtRealizeWidget((Widget)info->tip); | |||
| 511 | info->widget = NULL((void*)0); | |||
| 512 | info->mapped = False0; | |||
| 513 | info->next = NULL((void*)0); | |||
| 514 | XtAddEventHandler(shell, KeyPressMask(1L<<0), False0, TipShellEventHandler, | |||
| 515 | (XtPointer)NULL((void*)0)); | |||
| 516 | ||||
| 517 | return (info); | |||
| 518 | } | |||
| 519 | ||||
| 520 | static XawTipInfo * | |||
| 521 | FindTipInfo(Widget w) | |||
| 522 | { | |||
| 523 | XawTipInfo *ptip, *tip = first_tip; | |||
| 524 | Screen *screen = XtScreenOfObject(w); | |||
| 525 | ||||
| 526 | if (tip == NULL((void*)0)) | |||
| 527 | return (first_tip = tip = CreateTipInfo(w)); | |||
| 528 | ||||
| 529 | for (ptip = tip; tip; ptip = tip, tip = tip->next) | |||
| 530 | if (tip->screen == screen) | |||
| 531 | return (tip); | |||
| 532 | ||||
| 533 | return (ptip->next = CreateTipInfo(w)); | |||
| 534 | } | |||
| 535 | ||||
| 536 | static void | |||
| 537 | ResetTip(XawTipInfo *info, Boolint add_timeout) | |||
| 538 | { | |||
| 539 | if (info->tip->tip.timer) { | |||
| 540 | XtRemoveTimeOut(info->tip->tip.timer); | |||
| 541 | info->tip->tip.timer = 0; | |||
| 542 | } | |||
| 543 | if (info->mapped) { | |||
| 544 | XtRemoveGrab(XtParent((Widget)info->tip)(((Widget)info->tip)->core.parent)); | |||
| 545 | XUnmapWindow(XtDisplay((Widget)info->tip)((((Widget)info->tip)->core.screen)->display), XtWindow((Widget)info->tip)(((Widget)info->tip)->core.window)); | |||
| 546 | info->mapped = False0; | |||
| 547 | } | |||
| 548 | if (add_timeout) { | |||
| 549 | info->tip->tip.timer = | |||
| 550 | XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)info->tip), | |||
| 551 | info->tip->tip.timeout, TipTimeoutCallback, | |||
| 552 | (XtPointer)info); | |||
| 553 | } | |||
| 554 | } | |||
| 555 | ||||
| 556 | static void | |||
| 557 | TipTimeoutCallback(XtPointer closure, XtIntervalId *id) | |||
| 558 | { | |||
| 559 | XawTipInfo *info = (XawTipInfo*)closure; | |||
| 560 | Arg args[3]; | |||
| 561 | ||||
| 562 | info->tip->tip.label = NULL((void*)0); | |||
| 563 | info->tip->tip.international = False0; | |||
| 564 | info->tip->tip.encoding = 0; | |||
| 565 | info->tip->tip.timer = 0; | |||
| 566 | XtSetArg(args[0], XtNtip, &info->tip->tip.label)((void)( (args[0]).name = ("tip"), (args[0]).value = (XtArgVal )(&info->tip->tip.label) )); | |||
| 567 | XtSetArg(args[1], XtNinternational, &info->tip->tip.international)((void)( (args[1]).name = ("international"), (args[1]).value = (XtArgVal)(&info->tip->tip.international) )); | |||
| 568 | XtSetArg(args[2], XtNencoding, &info->tip->tip.encoding)((void)( (args[2]).name = ("encoding"), (args[2]).value = (XtArgVal )(&info->tip->tip.encoding) )); | |||
| 569 | XtGetValues(info->widget, args, 3); | |||
| 570 | ||||
| 571 | if (info->tip->tip.label) { | |||
| 572 | TipLayout(info); | |||
| 573 | TipPosition(info); | |||
| 574 | XMapRaised(XtDisplay((Widget)info->tip)((((Widget)info->tip)->core.screen)->display), XtWindow((Widget)info->tip)(((Widget)info->tip)->core.window)); | |||
| 575 | XtAddGrab(XtParent((Widget)info->tip)(((Widget)info->tip)->core.parent), True1, True1); | |||
| 576 | info->mapped = True1; | |||
| 577 | } | |||
| 578 | } | |||
| 579 | ||||
| 580 | /*ARGSUSED*/ | |||
| 581 | static void | |||
| 582 | TipShellEventHandler(Widget w, XtPointer client_data, XEvent *event, | |||
| 583 | Boolean *continue_to_dispatch) | |||
| 584 | { | |||
| 585 | ResetTip(FindTipInfo(w), False0); | |||
| 586 | } | |||
| 587 | ||||
| 588 | /*ARGSUSED*/ | |||
| 589 | static void | |||
| 590 | TipEventHandler(Widget w, XtPointer client_data, XEvent *event, | |||
| 591 | Boolean *continue_to_dispatch) | |||
| 592 | { | |||
| 593 | XawTipInfo *info = FindTipInfo(w); | |||
| 594 | Boolean add_timeout; | |||
| 595 | ||||
| 596 | if (info->widget != w) { | |||
| 597 | ResetTip(info, False0); | |||
| 598 | info->widget = w; | |||
| 599 | } | |||
| 600 | ||||
| 601 | switch (event->type) { | |||
| 602 | case EnterNotify7: | |||
| 603 | add_timeout = True1; | |||
| 604 | break; | |||
| 605 | case MotionNotify6: | |||
| 606 | /* If any button is pressed, timer is 0 */ | |||
| 607 | if (info->mapped) | |||
| 608 | return; | |||
| 609 | add_timeout = info->tip->tip.timer != 0; | |||
| 610 | break; | |||
| 611 | default: | |||
| 612 | add_timeout = False0; | |||
| 613 | break; | |||
| 614 | } | |||
| 615 | ResetTip(info, add_timeout); | |||
| 616 | } | |||
| 617 | ||||
| 618 | /* | |||
| 619 | * Public routines | |||
| 620 | */ | |||
| 621 | void | |||
| 622 | XawTipEnable(Widget w) | |||
| 623 | { | |||
| 624 | XtAddEventHandler(w, TIP_EVENT_MASK((1L<<2) | (1L<<3) | (1L<<6) | (1L<<13 ) | (1L<<0) | (1L<<1) | (1L<<4) | (1L<< 5)), False0, TipEventHandler, | |||
| 625 | (XtPointer)NULL((void*)0)); | |||
| 626 | } | |||
| 627 | ||||
| 628 | void | |||
| 629 | XawTipDisable(Widget w) | |||
| 630 | { | |||
| 631 | XawTipInfo *info = FindTipInfo(w); | |||
| 632 | ||||
| 633 | XtRemoveEventHandler(w, TIP_EVENT_MASK((1L<<2) | (1L<<3) | (1L<<6) | (1L<<13 ) | (1L<<0) | (1L<<1) | (1L<<4) | (1L<< 5)), False0, TipEventHandler, | |||
| 634 | (XtPointer)NULL((void*)0)); | |||
| 635 | if (info->widget == w) | |||
| 636 | ResetTip(info, False0); | |||
| 637 | } |