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 | } |