~ubuntu-branches/ubuntu/jaunty/texlive-bin/jaunty

« back to all changes in this revision

Viewing changes to build/source/texk/xdvik/gui/Tip.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2008-06-26 23:14:59 UTC
  • mfrom: (2.1.30 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080626231459-y02rjsrgtafu83yr
Tags: 2007.dfsg.2-3
add missing source roadmap.fig of roadmap.eps in fontinst documentation
(Closes: #482915) (urgency medium due to RC bug)
(new patch add-missing-fontinst-source)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2001-2004 Marcin Dalecki and others
 
3
 *
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 
5
 * of this software and associated documentation files (the "Software"), to
 
6
 * deal in the Software without restriction, including without limitation the
 
7
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 
8
 * sell copies of the Software, and to permit persons to whom the Software is
 
9
 * 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
 * PAUL VOJTA OR ANY OTHER AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY CLAIM,
 
18
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
19
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
20
 * OTHER DEALINGS IN THE SOFTWARE.
 
21
 *
 
22
 */
 
23
 
 
24
#include "xdvi-config.h"
 
25
#include "xdvi.h"
 
26
 
 
27
#include "Tip.h"
 
28
#include "xdvi-debug.h"
 
29
#include "util.h"
 
30
 
 
31
#ifdef MOTIF /* needed for `make depend' */
 
32
 
 
33
#ifndef UNUSED
 
34
#define UNUSED(x) ((void)(x))
 
35
#endif
 
36
 
 
37
#include <signal.h>
 
38
#include <stdio.h>
 
39
#include <stdlib.h>
 
40
 
 
41
#include <X11/IntrinsicP.h>
 
42
#include <X11/StringDefs.h>
 
43
#include <Xm/XmP.h>
 
44
 
 
45
#include <Xm/PushB.h>
 
46
#include <X11/ShellP.h>
 
47
 
 
48
#define TIP_NUM 1024 /* FIXME: remove this hard-coded value */
 
49
 
 
50
typedef struct {
 
51
    int __empty;
 
52
} TipClassPart;
 
53
 
 
54
/* Full class record declaration */
 
55
typedef struct _TipClassRec {
 
56
    CoreClassPart core_class;
 
57
    CompositeClassPart composite_class;
 
58
    ShellClassPart shell_class;
 
59
    OverrideShellClassPart override_shell_class;
 
60
    TipClassPart tip_class;
 
61
} TipClassRec;
 
62
 
 
63
/* keep information about each widget we are keeping track of */
 
64
struct tip_context {
 
65
    Widget watched;             /* the widget we are watching */
 
66
    Window window;              /* Window of the object we are monitoring */
 
67
    TipWidget tw;               /* pointer back to the tip widget */
 
68
    Position abs_x, abs_y;
 
69
    Boolean active;             /* if False, tip is suppressed */
 
70
    char *text;                 /* text to display */
 
71
    short size;                 /* its size */
 
72
};
 
73
 
 
74
/* New fields for the widget record */
 
75
typedef struct {
 
76
    /* resources */
 
77
    Pixel foreground;
 
78
    XFontSet fontset;           /* the font for text in box */
 
79
    int waitPeriod;             /* the delay resource - pointer must be
 
80
                                 * in watched widget this long before
 
81
                                 * help is popped up - in millisecs
 
82
                                 */
 
83
    unsigned int cwp;           /* after help is popped down - normal
 
84
                                 * wait period is cancelled for this
 
85
                                 * period - in millisecs
 
86
                                 */
 
87
 
 
88
    /* private state */
 
89
    struct tip_context twl[TIP_NUM];    /* list of widgets we are liteClue-ing */
 
90
    Cardinal nr_twl;            /* number of widgets we have attached */
 
91
    Dimension font_width;       /* width of '1' character */
 
92
    Dimension font_height;      /* height of font, rows are spaced using this */
 
93
    Dimension font_baseline;    /* relative displacement to baseline from top */
 
94
    GC text_GC;                 /* for drawing text */
 
95
    XtIntervalId tid;           /* holds timer id */
 
96
    Widget isup;                /* the help popup is up on this widget */
 
97
    Time HelpPopDownTime;       /* the time at which help popup
 
98
                                   was popped down */
 
99
} TipPart;
 
100
 
 
101
/*
 
102
 * Full instance record declaration
 
103
 */
 
104
typedef struct _TipRec {
 
105
    CorePart core;
 
106
    CompositePart composite;
 
107
    ShellPart shell;
 
108
    OverrideShellPart override;
 
109
    TipPart tip;
 
110
} TipRec;
 
111
 
 
112
#define CheckWidgetClass(routine) \
 
113
        if (XtClass(w) != tipWidgetClass) \
 
114
                wrong_widget(routine)
 
115
 
 
116
static void initialize(Widget, Widget, ArgList, Cardinal *);
 
117
static Boolean set_values(Widget, Widget, Widget, ArgList, Cardinal *);
 
118
static void destroy(Widget);
 
119
 
 
120
/*
 
121
 * Widget resources: eg to set tip box background: *tipShell.background: yellow.
 
122
 */
 
123
 
 
124
#define offset(field) XtOffsetOf(TipRec, field)
 
125
static XtResource resources[] = {
 
126
    {XtNforeground, XtCForeground,
 
127
     XtRPixel, sizeof(Pixel), offset(tip.foreground),
 
128
     XtRString, "black"},
 
129
    {XtNfontSet, XtCFontSet,
 
130
     XtRFontSet, sizeof(XFontSet), offset(tip.fontset),
 
131
     XtRString, "fixed"},
 
132
    {XmNwaitPeriod, XmCWaitPeriod,
 
133
     XtRInt, sizeof(int), offset(tip.waitPeriod),
 
134
     XtRImmediate, (XtPointer) 800},
 
135
    {XmNcancelWaitPeriod, XmCCancelWaitPeriod,
 
136
     XtRInt, sizeof(int), offset(tip.cwp),
 
137
     XtRImmediate, (XtPointer) 250},
 
138
};
 
139
#undef offset
 
140
 
 
141
TipClassRec tipClassRec = {
 
142
    {
 
143
     /* superclass           */ (WidgetClass) & overrideShellClassRec,
 
144
     /* class_name           */ "Tip",
 
145
     /* widget size          */ (Cardinal) sizeof(TipRec),
 
146
     /* class_init           */ NULL,
 
147
     /* class_part_init      */ (XtWidgetClassProc) NULL,
 
148
     /* class_inited         */ (XtEnum) FALSE,
 
149
     /* initialize           */ (XtInitProc) initialize,
 
150
     /* init_hook            */ (XtArgsProc) NULL,
 
151
     /* realize              */ XtInheritRealize,
 
152
     /* actions              */ (XtActionList) 0,
 
153
     /* num_actions          */ (Cardinal) 0,
 
154
     /* resources            */ (XtResourceList) resources,
 
155
     /* num_resources        */ (Cardinal) XtNumber(resources),
 
156
     /* xrm_class            */ NULLQUARK,
 
157
     /* compress_motion      */ TRUE,
 
158
     /* compress_exposur     */ (XtEnum) FALSE,
 
159
     /* compress enterleave  */ TRUE,
 
160
     /* visibility_interest  */ FALSE,
 
161
     /* destroy              */ destroy,
 
162
     /* resize               */ XtInheritResize,
 
163
     /* expose,              */ XtInheritExpose,
 
164
     /* set_values           */ (XtSetValuesFunc) set_values,
 
165
     /* set_values_hook      */ (XtArgsFunc) NULL,
 
166
     /* set_values_almost    */ XtInheritSetValuesAlmost,
 
167
     /* get_values_hook      */ (XtArgsProc) NULL,
 
168
     /* accept_focus         */ XtInheritAcceptFocus,
 
169
     /* version              */ XtVersion,
 
170
     /* callback_private     */ (XtPointer) NULL,
 
171
     /* translations         */ XtInheritTranslations,
 
172
     /* query_geometry       */ XtInheritQueryGeometry,
 
173
     /* display_accelerator  */ XtInheritDisplayAccelerator,
 
174
     /* extension            */ (XtPointer) 0,
 
175
     },
 
176
    /* composite part */
 
177
    {
 
178
     /* geometry_manager     */ XtInheritGeometryManager,
 
179
     /* change_managed       */ XtInheritChangeManaged,
 
180
     /* insert_child         */ XtInheritInsertChild,
 
181
     /* delete_child         */ XtInheritDeleteChild,
 
182
     /* extension            */ NULL
 
183
     },
 
184
    /* Shell */
 
185
    {
 
186
     (XtPointer) NULL,
 
187
     },
 
188
    /* Override Shell */
 
189
    {
 
190
     0,
 
191
     },
 
192
    /* tip */
 
193
    {
 
194
     0,
 
195
     }
 
196
};
 
197
 
 
198
WidgetClass tipWidgetClass = (WidgetClass) & tipClassRec;
 
199
 
 
200
/*
 
201
 * The font_information is derived.
 
202
 */
 
203
static void compute_font_info(TipWidget cw)
 
204
{
 
205
    XRectangle ink;
 
206
    XRectangle logical;
 
207
 
 
208
    if (!cw->tip.fontset)
 
209
        return;
 
210
    XmbTextExtents(cw->tip.fontset, "1", 1, &ink, &logical);
 
211
 
 
212
    cw->tip.font_baseline = -logical.y; /* y offset from top to baseline, don't
 
213
                                           know why this is returned as
 
214
                                           negative */
 
215
 
 
216
    cw->tip.font_width = logical.width; /* the width and height of the object */
 
217
 
 
218
    cw->tip.font_height = logical.height;
 
219
    TRACE_GUI((stderr, "baseline: %d, width: %d, height: %d\n",
 
220
               cw->tip.font_baseline, cw->tip.font_width, cw->tip.font_height));
 
221
}
 
222
 
 
223
/*
 
224
 * Creates the various graphic contexts we will need.
 
225
 */
 
226
static void create_GC(TipWidget cw)
 
227
{
 
228
    XtGCMask valuemask;
 
229
    XGCValues myXGCV;
 
230
 
 
231
    valuemask = GCForeground | GCBackground | GCFillStyle;
 
232
    myXGCV.foreground = cw->tip.foreground;
 
233
    myXGCV.background = cw->core.background_pixel;
 
234
    myXGCV.fill_style = FillSolid;
 
235
 
 
236
    if (cw->tip.text_GC)
 
237
        XtReleaseGC((Widget) cw, cw->tip.text_GC);
 
238
    cw->tip.text_GC = XtGetGC((Widget) cw, valuemask, &myXGCV);
 
239
}
 
240
 
 
241
/*
 
242
 * A routine to halt execution and force a core dump for debugging analysis
 
243
 * when a public routine is called with the wrong class of widget.
 
244
 */
 
245
 
 
246
static void wrong_widget(char *routine)
 
247
{
 
248
    XDVI_ABORT((stderr, "Wrong class of widget passed to %s", routine));
 
249
}
 
250
 
 
251
/*
 
252
 * Global list of shells for tips that are in use.
 
253
 */
 
254
 
 
255
static TipWidget *shells = NULL;
 
256
static int nr_shells = 0;
 
257
 
 
258
/****************************************************************************
 
259
 * Widget Methods
 
260
 */
 
261
 
 
262
static void initialize(Widget treq, Widget tnew, ArgList args,
 
263
                       Cardinal * nargs)
 
264
{
 
265
    TipWidget tw = (TipWidget) tnew;
 
266
 
 
267
    UNUSED(treq);
 
268
    UNUSED(args);
 
269
    UNUSED(nargs);
 
270
    
 
271
    tw->tip.text_GC = NULL;
 
272
    tw->tip.isup = NULL;
 
273
    tw->tip.HelpPopDownTime = 0;
 
274
    tw->tip.tid = (XtIntervalId) 0;
 
275
    tw->tip.nr_twl = 0;
 
276
    compute_font_info(tw);
 
277
    create_GC(tw);
 
278
 
 
279
    /* Add to our list of tip shells.
 
280
     */
 
281
    if (!shells)
 
282
        shells = (TipWidget *)XtMalloc(sizeof(TipWidget));
 
283
    else
 
284
        shells = (TipWidget *)XtRealloc((char *)shells,
 
285
                                        sizeof(TipWidget) * (nr_shells + 1));
 
286
 
 
287
    shells[nr_shells++] = tw;
 
288
}
 
289
 
 
290
static Boolean set_values(Widget _current, Widget _request, Widget _new,
 
291
                          ArgList args, Cardinal * nargs)
 
292
{
 
293
    TipWidget cw_new = (TipWidget) _new;
 
294
    TipWidget cw_cur = (TipWidget) _current;
 
295
 
 
296
    UNUSED(_request);
 
297
    UNUSED(args);
 
298
    UNUSED(nargs);
 
299
    
 
300
    /* values of cw_new->tip.cwp and
 
301
       cw_new->tip.waitPeriod are accepted without checking */
 
302
 
 
303
    if (cw_new->tip.foreground != cw_cur->tip.foreground
 
304
        || cw_new->core.background_pixel !=
 
305
        cw_cur->core.background_pixel) {
 
306
        create_GC(cw_new);
 
307
    }
 
308
    return FALSE;
 
309
}
 
310
 
 
311
static void destroy(Widget w)
 
312
{
 
313
    TipWidget tw = (TipWidget) w;
 
314
    int i;
 
315
    Boolean copy = False;
 
316
 
 
317
    /* Remove this tip shell from our global list.
 
318
     */
 
319
    for (i = 0; i < nr_shells; ++i) {
 
320
        if (shells[i] == tw) {
 
321
            copy = True;
 
322
            --nr_shells;
 
323
        }
 
324
        if (copy && nr_shells)
 
325
            shells[i] = shells[i + 1];
 
326
    }
 
327
    if (!nr_shells) {
 
328
        XtFree((char *) shells);
 
329
        shells = NULL;
 
330
    }
 
331
}
 
332
 
 
333
/****************************************************************************
 
334
 * Event handlers
 
335
 */
 
336
 
 
337
/* callback to popup the tip window
 
338
 */
 
339
static void timeout_event(XtPointer client_data, XtIntervalId *id)
 
340
{
 
341
#define HBorderPix 3
 
342
#define VBorderPix 3
 
343
    struct tip_context *obj = (struct tip_context *) client_data;
 
344
    TipWidget tw = obj->tw;
 
345
    Position abs_x, abs_y;
 
346
    int ptr_x, ptr_y;
 
347
 
 
348
    XRectangle ink;
 
349
    XRectangle logical;
 
350
    Position w_height, w_width;
 
351
    Widget w;
 
352
    
 
353
    UNUSED(id);
 
354
 
 
355
    TRACE_GUI((stderr, "timeout called!"));
 
356
    
 
357
    if (tw->tip.tid == (XtIntervalId) 0)
 
358
        return;                 /* timeout was removed but callback happened
 
359
                                   anyway */
 
360
 
 
361
    tw->tip.tid = (XtIntervalId) 0;
 
362
    if (obj->active == False)
 
363
        return;
 
364
 
 
365
    w = obj->watched;
 
366
 
 
367
    if (!XtIsManaged(w))
 
368
        return;
 
369
 
 
370
    { /* perform additional check that pointer is really still over the widget;
 
371
         else, tooltips will sometimes pop up if window had received an Enter
 
372
         event before (for some reason, not all Enters are followed by Leaves).
 
373
         This is especially apparent when running xdvi from a remote display over
 
374
         a slow connection.
 
375
       */
 
376
        Window root, child;
 
377
        int root_x, root_y;
 
378
        unsigned int keys_buttons;
 
379
        if (!XQueryPointer(DISP, RootWindowOfScreen(SCRN), &root, &child,
 
380
                           &root_x, &root_y, &ptr_x, &ptr_y, &keys_buttons))
 
381
            return;
 
382
 
 
383
        TRACE_GUI((stderr, "Pointerlocate: %d, %d", root_x, root_y));
 
384
        
 
385
        XtVaGetValues(w, XtNheight, &w_height, XtNwidth, &w_width, NULL);
 
386
        XtTranslateCoords(w, 0, 0, &abs_x, &abs_y);
 
387
        
 
388
        TRACE_GUI((stderr, "Window: %d,%d - %d,%d",
 
389
                   abs_x, abs_y, abs_x + w_width, abs_y + w_height));
 
390
        
 
391
        if (root_x < abs_x || root_x > abs_x + w_width
 
392
            || root_y < abs_y || root_y > abs_y + w_height) {
 
393
            TRACE_GUI((stderr, "not really over toolbutton - returning!"));
 
394
            return;
 
395
        }
 
396
    }
 
397
 
 
398
    /* position just below the pointer
 
399
     * (NOT the widget, in case the widget is large!)
 
400
     */
 
401
    ptr_y += 20;
 
402
/*     abs_x += w_width / 2; */
 
403
/*     abs_y += w_height; */
 
404
    
 
405
    XmbTextExtents(tw->tip.fontset, obj->text, obj->size, &ink, &logical);
 
406
 
 
407
    XtRealizeWidget((Widget)tw); /* so that setting the size etc. works */
 
408
        
 
409
    XtResizeWidget((Widget) tw,
 
410
                   2 * HBorderPix + logical.width,
 
411
                   2 * VBorderPix + tw->tip.font_height,
 
412
                   tw->core.border_width);
 
413
    TRACE_GUI((stderr, "Popup size: %d x %d (hborder: %d, vborder: %d)\n",
 
414
               2 * HBorderPix + logical.width, 2 * VBorderPix + tw->tip.font_height,
 
415
               HBorderPix, VBorderPix));
 
416
    XtMoveWidget((Widget)tw, ptr_x, ptr_y);
 
417
 
 
418
    XtPopup((Widget) tw, XtGrabNone);
 
419
    tw->tip.isup = obj->watched;
 
420
 
 
421
    XmbDrawImageString(XtDisplay((Widget) tw),
 
422
                       XtWindow((Widget) tw),
 
423
                       tw->tip.fontset,
 
424
                       tw->tip.text_GC,
 
425
                       HBorderPix,
 
426
                       VBorderPix + tw->tip.font_baseline,
 
427
                       obj->text, obj->size);
 
428
}
 
429
 
 
430
/*
 
431
 * Pointer enters watched widget, set a timer to popup the help.
 
432
 */
 
433
static void enter(struct tip_context *obj, XEvent * xevent,
 
434
                  XtAppContext app)
 
435
{
 
436
    TipWidget tw = obj->tw;
 
437
    XEnterWindowEvent *event = &xevent->xcrossing;
 
438
    int current_waitPeriod;
 
439
 
 
440
    /* this doesn't help against the Enter/Leave problem mentioned above,
 
441
       so it's not related to Widget creation ... */
 
442
    if (!XtIsManaged(obj->watched)) {
 
443
        TRACE_GUI((stderr, "%s:%d: Not yet managed!", __FILE__, __LINE__));
 
444
        return;
 
445
    }
 
446
    
 
447
    TRACE_GUI((stderr, "%s:%d: Enter!", __FILE__, __LINE__));
 
448
    
 
449
    if (obj->active == False)
 
450
        return;
 
451
 
 
452
    /* check for two enters in a row - happens when widget is
 
453
       exposed under a pop-up */
 
454
    if (tw->tip.tid != (XtIntervalId) 0)
 
455
        return;
 
456
 
 
457
    if (event->mode != NotifyNormal)
 
458
        return;
 
459
 
 
460
    /* it seems that this makes the tooltips somewhat unpredictable (they
 
461
       don't show when hovering fast over several buttons, then staying on
 
462
       one button); disabled this for the time being. */
 
463
/*     if ((event->time - tw->tip.HelpPopDownTime) > tw->tip.cwp) */
 
464
/*      current_waitPeriod = tw->tip.waitPeriod; */
 
465
/*     else */
 
466
/*      current_waitPeriod = 0; */
 
467
 
 
468
/*     current_waitPeriod = tw->tip.waitPeriod; */
 
469
    current_waitPeriod =  resource.tooltips_wait_period;
 
470
    if (current_waitPeriod >= 0) {
 
471
        tw->tip.tid = XtAppAddTimeOut(app, current_waitPeriod, timeout_event,
 
472
                                      (XtPointer) obj);
 
473
    }
 
474
}
 
475
 
 
476
/*
 
477
 * Remove timer if its pending. Then popdown help.
 
478
 */
 
479
static void leave(struct tip_context *obj, XEvent * xevent)
 
480
{
 
481
    TipWidget tw = obj->tw;
 
482
    XEnterWindowEvent *event = &xevent->xcrossing;
 
483
 
 
484
    TRACE_GUI((stderr, "%s:%d: Leave!", __FILE__, __LINE__));
 
485
    
 
486
    if (tw->tip.tid != (XtIntervalId) 0) {
 
487
        if (globals.debug & DBG_EVENT)
 
488
            fprintf(stderr, "%s:%d: removing timeout %ld\n", __FILE__, __LINE__, tw->tip.tid);
 
489
        XtRemoveTimeOut(tw->tip.tid);
 
490
        tw->tip.tid = (XtIntervalId) 0;
 
491
    }
 
492
 
 
493
    if (obj->active == False)
 
494
        return;
 
495
 
 
496
    if (tw->tip.isup) {
 
497
        XtPopdown((Widget) tw);
 
498
        tw->tip.isup = NULL;
 
499
        tw->tip.HelpPopDownTime = event->time;
 
500
    }
 
501
}
 
502
 
 
503
/****************************************************************************
 
504
 * Public interface implementation.
 
505
 */
 
506
 
 
507
void TipAppHandle(XtAppContext app, XEvent *event)
 
508
{
 
509
    int i;
 
510
 
 
511
    if (!(event->type == EnterNotify
 
512
          || event->type == MotionNotify
 
513
          || event->type == LeaveNotify
 
514
          || event->type == ButtonPress)) {
 
515
        return;
 
516
    }
 
517
 
 
518
    for (i = 0; i < nr_shells; ++i) {
 
519
        unsigned int j;
 
520
 
 
521
        for (j = 0; j < shells[i]->tip.nr_twl; ++j) {
 
522
            if (event->xany.window == shells[i]->tip.twl[j].window) {
 
523
                if (event->type == EnterNotify)
 
524
                    enter(shells[i]->tip.twl + j, event, app);
 
525
                if (event->xany.type == LeaveNotify
 
526
                    || event->xany.type == MotionNotify /* FIXME: this doesn' work? */
 
527
                    /* might be useful to popdown tip when mouse is moved */
 
528
                    || event->xany.type == ButtonPress) {
 
529
                    leave(shells[i]->tip.twl + j, event);
 
530
                }
 
531
            }
 
532
        }
 
533
    }
 
534
}
 
535
 
 
536
/*
 
537
 * This has to replace the XtAppMainLoop in the application using
 
538
 * tooltips.
 
539
 */
 
540
void TipAppMainLoop(XtAppContext app)
 
541
{
 
542
    XEvent event;
 
543
 
 
544
    for (;;) {
 
545
        XtAppNextEvent(app, &event);
 
546
        TipAppHandle(app, &event);
 
547
        XtDispatchEvent(&event);
 
548
    }
 
549
}
 
550
 
 
551
/*
 
552
 * Add a widget to be watched for tooltips.
 
553
 *
 
554
 * This function must be called after the widget has been realized!
 
555
 * Further on please make sure that this function will not be called twice
 
556
 * for one button!
 
557
 *
 
558
 * w            - tip widget
 
559
 * watch        - the widget to give tips for
 
560
 * text         - pointer to tip text
 
561
 */
 
562
void TipAddWidget(Widget w, Widget watch, const String text)
 
563
{
 
564
#define ROUTINE "TipAddWidget"
 
565
    TipWidget tw = (TipWidget) w;
 
566
    int i;
 
567
 
 
568
    CheckWidgetClass(ROUTINE);  /* make sure we are called with a tip widget */
 
569
 
 
570
    /* Make internal resource available via resource.tooltips_wait_period(_bak) and
 
571
     * resource.show_tooltips.
 
572
     */
 
573
    resource.tooltips_wait_period_bak = resource.tooltips_wait_period = ABS(tw->tip.waitPeriod);
 
574
    if (tw->tip.waitPeriod < 0) {
 
575
        resource.show_tooltips = False;
 
576
    }
 
577
    else if (!resource.show_tooltips) {
 
578
        if (resource.tooltips_wait_period == 0)
 
579
            resource.tooltips_wait_period = -1;
 
580
        else
 
581
            resource.tooltips_wait_period = -resource.tooltips_wait_period;
 
582
    }
 
583
    
 
584
    for (i = 0; i < nr_shells; ++i)
 
585
        if (shells[i] == tw) {
 
586
            struct tip_context *obj;
 
587
 
 
588
            if (tw->tip.nr_twl >= TIP_NUM) {
 
589
                XDVI_FATAL((stderr, "Too many tip widgets, cannot add new tip"));
 
590
                return;
 
591
            }
 
592
            obj = tw->tip.twl + tw->tip.nr_twl;
 
593
            obj->text = XtNewString(text);
 
594
            obj->size = strlen(text);
 
595
            obj->watched = watch;
 
596
            obj->window = XtWindow(watch);
 
597
            obj->active = True;
 
598
            obj->tw = tw;
 
599
            tw->tip.nr_twl++;
 
600
        }
 
601
#undef ROUTINE
 
602
}
 
603
 
 
604
#else
 
605
/* silence `empty compilation unit' warnings */
 
606
static void bar(void); static void foo() { bar(); } static void bar(void) { foo(); }
 
607
#endif /* MOTIF */