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')(strchr((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')(strchr((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')(strchr((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')(strchr((label),('\n')))) == NULL((void*)0)) | ||
425 | nl = index(label, '\0')(strchr((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')(strchr((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')(strchr((label),('\n')))) == NULL((void*)0)) | ||
447 | nl = index(label, '\0')(strchr((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 | } |