1
2 /******************************************************************************
3 * MODULE : x_gui.cpp
4 * DESCRIPTION: Graphical user interface for X11
5 * COPYRIGHT : (C) 1999 Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11
12 #include "timer.hpp"
13 #include "dictionary.hpp"
14 #include "X11/x_gui.hpp"
15 #include "X11/x_drawable.hpp"
16 #include "X11/x_window.hpp"
17 #include "image_files.hpp"
18 #include <X11/cursorfont.h>
19 #include "message.hpp"
20 #include "x_picture.hpp"
21
22 extern hashmap<Window,pointer> Window_to_window;
23
24 /******************************************************************************
25 * Making color scales for anti alised fonts
26 ******************************************************************************/
27
x_character_rep(int c2,font_glyphs fng2,int sf2,color fg2,color bg2)28 x_character_rep::x_character_rep (
29 int c2, font_glyphs fng2, int sf2, color fg2, color bg2):
30 c (c2), fng (fng2), sf (sf2), fg (fg2), bg (bg2) {}
31
x_character(int c,font_glyphs fng,int sf,color fg,color bg)32 x_character::x_character (int c, font_glyphs fng, int sf, color fg, color bg):
33 rep (tm_new<x_character_rep> (c, fng, sf, fg, bg)) {}
34
operator tree()35 x_character::operator tree () {
36 tree t (TUPLE, as_string (rep->c), rep->fng->res_name);
37 t << as_string (rep->sf) << as_string (rep->fg) << as_string (rep->bg);
38 return t; }
39
operator ==(x_character xc1,x_character xc2)40 bool operator == (x_character xc1, x_character xc2) {
41 return
42 (xc1->c==xc2->c) && (xc1->fng.rep==xc2->fng.rep) &&
43 (xc1->sf==xc2->sf) && (xc1->fg==xc2->fg) && (xc1->bg==xc2->bg); }
44
operator !=(x_character xc1,x_character xc2)45 bool operator != (x_character xc1, x_character xc2) {
46 return
47 (xc1->c!=xc2->c) || (xc1->fng.rep!=xc2->fng.rep) ||
48 (xc1->sf!=xc2->sf) || (xc1->fg!=xc2->fg) || (xc1->bg!=xc2->bg); }
49
hash(x_character xc)50 int hash (x_character xc) {
51 return xc->c ^ ((intptr_t) xc->fng.rep) ^ xc->fg ^ xc->bg ^ xc->sf; }
52
53 void
prepare_color(int sf,color fg,color bg)54 x_gui_rep::prepare_color (int sf, color fg, color bg) {
55 int nr_cols= sf*sf;
56 if (nr_cols >= 64) nr_cols= 64;
57 x_character col_entry (0, font_glyphs (), sf, fg, bg);
58 color* cols= (color*) color_scale [col_entry];
59 if (cols == NULL) {
60 int fR, fG, fB, fA, bR, bG, bB, bA, j;
61 get_rgb_color (fg, fR, fG, fB, fA);
62 get_rgb_color (bg, bR, bG, bB, bA);
63 if (fA != 255) {
64 fR= (bR * (255 - fA) + fR * fA) / 255;
65 fG= (bG * (255 - fA) + fG * fA) / 255;
66 fB= (bB * (255 - fA) + fB * fA) / 255;
67 }
68 cols= tm_new_array<color> (nr_cols+1);
69 for (j=0; j<=nr_cols; j++)
70 cols [nr_cols-j]= rgb_color ((bR*j + fR*(nr_cols-j)) / nr_cols,
71 (bG*j + fG*(nr_cols-j)) / nr_cols,
72 (bB*j + fB*(nr_cols-j)) / nr_cols);
73 color_scale (col_entry)= (void*) cols;
74 }
75 }
76
77 /******************************************************************************
78 * Subroutines
79 ******************************************************************************/
80
81 void
set_button_state(unsigned int state)82 x_gui_rep::set_button_state (unsigned int state) {
83 int i= 0;
84 if ((state & Button1Mask) != 0) i += 1;
85 if ((state & Button2Mask) != 0) i += 2;
86 if ((state & Button3Mask) != 0) i += 4;
87 if ((state & Button4Mask) != 0) i += 8;
88 if ((state & Button5Mask) != 0) i += 16;
89 if ((state & ShiftMask) != 0) i += 256;
90 if ((state & ControlMask) != 0) i += 512;
91 if ((state & LockMask) != 0) i += 1024;
92 if ((state & Mod1Mask) != 0) i += 2048;
93 if ((state & Mod2Mask) != 0) i += 4096;
94 if ((state & Mod3Mask) != 0) i += 8192;
95 if ((state & Mod4Mask) != 0) i += 16384;
96 if ((state & Mod5Mask) != 0) i += 32768;
97 x_gui_rep::state= i;
98 }
99
100 void
emulate_leave_enter(widget old_widget,widget new_widget)101 x_gui_rep::emulate_leave_enter (widget old_widget, widget new_widget) {
102 Window root, child;
103 SI root_x, root_y, x, y;
104 unsigned int mask;
105
106 XQueryPointer (dpy, get_Window (old_widget),
107 &root, &child, &root_x, &root_y, &x, &y, &mask);
108 set_button_state (mask);
109 x= (x * PIXEL);
110 y= ((-y) * PIXEL);
111 // cout << "\nLeave " << old_widget << "\n";
112 send_mouse (old_widget, "leave", x, y, state, 0);
113 // cout << "Leave OK\n";
114
115 XQueryPointer (dpy, get_Window (new_widget),
116 &root, &child, &root_x, &root_y, &x, &y, &mask);
117 set_button_state (mask);
118 x= (x * PIXEL);
119 y= ((-y) * PIXEL);
120 // cout << "Enter " << new_widget << "\n";
121 send_mouse (new_widget, "enter", x, y, state, 0);
122 // cout << "Enter OK\n\n";
123 }
124
125 /******************************************************************************
126 * Grabbing
127 ******************************************************************************/
128
129 /*
130 string
131 pritty (tree t) {
132 if (is_atomic (t)) return copy (as_string (t));
133 else if (N(t) == 2) return pritty (t[1]);
134 else {
135 int i;
136 string s ("(");
137 for (i=1; i<N(t); i++) {
138 if (i>1) s << " ";
139 s << pritty (t[i]);
140 }
141 s << ")";
142 return s;
143 }
144 }
145 */
146
147 void
obtain_mouse_grab(widget wid)148 x_gui_rep::obtain_mouse_grab (widget wid) {
149 Window win= get_Window (wid);
150 if ((!is_nil (grab_ptr)) && (wid==grab_ptr->item)) return;
151 widget old_widget; if (!is_nil (grab_ptr)) old_widget= grab_ptr->item;
152 grab_ptr= list<widget> (wid, grab_ptr);
153 widget new_widget= grab_ptr->item;
154 notify_mouse_grab (new_widget, true);
155 XGrabPointer (dpy, win, false,
156 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
157 GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
158 // cout << "\n---> In grab " << pritty ((tree) wid) << "\n\n";
159 if (!is_nil (old_widget)) {
160 notify_mouse_grab (old_widget, false);
161 emulate_leave_enter (old_widget, new_widget);
162 }
163 }
164
165 void
release_mouse_grab()166 x_gui_rep::release_mouse_grab () {
167 if (is_nil (grab_ptr)) return;
168 widget old_widget= grab_ptr->item;
169 grab_ptr= grab_ptr->next;
170 widget new_widget; if (!is_nil (grab_ptr)) new_widget= grab_ptr->item;
171 if (is_nil (grab_ptr)) {
172 XUngrabPointer (dpy, CurrentTime);
173 // cout << "\n---> No grab\n\n";
174 }
175 else {
176 x_window grab_win= get_x_window (new_widget);
177 notify_mouse_grab (new_widget, true);
178 XGrabPointer (dpy, grab_win->win, false,
179 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
180 GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
181 // cout << "\n---> In grab " << new_widget << "\n";
182 notify_mouse_grab (old_widget, false);
183 emulate_leave_enter (old_widget, new_widget);
184 }
185 }
186
187 bool
has_mouse_grab(widget w)188 x_gui_rep::has_mouse_grab (widget w) {
189 return (!is_nil (grab_ptr)) && (grab_ptr->item == w);
190 }
191
192 /******************************************************************************
193 * Selections
194 ******************************************************************************/
195
196 Bool
my_selnotify_predicate(Display * dpy,XEvent * ev,XPointer arg)197 my_selnotify_predicate (Display* dpy, XEvent* ev, XPointer arg) { (void) dpy;
198 x_window win= (x_window) arg;
199 return (win->win==ev->xany.window) && (ev->type==SelectionNotify);
200 }
201
202 void
created_window(Window win)203 x_gui_rep::created_window (Window win) {
204 windows_l << win;
205 }
206
207 void
deleted_window(Window win)208 x_gui_rep::deleted_window (Window win) {
209 windows_l= remove (windows_l, win);
210 }
211
212 void
focussed_window(Window win)213 x_gui_rep::focussed_window (Window win) {
214 windows_l= list<Window> (win, remove (windows_l, win));
215 }
216
217 bool
get_selection(string key,tree & t,string & s)218 x_gui_rep::get_selection (string key, tree& t, string& s) {
219 t= "none";
220 s= "";
221 bool res=false;
222
223 if (selection_t->contains (key)) {
224 t= copy (selection_t [key]);
225 s= copy (selection_s [key]);
226 return true;
227 }
228
229 Atom xsel;
230 if (key == "primary") xsel = XA_CLIPBOARD;
231 else if (key == "mouse") xsel = XA_PRIMARY;
232 else return res;
233
234 Window selown = XGetSelectionOwner(dpy, xsel);
235 if (selown == None ||
236 is_nil (windows_l) ||
237 contains (windows_l, selown)) return res;
238
239 Window win= windows_l->item;
240 x_window x_win= (x_window) Window_to_window[win];
241 Atom prop= XInternAtom (dpy, "MY_STRING_SELECTION", false);
242 XConvertSelection (dpy, xsel, XA_STRING, prop, win, CurrentTime);
243
244 int i;
245 XEvent ev;
246 for (i=0; i<1000000; i++)
247 if (XCheckIfEvent (dpy, &ev, my_selnotify_predicate, (XPointer) x_win))
248 break;
249 if (i==1000000) return res;
250 XSelectionEvent& sel= ev.xselection;
251
252 if (sel.property==prop) {
253 long offset=0;
254 Atom type;
255 int fm;
256 unsigned long n, remains;
257 unsigned char* ret;
258
259 do {
260 XGetWindowProperty (dpy, win, sel.property,
261 offset, 1024, true, AnyPropertyType,
262 &type, &fm, &n, &remains, &ret);
263 s << string ((char*) ret, n);
264 offset += (n >> 2);
265 XFree (ret);
266 } while (remains>0);
267 t= tuple ("extern", s);
268 return true;
269 }
270 else return res;
271 }
272
273 bool
set_selection(string key,tree t,string s)274 x_gui_rep::set_selection (string key, tree t, string s) {
275 selection_t (key)= copy (t);
276 selection_s (key)= copy (s);
277 Atom xsel;
278 if(key == "primary") xsel = XA_CLIPBOARD;
279 else if (key == "mouse") xsel = XA_PRIMARY;
280 else return true;
281 if (is_nil (windows_l)) return false;
282 Window win= windows_l->item;
283 selection_w= win;
284 XSetSelectionOwner (dpy, xsel, win, CurrentTime);
285 if (XGetSelectionOwner (dpy, xsel) == None) return false;
286 return true;
287 }
288
289 void
clear_selection(string key)290 x_gui_rep::clear_selection (string key) {
291 selection_t->reset (key);
292 selection_s->reset (key);
293 }
294
295 bool
set_selection(string key,tree t,string s,string sv,string sh,string format)296 set_selection (string key, tree t,
297 string s, string sv, string sh, string format) {
298 (void) format;
299 return the_gui->set_selection (key, t, s);
300 }
301
302 bool
get_selection(string key,tree & t,string & s,string format)303 get_selection (string key, tree& t, string& s, string format) {
304 (void) format;
305 return the_gui->get_selection (key, t, s);
306 }
307
308 void
clear_selection(string key)309 clear_selection (string key) {
310 the_gui->clear_selection (key);
311 }
312
313 /******************************************************************************
314 * X Pointers
315 ******************************************************************************/
316
317 // Definitions from X11/cursorfont.h
318 static int
fetch_X11_cursor_no(string name)319 fetch_X11_cursor_no (string name) {
320 string pref= name(0,3);
321 if (pref!="XC_") return -1;
322 name= name (3,N(name));
323 switch (name[0]) {
324 case 'X':
325 if (name=="X_cursor") return XC_X_cursor;
326 break;
327 case 'a':
328 if (name=="arrow") return XC_arrow;
329 break;
330 case 'b':
331 if (name=="based_arrow_down") return XC_based_arrow_down;
332 if (name=="based_arrow_up") return XC_based_arrow_up;
333 if (name=="boat") return XC_boat;
334 if (name=="bogosity") return XC_bogosity;
335 if (name=="bottom_left_corner") return XC_bottom_left_corner;
336 if (name=="bottom_right_corner") return XC_bottom_right_corner;
337 if (name=="bottom_side") return XC_bottom_side;
338 if (name=="bottom_tee") return XC_bottom_tee;
339 if (name=="box_spiral") return XC_box_spiral;
340 break;
341 case 'c':
342 if (name=="center_ptr") return XC_center_ptr;
343 if (name=="circle") return XC_circle;
344 if (name=="clock") return XC_clock;
345 if (name=="coffee_mug") return XC_coffee_mug;
346 if (name=="cross") return XC_cross;
347 if (name=="cross_reverse") return XC_cross_reverse;
348 if (name=="crosshair") return XC_crosshair;
349 break;
350 case 'd':
351 if (name=="diamond_cross") return XC_diamond_cross;
352 if (name=="dot") return XC_dot;
353 if (name=="dotbox") return XC_dotbox;
354 if (name=="double_arrow") return XC_double_arrow;
355 if (name=="draft_large") return XC_draft_large;
356 if (name=="draft_small") return XC_draft_small;
357 if (name=="draped_box") return XC_draped_box;
358 break;
359 case 'e':
360 if (name=="exchange") return XC_exchange;
361 break;
362 case 'f':
363 if (name=="fleur") return XC_fleur;
364 break;
365 case 'g':
366 if (name=="gobbler") return XC_gobbler;
367 if (name=="gumby") return XC_gumby;
368 break;
369 case 'h':
370 if (name=="hand1") return XC_hand1;
371 if (name=="hand2") return XC_hand2;
372 if (name=="heart") return XC_heart;
373 break;
374 case 'i':
375 if (name=="icon") return XC_icon;
376 if (name=="iron_cross") return XC_iron_cross;
377 break;
378 case 'l':
379 if (name=="left_ptr") return XC_left_ptr;
380 if (name=="left_side") return XC_left_side;
381 if (name=="left_tee") return XC_left_tee;
382 if (name=="leftbutton") return XC_leftbutton;
383 if (name=="ll_angle") return XC_ll_angle;
384 if (name=="lr_angle") return XC_lr_angle;
385 break;
386 case 'm':
387 if (name=="man") return XC_man;
388 if (name=="middlebutton") return XC_middlebutton;
389 if (name=="mouse") return XC_mouse;
390 break;
391 case 'p':
392 if (name=="pencil") return XC_pencil;
393 if (name=="pirate") return XC_pirate;
394 if (name=="plus") return XC_plus;
395 break;
396 case 'q':
397 if (name=="question_arrow") return XC_question_arrow;
398 break;
399 case 'r':
400 if (name=="right_ptr") return XC_right_ptr;
401 if (name=="right_side") return XC_right_side;
402 if (name=="right_tee") return XC_right_tee;
403 if (name=="rightbutton") return XC_rightbutton;
404 if (name=="rtl_logo") return XC_rtl_logo;
405 break;
406 case 's':
407 if (name=="sailboat") return XC_sailboat;
408 if (name=="sb_down_arrow") return XC_sb_down_arrow;
409 if (name=="sb_h_double_arrow") return XC_sb_h_double_arrow;
410 if (name=="sb_left_arrow") return XC_sb_left_arrow;
411 if (name=="sb_right_arrow") return XC_sb_right_arrow;
412 if (name=="sb_up_arrow") return XC_sb_up_arrow;
413 if (name=="sb_v_double_arrow") return XC_sb_v_double_arrow;
414 if (name=="shuttle") return XC_shuttle;
415 if (name=="sizing") return XC_sizing;
416 if (name=="spider") return XC_spider;
417 if (name=="spraycan") return XC_spraycan;
418 if (name=="star") return XC_star;
419 break;
420 case 't':
421 if (name=="target") return XC_target;
422 if (name=="tcross") return XC_tcross;
423 if (name=="top_left_arrow") return XC_top_left_arrow;
424 if (name=="top_left_corner") return XC_top_left_corner;
425 if (name=="top_right_corner") return XC_top_right_corner;
426 if (name=="top_side") return XC_top_side;
427 if (name=="top_tee") return XC_top_tee;
428 if (name=="trek") return XC_trek;
429 break;
430 case 'u':
431 if (name=="ul_angle") return XC_ul_angle;
432 if (name=="umbrella") return XC_umbrella;
433 if (name=="ur_angle") return XC_ur_angle;
434 break;
435 case 'w':
436 if (name=="watch") return XC_watch;
437 break;
438 case 'x':
439 if (name=="xterm") return XC_xterm;
440 break;
441 }
442 return -1;
443 }
444
445 void
set_mouse_pointer(widget w,string name)446 x_gui_rep::set_mouse_pointer (widget w, string name) {
447 int no= fetch_X11_cursor_no (name);
448 if (no==-1) return;
449 Cursor cursor=XCreateFontCursor(dpy, no);
450 x_window win= get_x_window (w);
451 if (win != NULL) XDefineCursor(dpy, win->win, cursor);
452 }
453
454 void
set_mouse_pointer(widget w,string name,string mask_name)455 x_gui_rep::set_mouse_pointer (widget w, string name, string mask_name) {
456 static hashmap<string,tree> xpm_cache ("");
457 if (mask_name=="") mask_name= name;
458 Pixmap curs= retrieve_bitmap (load_xpm (name));
459 Pixmap mask= retrieve_bitmap (load_xpm (mask_name));
460
461 if (!xpm_cache->contains (name))
462 xpm_cache (name)= xpm_load (name);
463
464 if (!xpm_cache->contains (mask_name))
465 xpm_cache (mask_name)= xpm_load (mask_name);
466
467 array<string> cnames_curs= xpm_colors (xpm_cache[name]);
468 array<SI> hotspot= xpm_hotspot (xpm_cache[name]);
469 ASSERT (N(hotspot) != 0, "missing hotspot");
470 array<string> cnames_mask= xpm_colors (xpm_cache[mask_name]);
471 c_string bgcolor (N(cnames_mask)>1 ? cnames_mask[1]: string ("white"));
472 c_string fgcolor (N(cnames_curs)>1 ? cnames_curs[1]: string ("black"));
473 if (!strcmp (bgcolor, "none")) bgcolor= c_string (string ("white"));
474 if (!strcmp (fgcolor, "none")) fgcolor= c_string (string ("white"));
475
476 XColor *bg= NULL, *fg= NULL;
477 XColor exact1, closest1;
478 XLookupColor(dpy, cols, fgcolor, &exact1, &closest1);
479 if (XAllocColor (dpy, cols, &exact1)) fg= &exact1;
480 else if (XAllocColor (dpy, cols, &closest1)) fg= &closest1;
481 else FAILED ("unable to allocate fgcolor");
482
483 XColor exact2, closest2;
484 XLookupColor(dpy, cols, bgcolor, &exact2, &closest2);
485 if (XAllocColor (dpy, cols, &exact2)) bg= &exact2;
486 else if (XAllocColor (dpy, cols, &closest2)) bg= &closest2;
487 else FAILED ("unable to allocate bgcolor");
488
489 SI x= hotspot[0], y= hotspot[1];
490 Cursor cursor=XCreatePixmapCursor (dpy, curs, mask, fg, bg, x, y);
491 x_window win= get_x_window (w);
492 if (win != NULL) XDefineCursor(dpy, win->win, cursor);
493 }
494
495 /******************************************************************************
496 * Miscellaneous
497 ******************************************************************************/
498
499 void
show_help_balloon(widget wid,SI x,SI y)500 x_gui_rep::show_help_balloon (widget wid, SI x, SI y) {
501 unmap_balloon ();
502 balloon_wid = wid;
503 balloon_win = NULL;
504 balloon_x = x;
505 balloon_y = y;
506 balloon_time= texmacs_time ();
507 }
508
509 void
map_balloon()510 x_gui_rep::map_balloon () {
511 widget win_wid= popup_window_widget (balloon_wid, "Balloon");
512 set_position (win_wid, balloon_x, balloon_y);
513 balloon_win= (window) get_x_window (win_wid);
514 balloon_win->set_visibility (true);
515 }
516
517 void
unmap_balloon()518 x_gui_rep::unmap_balloon () {
519 if (!is_nil (balloon_wid)) {
520 if (balloon_win != NULL) {
521 balloon_win->set_visibility (false);
522 tm_delete (balloon_win);
523 balloon_win= NULL;
524 }
525 balloon_wid= widget ();
526 }
527 }
528
529 void
show_wait_indicator(widget w,string message,string arg)530 x_gui_rep::show_wait_indicator (widget w, string message, string arg) {
531 // NOTE: the wait indicator is directly displayed inside the window
532 // corresponding to w. We explicitly shortcut the main event loop
533 // by invalidating the wait widget and requesting a redraw.
534 // Using a popup window does not work, because it would be necessary
535 // to return to the main loop to map and redraw it.
536 x_window ww= get_x_window (w);
537 if (ww == NULL || message == "") return;
538 if (arg != "") message= message * " " * arg * "...";
539 SI width= 400*PIXEL, height= 160*PIXEL;
540 widget wait_wid= wait_widget (width, height, message);
541 SI mid_x= (ww->win_w>>1)*PIXEL, mid_y= -(ww->win_h>>1)*PIXEL + height;
542 SI x= mid_x- width/2, y= mid_y- height/2;
543 widget old_wid= ww->w;
544 ww->w= wait_wid;
545 set_position (wait_wid, x, y);
546 set_identifier (wait_wid, (int) ww->win);
547 send_invalidate_all (wait_wid);
548 ww->repaint_invalid_regions ();
549 ww->w= old_wid;
550 XFlush (dpy);
551 send_invalidate_all (old_wid);
552 }
553
554 void
external_event(string type,time_t t)555 x_gui_rep::external_event (string type, time_t t) {
556 (void) t;
557 if (!is_nil (windows_l)) {
558 Window win= windows_l->item;
559 x_window x_win= (x_window) Window_to_window[win];
560 x_win->key_event (type);
561 }
562 }
563
564 bool
check_event(int type)565 x_gui_rep::check_event (int type) {
566 bool status;
567 XEvent ev;
568 switch (type) {
569 case INTERRUPT_EVENT:
570 if (interrupted) return true;
571 else {
572 time_t now= texmacs_time ();
573 if (now - interrupt_time < 0) return false;
574 else interrupt_time= now + (100 / (XPending (dpy) + 1));
575 interrupted= XCheckMaskEvent (dpy, KeyPressMask|ButtonPressMask, &ev);
576 if (interrupted) XPutBackEvent (dpy, &ev);
577 return interrupted;
578 }
579 case INTERRUPTED_EVENT:
580 return interrupted;
581 case ANY_EVENT:
582 return (XPending (dpy)>0);
583 case MOTION_EVENT:
584 status= XCheckMaskEvent (dpy, PointerMotionMask, &ev);
585 if (status) XPutBackEvent (dpy, &ev);
586 return status;
587 case DRAG_EVENT:
588 status= XCheckMaskEvent (dpy, ButtonMotionMask, &ev);
589 if (status) XPutBackEvent (dpy, &ev);
590 return status;
591 case MENU_EVENT:
592 status= XCheckMaskEvent (dpy, ButtonMotionMask|ButtonReleaseMask, &ev);
593 if (status) XPutBackEvent (dpy, &ev);
594 return status;
595 }
596 return interrupted;
597 }
598
599 void
beep()600 beep () {
601 #ifdef OS_WIN32
602 XBeep ();
603 #else
604 cerr << '\a';
605 #endif
606 }
607
608 void
show_help_balloon(widget wid,SI x,SI y)609 show_help_balloon (widget wid, SI x, SI y) {
610 the_gui->show_help_balloon (wid, x, y);
611 }
612
613 void
show_wait_indicator(widget w,string message,string arg)614 show_wait_indicator (widget w, string message, string arg) {
615 the_gui->show_wait_indicator (w, message, arg);
616 }
617
618 void
external_event(string type,time_t t)619 external_event (string type, time_t t) {
620 the_gui->external_event (type, t);
621 }
622
623 void
needs_update()624 needs_update () {
625 }
626
627 bool
check_event(int type)628 check_event (int type) {
629 return the_gui->check_event (type);
630 }
631
632 bool
gui_interrupted(bool check)633 gui_interrupted (bool check) {
634 return check_event (check? INTERRUPT_EVENT: INTERRUPTED_EVENT);
635 }
636
637
638