00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 #include <unistd.h>
00112 #include <signal.h>
00113
00114 #include <X11/IntrinsicP.h>
00115 #include <X11/StringDefs.h>
00116 extern void RWC_xineramize( Display *,int,int,int,int,int *,int *) ;
00117
00118 #include "LiteClueP.h"
00119
00120 #include <stdio.h>
00121
00122 #if 0
00123 #define CheckWidgetClass(routine) \
00124 if (XtClass(w) != xcgLiteClueWidgetClass) \
00125 wrong_widget(routine)
00126
00127 #else
00128 #define CheckWidgetClass(routine) \
00129 if (XtClass(w) != xcgLiteClueWidgetClass) \
00130 return BADVALUE
00131 #endif
00132
00133
00134 static Boolean setValues( Widget _current, Widget _request, Widget _new, ArgList args, Cardinal * num_args);
00135 static void Initialize(Widget treq, Widget tnew, ArgList args, Cardinal *num_args);
00136 struct liteClue_context_str * alloc_liteClue_context(void);
00137
00138
00139 struct liteClue_context_str
00140 {
00141 ListThread next;
00142 Widget watched_w;
00143 XcgLiteClueWidget cw;
00144 Position abs_x, abs_y;
00145 Boolean sensitive;
00146 char * text;
00147 short text_size;
00148 };
00149
00150 void free_widget_context(XcgLiteClueWidget cw, struct liteClue_context_str * obj);
00151
00152
00153
00154
00155
00156 #define offset(field) XtOffsetOf(LiteClueRec, field)
00157 static XtResource resources[] =
00158 {
00159 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
00160 offset(liteClue.foreground), XtRString, "black"},
00161 #if XtSpecificationRelease < 5
00162 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
00163 offset(liteClue.font), XtRString,
00164 "-adobe-new century schoolbook-bold-r-normal-*-14-*-*-*-*-*-*-*"},
00165 #else
00166 {XtNfontSet, XtCFontSet, XtRFontSet, sizeof(XFontSet),
00167 offset(liteClue.fontset), XtRString, "-adobe-new century schoolbook-bold-r-normal-*-12-*"},
00168 #endif
00169 {XgcNwaitPeriod, XgcCWaitPeriod, XtRInt , sizeof(int),
00170 offset(liteClue.waitPeriod),XtRString, "500" },
00171
00172 {XgcNcancelWaitPeriod, XgcCCancelWaitPeriod, XtRInt , sizeof(int),
00173 offset(liteClue.cancelWaitPeriod),XtRString, "2000" },
00174 };
00175
00176 #undef offset
00177
00178 #if 0
00179 static XtActionsRec actions[] =
00180 };
00181 #endif
00182
00183
00184 LiteClueClassRec xcgLiteClueClassRec =
00185 {
00186 {
00187 (WidgetClass)&overrideShellClassRec,
00188 "XcgLiteClue",
00189 (Cardinal)sizeof(LiteClueRec),
00190 NULL,
00191 (XtWidgetClassProc)NULL,
00192 (XtEnum)FALSE,
00193 (XtInitProc)Initialize,
00194 (XtArgsProc)NULL,
00195 XtInheritRealize,
00196 (XtActionList)0,
00197 (Cardinal)0,
00198 (XtResourceList)resources,
00199 (Cardinal)XtNumber(resources),
00200 NULLQUARK,
00201 TRUE,
00202 (XtEnum)FALSE,
00203 TRUE,
00204 FALSE,
00205 (XtWidgetProc)NULL,
00206 XtInheritResize,
00207 XtInheritExpose,
00208 (XtSetValuesFunc)setValues,
00209 (XtArgsFunc)NULL,
00210 XtInheritSetValuesAlmost,
00211 (XtArgsProc)NULL,
00212 XtInheritAcceptFocus,
00213 XtVersion,
00214 (XtPointer)NULL,
00215 XtInheritTranslations,
00216 XtInheritQueryGeometry,
00217 XtInheritDisplayAccelerator,
00218 (XtPointer)0,
00219 },
00220 {
00221 XtInheritGeometryManager,
00222 XtInheritChangeManaged,
00223 XtInheritInsertChild,
00224 XtInheritDeleteChild,
00225 NULL
00226 },
00227 {
00228 (XtPointer) NULL,
00229 },
00230
00231 {
00232 0,
00233 },
00234
00235 {
00236 0,
00237 },
00238 };
00239
00240 WidgetClass xcgLiteClueWidgetClass = (WidgetClass) & xcgLiteClueClassRec;
00241
00242
00243
00244
00245
00246
00247 static void xcgListInit(ListThread *newbuf)
00248 {
00249 newbuf->back = newbuf;
00250 newbuf->forw = newbuf;
00251 }
00252
00253
00254
00255
00256
00257 static void xcgListInsertBefore(ListThread *newlist, ListThread *poslist)
00258 {
00259 ListThread *prevbuf;
00260
00261 prevbuf = poslist->back;
00262
00263 poslist->back = newlist;
00264 newlist->forw = poslist;
00265 newlist->back = prevbuf;
00266 prevbuf->forw = newlist;
00267 }
00268
00269
00270
00271
00272
00273 static ListThread * xcgListRemove(ListThread *rembuf)
00274 {
00275 ListThread *prevbuf, *nextbuf;
00276
00277 prevbuf = rembuf->back;
00278 nextbuf = rembuf->forw;
00279
00280 prevbuf->forw = nextbuf;
00281 nextbuf->back = prevbuf;
00282
00283 rembuf->back = (ListThread *) NULL;
00284 rembuf->forw = (ListThread *) NULL;
00285 return rembuf;
00286 }
00287
00288
00289
00290
00291
00292 #if XtSpecificationRelease >= 5
00293
00294 static void compute_font_info(XcgLiteClueWidget cw)
00295 {
00296 XRectangle ink;
00297 XRectangle logical;
00298
00299 if (!cw->liteClue.fontset)
00300 return;
00301 XmbTextExtents(cw->liteClue.fontset, "1", 1,&ink, &logical);
00302
00303 cw->liteClue.font_baseline = -logical.y;
00304
00305 cw->liteClue.font_width = logical.width;
00306 cw->liteClue.font_height = logical.height;
00307 }
00308
00309 #else
00310
00311 static void compute_font_info(XcgLiteClueWidget cw)
00312 {
00313 int direction_return;
00314 int font_ascent_return, font_descent_return;
00315 XCharStruct oret;
00316 if ( cw->liteClue.font == NULL )
00317 return;
00318 XTextExtents( cw->liteClue.font, "1", 1,
00319 &direction_return,
00320 &font_ascent_return, &font_descent_return, &oret);
00321
00322 cw->liteClue.font_baseline = oret.ascent;
00323
00324 cw->liteClue.font_width = oret.width;
00325 cw->liteClue.font_height = oret.ascent+oret.descent;
00326 }
00327 #endif
00328
00329
00330
00331
00332 static void create_GC(XcgLiteClueWidget cw )
00333 {
00334 XtGCMask valuemask;
00335 XGCValues myXGCV;
00336
00337
00338 valuemask = GCForeground | GCBackground | GCFillStyle ;
00339 myXGCV.foreground = cw->liteClue.foreground;
00340 myXGCV.background = cw->core.background_pixel;
00341 myXGCV.fill_style = FillSolid;
00342
00343 #if XtSpecificationRelease < 5
00344 myXGCV.font = cw->liteClue.font->fid;
00345 #endif
00346
00347 if (cw->liteClue.text_GC )
00348 XtReleaseGC((Widget) cw, cw->liteClue.text_GC );
00349 cw->liteClue.text_GC = XtGetGC((Widget)cw, valuemask, &myXGCV);
00350 }
00351
00352
00353
00354
00355
00356
00357 static void wrong_widget(char * routine)
00358 {
00359 int mypid = getpid();
00360 fprintf(stderr, "Wrong class of widget passed to %s\n", routine);
00361 fflush(stderr);
00362 kill(mypid, SIGABRT);
00363 }
00364
00365
00366
00367
00368
00369 static struct liteClue_context_str * find_watched_widget(XcgLiteClueWidget cw,
00370 Widget target)
00371 {
00372 struct liteClue_context_str * obj;
00373
00374 for (obj = (struct liteClue_context_str *) cw->liteClue.widget_list.forw;
00375 obj != (struct liteClue_context_str *) & cw->liteClue.widget_list;
00376 obj = (struct liteClue_context_str *)obj->next.forw )
00377 {
00378 if (target == obj->watched_w)
00379 return obj;
00380 }
00381 return NULL;
00382 }
00383
00384
00385
00386
00387 struct liteClue_context_str * alloc_liteClue_context(void)
00388 {
00389 struct liteClue_context_str * out;
00390 out = (struct liteClue_context_str *) XtMalloc(sizeof(struct liteClue_context_str));
00391 memset(out, 0, sizeof(struct liteClue_context_str));
00392 xcgListInit(&out->next);
00393 return out ;
00394 }
00395
00396
00397
00398
00399 static struct liteClue_context_str * alloc_link_liteClue_context(XcgLiteClueWidget cw )
00400 {
00401 struct liteClue_context_str * out = alloc_liteClue_context();
00402
00403
00404 xcgListInsertBefore(&out->next, &cw->liteClue.widget_list);
00405 out->cw = cw;
00406 return out;
00407 }
00408
00409
00410
00411
00412 void free_widget_context(XcgLiteClueWidget cw, struct liteClue_context_str * obj)
00413 {
00414 xcgListRemove((ListThread *)obj);
00415
00416 obj->sensitive = False;
00417 if (obj->text )
00418 XtFree(obj->text);
00419 XtFree((char *) obj);
00420 }
00421
00422
00423
00424
00425 static void Initialize(Widget treq, Widget tnew, ArgList args,
00426 Cardinal *num_args)
00427 {
00428 XcgLiteClueWidget cw = (XcgLiteClueWidget) tnew;
00429
00430
00431 cw->liteClue.text_GC = NULL;
00432 cw->liteClue.HelpIsUp = False;
00433 cw->liteClue.HelpPopDownTime = 0;
00434 cw->liteClue.interval_id = (XtIntervalId)0;
00435 xcgListInit(&cw->liteClue.widget_list);
00436 compute_font_info(cw);
00437 create_GC(cw );
00438 }
00439
00440 static Boolean setValues( Widget _current, Widget _request, Widget _new, ArgList args, Cardinal * num_args)
00441 {
00442 XcgLiteClueWidget cw_new = (XcgLiteClueWidget) _new;
00443 XcgLiteClueWidget cw_cur = (XcgLiteClueWidget) _current;
00444
00445
00446
00447
00448 if (cw_new->liteClue.foreground != cw_cur->liteClue.foreground
00449 || cw_new->core.background_pixel != cw_cur->core.background_pixel )
00450 {
00451 create_GC(cw_new);
00452 }
00453
00454 return FALSE;
00455 }
00456
00457
00458
00459
00460
00461 static void timeout_event( XtPointer client_data, XtIntervalId *id)
00462 {
00463 #define BorderPix 3
00464 struct liteClue_context_str * obj = (struct liteClue_context_str *) client_data;
00465 XcgLiteClueWidget cw = obj->cw;
00466 Position abs_x, abs_y;
00467
00468 XRectangle ink;
00469 XRectangle logical;
00470 Position w_height;
00471 Widget w;
00472
00473 int RWC_width , RWC_height ;
00474
00475 if (cw->liteClue.interval_id == (XtIntervalId)0)
00476 return;
00477 cw->liteClue.interval_id = (XtIntervalId)0;
00478 if (obj->sensitive == False)
00479 return;
00480
00481 w = obj->watched_w;
00482 XtVaGetValues(w, XtNheight, &w_height, NULL );
00483
00484 XtTranslateCoords(w, 0, w_height, &abs_x, &abs_y);
00485
00486 #if XtSpecificationRelease < 5
00487 {
00488 int direction_return;
00489 int font_ascent_return, font_descent_return;
00490 XCharStruct oret;
00491 XTextExtents( cw->liteClue.font ,obj->text , obj->text_size,
00492 &direction_return,
00493 &font_ascent_return, &font_descent_return, &oret);
00494 logical.width = oret.width;
00495 }
00496 #else
00497 XmbTextExtents(cw->liteClue.fontset, obj->text , obj->text_size ,&ink, &logical);
00498 #endif
00499
00500 RWC_width = 2*BorderPix +logical.width ;
00501 RWC_height = 2*BorderPix + cw->liteClue.font_height ;
00502 XtResizeWidget((Widget) cw, RWC_width , RWC_height ,
00503 cw->core.border_width );
00504
00505
00506 { int scw = WidthOfScreen(XtScreen(cw)) , sch = HeightOfScreen(XtScreen(cw)) ;
00507 int newx = abs_x + 1 , newy = abs_y+1 ; int xx,yy ;
00508 if( newx + logical.width > scw ) newx = scw - logical.width - 2*BorderPix ;
00509 if( newx < 0 ) newx = 0 ;
00510 if( newy + cw->liteClue.font_height + 2 >= sch )
00511 newy = newy - w_height - cw->liteClue.font_height - 2*BorderPix ;
00512 if( newy < 0 ) newy = 0 ;
00513
00514 #if 1
00515 RWC_xineramize( XtDisplay(w) ,
00516 newx,newy , RWC_width,RWC_height , &xx,&yy ) ;
00517 if( yy < newy )
00518 yy = newy - w_height - cw->liteClue.font_height - 2*BorderPix ;
00519 XtMoveWidget((Widget) cw, xx,yy);
00520 #else
00521 XtMoveWidget((Widget) cw, newx,newy);
00522 #endif
00523 }
00524
00525 XtPopup((Widget) cw, XtGrabNone);
00526 cw->liteClue.HelpIsUp = True;
00527
00528 #if XtSpecificationRelease < 5
00529 XDrawImageString(XtDisplay((Widget) cw), XtWindow((Widget) cw),
00530 cw->liteClue.text_GC , BorderPix,
00531 BorderPix + cw->liteClue.font_baseline, obj->text , obj->text_size);
00532 #else
00533 XmbDrawImageString(XtDisplay((Widget) cw), XtWindow((Widget) cw),
00534 cw->liteClue.fontset,
00535 cw->liteClue.text_GC , BorderPix,
00536 BorderPix + cw->liteClue.font_baseline, obj->text , obj->text_size);
00537 #endif
00538
00539
00540 XDrawRectangle( XtDisplay((Widget) cw) , XtWindow((Widget) cw) ,
00541 cw->liteClue.text_GC ,
00542 0,0 , RWC_width-1,RWC_height-1 ) ;
00543 }
00544
00545
00546
00547
00548
00549 static void Enter_event(Widget w, XtPointer client_data, XEvent * xevent, Boolean * continue_to_dispatch )
00550 {
00551 struct liteClue_context_str * obj = (struct liteClue_context_str *) client_data;
00552 XcgLiteClueWidget cw = obj->cw;
00553 XEnterWindowEvent * event = & xevent->xcrossing;
00554 int current_waitPeriod ;
00555
00556 if (obj->sensitive == False)
00557 return;
00558
00559
00560 if (cw->liteClue.interval_id != (XtIntervalId)0)
00561 return;
00562 if(event->mode != NotifyNormal)
00563 return;
00564
00565
00566
00567
00568 if ((event->time - cw->liteClue.HelpPopDownTime) >
00569 cw->liteClue.cancelWaitPeriod )
00570 current_waitPeriod = cw->liteClue.waitPeriod,timeout_event;
00571 else
00572 current_waitPeriod = 0;
00573
00574 cw->liteClue.interval_id = XtAppAddTimeOut(
00575 XtWidgetToApplicationContext(w),
00576 current_waitPeriod, timeout_event, client_data);
00577 }
00578
00579
00580
00581
00582 static void Leave_event(Widget w, XtPointer client_data, XEvent * xevent, Boolean * continue_to_dispatch )
00583 {
00584 struct liteClue_context_str * obj = (struct liteClue_context_str *) client_data;
00585 XcgLiteClueWidget cw = obj->cw;
00586 XEnterWindowEvent * event = & xevent->xcrossing;
00587
00588 if (cw->liteClue.interval_id != (XtIntervalId)0)
00589 {
00590 XtRemoveTimeOut(cw->liteClue.interval_id);
00591 cw->liteClue.interval_id= (XtIntervalId)0;
00592 }
00593
00594 if (obj->sensitive == False)
00595 return;
00596 if (cw->liteClue.HelpIsUp)
00597 {
00598 XtPopdown((Widget) cw);
00599 cw->liteClue.HelpIsUp = False;
00600 cw->liteClue.HelpPopDownTime = event->time;
00601 }
00602 }
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 void XcgLiteClueAddWidget(Widget w, Widget watch, char * text, int size, int option )
00637 {
00638 # define ROUTINE "XcgLiteClueAddWidget"
00639 # define BADVALUE
00640 XcgLiteClueWidget cw = (XcgLiteClueWidget) w;
00641 struct liteClue_context_str * obj;
00642 Boolean exists = False;
00643
00644 CheckWidgetClass(ROUTINE);
00645
00646 obj = find_watched_widget(cw, watch);
00647 if (obj)
00648 {
00649 exists = True;
00650 if (text)
00651 {
00652 if(obj->text)
00653 XtFree(obj->text);
00654 obj->text = NULL;
00655 }
00656 }
00657 else
00658 {
00659 obj = alloc_link_liteClue_context(cw );
00660 obj->watched_w = watch;
00661 }
00662 if (text && !(obj->text))
00663 {
00664 if (!size)
00665 size = strlen(text);
00666 obj->text = (char*) XtMalloc(size+1);
00667 memcpy(obj->text, text, size);
00668 obj->text[size] = 0;
00669 obj->text_size = size;
00670 }
00671 if (!exists)
00672 {
00673 XtAddEventHandler(watch, EnterWindowMask, False,
00674 Enter_event, (XtPointer) obj);
00675 XtAddEventHandler(watch, LeaveWindowMask|ButtonPressMask,
00676 False, Leave_event, (XtPointer) obj);
00677 obj->sensitive = True;
00678 }
00679
00680 # undef ROUTINE
00681 # undef BADVALUE
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701 void XcgLiteClueDeleteWidget(Widget w, Widget watch)
00702 {
00703 # define ROUTINE "XcgLiteClueDeleteWidget"
00704 # define BADVALUE
00705 XcgLiteClueWidget cw = (XcgLiteClueWidget) w;
00706 struct liteClue_context_str * obj;
00707
00708 CheckWidgetClass(ROUTINE);
00709 obj = find_watched_widget(cw, watch);
00710 if (obj)
00711 {
00712 XtRemoveEventHandler(watch, EnterWindowMask, False,
00713 Enter_event, (XtPointer) obj);
00714 XtRemoveEventHandler(watch, LeaveWindowMask|ButtonPressMask,
00715 False, Leave_event, (XtPointer) obj);
00716 if (cw->liteClue.interval_id != (XtIntervalId)0)
00717 {
00718 XtRemoveTimeOut(cw->liteClue.interval_id);
00719 cw->liteClue.interval_id= (XtIntervalId)0;
00720 }
00721 free_widget_context(cw, obj);
00722 }
00723
00724 # undef ROUTINE
00725 # undef BADVALUE
00726 }
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749 void XcgLiteClueSetSensitive(Widget w, Widget watch, Boolean sensitive)
00750 {
00751 # define ROUTINE "XcgLiteClueSetSensitive"
00752 # define BADVALUE
00753 XcgLiteClueWidget cw = (XcgLiteClueWidget) w;
00754 struct liteClue_context_str * obj;
00755
00756 CheckWidgetClass(ROUTINE);
00757 if (watch)
00758 {
00759 obj = find_watched_widget(cw, watch);
00760 if (obj)
00761 {
00762 obj->sensitive = sensitive;
00763 return;
00764 }
00765 else
00766 return;
00767 }
00768
00769
00770 for (obj = (struct liteClue_context_str *) cw->liteClue.widget_list.forw;
00771 obj != (struct liteClue_context_str *) & cw->liteClue.widget_list;
00772 obj = (struct liteClue_context_str *)obj->next.forw )
00773 {
00774 obj->sensitive = sensitive;
00775 }
00776
00777 # undef ROUTINE
00778 # undef BADVALUE
00779 }
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801 Boolean XcgLiteClueGetSensitive(Widget w, Widget watch)
00802 {
00803 # define ROUTINE "XcgLiteClueGetSensitive"
00804 # define BADVALUE False
00805
00806 XcgLiteClueWidget cw = (XcgLiteClueWidget) w;
00807 struct liteClue_context_str * obj;
00808
00809 CheckWidgetClass(ROUTINE);
00810 if (watch)
00811 {
00812 obj = find_watched_widget(cw, watch);
00813 if (obj)
00814 return obj->sensitive;
00815 else
00816 return False;
00817 }
00818
00819 obj = (struct liteClue_context_str *) cw->liteClue.widget_list.forw;
00820 if (obj != (struct liteClue_context_str *) & cw->liteClue.widget_list)
00821 return obj->sensitive;
00822 else
00823 return False;
00824
00825 # undef ROUTINE
00826 # undef BADVALUE
00827 }
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864 Boolean XcgLiteClueDispatchEvent(Widget w, XEvent *event)
00865 {
00866 # define ROUTINE "XcgLiteClueDispatchEvent"
00867 # define BADVALUE False
00868
00869 XcgLiteClueWidget cw = (XcgLiteClueWidget) w;
00870 struct liteClue_context_str * obj;
00871 Boolean continue_to_dispatch;
00872
00873 if (event->type != EnterNotify && event->type != LeaveNotify)
00874 return False;
00875 CheckWidgetClass(ROUTINE);
00876
00877
00878 for (obj = (struct liteClue_context_str *) cw->liteClue.widget_list.forw;
00879 obj != (struct liteClue_context_str *) & cw->liteClue.widget_list;
00880 obj = (struct liteClue_context_str *)obj->next.forw )
00881 {
00882 if ((XtWindow(obj->watched_w) != event->xany.window)
00883 || (XtIsSensitive(obj->watched_w)) )
00884 continue;
00885
00886 if (event->type == EnterNotify )
00887 Enter_event(obj->watched_w, obj, event, &continue_to_dispatch);
00888 else
00889 Leave_event(obj->watched_w, obj, event, &continue_to_dispatch);
00890 return True;
00891 }
00892 return False;
00893
00894 # undef ROUTINE
00895 # undef BADVALUE
00896 }
00897