Back to index

texmacs  1.0.7.15
x_gui.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : x_gui.cpp
00004 * DESCRIPTION: Graphical user interface for X11
00005 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "timer.hpp"
00013 #include "dictionary.hpp"
00014 #include "X11/x_gui.hpp"
00015 #include "X11/x_drawable.hpp"
00016 #include "X11/x_window.hpp"
00017 #include "image_files.hpp"
00018 #include <X11/cursorfont.h>
00019 #include "message.hpp"
00020 
00021 extern hashmap<Window,pointer> Window_to_window;
00022 
00023 /******************************************************************************
00024 * Making color scales for anti alised fonts
00025 ******************************************************************************/
00026 
00027 x_character_rep::x_character_rep (
00028   int c2, font_glyphs fng2, int sf2, color fg2, color bg2):
00029     c (c2), fng (fng2), sf (sf2), fg (fg2), bg (bg2) {}
00030 
00031 x_character::x_character (int c, font_glyphs fng, int sf, color fg, color bg):
00032   rep (tm_new<x_character_rep> (c, fng, sf, fg, bg)) {}
00033 
00034 x_character::operator tree () {
00035   tree t (TUPLE,  as_string (rep->c), rep->fng->res_name);
00036   t << as_string (rep->sf) << as_string (rep->fg) << as_string (rep->bg);
00037   return t; }
00038 
00039 bool operator == (x_character xc1, x_character xc2) {
00040   return
00041     (xc1->c==xc2->c) && (xc1->fng.rep==xc2->fng.rep) &&
00042     (xc1->sf==xc2->sf) && (xc1->fg==xc2->fg) && (xc1->bg==xc2->bg); }
00043 
00044 bool operator != (x_character xc1, x_character xc2) {
00045   return
00046     (xc1->c!=xc2->c) || (xc1->fng.rep!=xc2->fng.rep) ||
00047     (xc1->sf!=xc2->sf) || (xc1->fg!=xc2->fg) || (xc1->bg!=xc2->bg); }
00048 
00049 int hash (x_character xc) {
00050   return xc->c ^ ((intptr_t) xc->fng.rep) ^ xc->fg ^ xc->bg ^ xc->sf; }
00051 
00052 void
00053 x_gui_rep::prepare_color (int sf, color fg, color bg) {
00054   int nr_cols= sf*sf;
00055   if (nr_cols >= 64) nr_cols= 64;
00056   x_character col_entry (0, font_glyphs (), sf, fg, bg);
00057   color* cols= (color*) color_scale [col_entry];
00058   if (cols == NULL) {
00059     int fR, fG, fB, fA, bR, bG, bB, bA, j;
00060     get_rgb_color (fg, fR, fG, fB, fA);
00061     get_rgb_color (bg, bR, bG, bB, bA);
00062     if (fA != 255) {
00063       fR= (bR * (255 - fA) + fR * fA) / 255;
00064       fG= (bG * (255 - fA) + fG * fA) / 255;
00065       fB= (bB * (255 - fA) + fB * fA) / 255;
00066     }
00067     cols= tm_new_array<color> (nr_cols+1);
00068     for (j=0; j<=nr_cols; j++)
00069       cols [nr_cols-j]= rgb_color ((bR*j + fR*(nr_cols-j)) / nr_cols,
00070                                (bG*j + fG*(nr_cols-j)) / nr_cols,
00071                                (bB*j + fB*(nr_cols-j)) / nr_cols);
00072     color_scale (col_entry)= (void*) cols;
00073   }
00074 }
00075 
00076 /******************************************************************************
00077 * Subroutines
00078 ******************************************************************************/
00079 
00080 void
00081 x_gui_rep::set_button_state (unsigned int state) {
00082   int i= 0;
00083   if ((state & Button1Mask) != 0) i += 1;
00084   if ((state & Button2Mask) != 0) i += 2;
00085   if ((state & Button3Mask) != 0) i += 4;
00086   if ((state & Button4Mask) != 0) i += 8;
00087   if ((state & Button5Mask) != 0) i += 16;
00088   if ((state & ShiftMask)   != 0) i += 256;
00089   if ((state & ControlMask) != 0) i += 512;
00090   if ((state & LockMask)    != 0) i += 1024;
00091   if ((state & Mod1Mask)    != 0) i += 2048;
00092   if ((state & Mod2Mask)    != 0) i += 4096;
00093   if ((state & Mod3Mask)    != 0) i += 8192;
00094   if ((state & Mod4Mask)    != 0) i += 16384;
00095   if ((state & Mod5Mask)    != 0) i += 32768;
00096   x_gui_rep::state= i;
00097 }
00098 
00099 void
00100 x_gui_rep::emulate_leave_enter (widget old_widget, widget new_widget) {
00101   Window root, child;
00102   SI root_x, root_y, x, y;
00103   unsigned int mask;
00104 
00105   XQueryPointer (dpy, get_Window (old_widget),
00106                &root, &child, &root_x, &root_y, &x, &y, &mask);
00107   set_button_state (mask);
00108   x= (x * PIXEL);
00109   y= ((-y) * PIXEL);
00110   // cout << "\nLeave " << old_widget << "\n";
00111   send_mouse (old_widget, "leave", x, y, state, 0);
00112   // cout << "Leave OK\n";
00113 
00114   XQueryPointer (dpy, get_Window (new_widget),
00115                &root, &child, &root_x, &root_y, &x, &y, &mask);
00116   set_button_state (mask);
00117   x= (x * PIXEL);
00118   y= ((-y) * PIXEL);
00119   // cout << "Enter " << new_widget << "\n";
00120   send_mouse (new_widget, "enter", x, y, state, 0);
00121   // cout << "Enter OK\n\n";
00122 }
00123 
00124 /******************************************************************************
00125 * Grabbing
00126 ******************************************************************************/
00127 
00128 /*
00129 string
00130 pritty (tree t) {
00131   if (is_atomic (t)) return copy (as_string (t));
00132   else if (N(t) == 2) return pritty (t[1]);
00133   else {
00134     int i;
00135     string s ("(");
00136     for (i=1; i<N(t); i++) {
00137       if (i>1) s << " ";
00138       s << pritty (t[i]);
00139     }
00140     s << ")";
00141     return s;
00142   }
00143 }
00144 */
00145 
00146 void
00147 x_gui_rep::obtain_mouse_grab (widget wid) {
00148   Window win= get_Window (wid);
00149   if ((!is_nil (grab_ptr)) && (wid==grab_ptr->item)) return;
00150   widget old_widget; if (!is_nil (grab_ptr)) old_widget= grab_ptr->item;
00151   grab_ptr= list<widget> (wid, grab_ptr);
00152   widget new_widget= grab_ptr->item;
00153   notify_mouse_grab (new_widget, true);
00154   XGrabPointer (dpy, win, false,
00155               PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
00156               GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
00157   // cout << "\n---> In grab " << pritty ((tree) wid) << "\n\n";
00158   if (!is_nil (old_widget)) {
00159     notify_mouse_grab (old_widget, false);
00160     emulate_leave_enter (old_widget, new_widget);
00161   }
00162 }
00163 
00164 void
00165 x_gui_rep::release_mouse_grab () {
00166   if (is_nil (grab_ptr)) return;
00167   widget old_widget= grab_ptr->item;
00168   grab_ptr= grab_ptr->next;
00169   widget new_widget; if (!is_nil (grab_ptr)) new_widget= grab_ptr->item;
00170   if (is_nil (grab_ptr)) {
00171     XUngrabPointer (dpy, CurrentTime);
00172     // cout << "\n---> No grab\n\n";
00173   }
00174   else {
00175     x_window grab_win= get_x_window (new_widget);
00176     notify_mouse_grab (new_widget, true);    
00177     XGrabPointer (dpy, grab_win->win, false,
00178                 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
00179                 GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
00180     // cout << "\n---> In grab " << new_widget << "\n";
00181     notify_mouse_grab (old_widget, false);
00182     emulate_leave_enter (old_widget, new_widget);
00183   }
00184 }
00185 
00186 bool
00187 x_gui_rep::has_mouse_grab (widget w) {
00188   return (!is_nil (grab_ptr)) && (grab_ptr->item == w);
00189 }
00190 
00191 /******************************************************************************
00192 * Selections
00193 ******************************************************************************/
00194 
00195 Bool
00196 my_selnotify_predicate (Display* dpy, XEvent* ev, XPointer arg) { (void) dpy;
00197   x_window win= (x_window) arg;
00198   return (win->win==ev->xany.window) && (ev->type==SelectionNotify);
00199 }
00200 
00201 void
00202 x_gui_rep::created_window (Window win) {
00203   windows_l << win;
00204 }
00205 
00206 void
00207 x_gui_rep::deleted_window (Window win) {
00208   windows_l= remove (windows_l, win);
00209 }
00210 
00211 void
00212 x_gui_rep::focussed_window (Window win) {
00213   windows_l= list<Window> (win, remove (windows_l, win));
00214 }
00215 
00216 bool
00217 x_gui_rep::get_selection (string key, tree& t, string& s) {
00218   t= "none";
00219   s= "";
00220   bool res=false;
00221 
00222   if (selection_t->contains (key)) {
00223     t= copy (selection_t [key]);
00224     s= copy (selection_s [key]);
00225     return true;
00226   }
00227   
00228   Atom xsel;
00229   if (key == "primary") xsel = XA_CLIPBOARD;
00230   else if (key == "mouse") xsel = XA_PRIMARY;
00231   else return res;
00232 
00233   Window selown = XGetSelectionOwner(dpy, xsel);
00234   if (selown == None ||
00235       is_nil (windows_l) ||
00236       contains (windows_l, selown)) return res;
00237 
00238   Window win= windows_l->item;
00239   x_window x_win= (x_window) Window_to_window[win];
00240   Atom prop= XInternAtom (dpy, "MY_STRING_SELECTION", false);
00241   XConvertSelection (dpy, xsel, XA_STRING, prop, win, CurrentTime);
00242 
00243   int i;
00244   XEvent ev;
00245   for (i=0; i<1000000; i++)
00246     if (XCheckIfEvent (dpy, &ev, my_selnotify_predicate, (XPointer) x_win))
00247       break;
00248   if (i==1000000) return res;
00249   XSelectionEvent& sel= ev.xselection;
00250 
00251   if (sel.property==prop) {
00252     long offset=0;
00253     Atom type;
00254     int fm;
00255     unsigned long n, remains;
00256     unsigned char* ret;
00257     
00258     do {
00259       XGetWindowProperty (dpy, win, sel.property,
00260                        offset, 1024, true, AnyPropertyType,
00261                        &type, &fm, &n, &remains, &ret);
00262       s << string ((char*) ret, n);
00263       offset += (n >> 2);
00264       XFree (ret);
00265     } while (remains>0);
00266     t= tuple ("extern", s);
00267     return true;
00268   }
00269   else return res;
00270 }
00271 
00272 bool
00273 x_gui_rep::set_selection (string key, tree t, string s) {
00274   selection_t (key)= copy (t);
00275   selection_s (key)= copy (s);
00276   Atom xsel;
00277   if(key == "primary") xsel = XA_CLIPBOARD;
00278   else if (key == "mouse") xsel = XA_PRIMARY;
00279   else return true;
00280   if (is_nil (windows_l)) return false;
00281   Window win= windows_l->item;
00282   selection_w= win;
00283   XSetSelectionOwner (dpy, xsel, win, CurrentTime);
00284   if (XGetSelectionOwner (dpy, xsel) == None) return false;
00285   return true;
00286 }
00287 
00288 void
00289 x_gui_rep::clear_selection (string key) {
00290   selection_t->reset (key);
00291   selection_s->reset (key);
00292 }
00293 
00294 bool
00295 set_selection (string key, tree t, string s, string format) {
00296   (void) format;
00297   return the_gui->set_selection (key, t, s);
00298 }
00299 
00300 bool
00301 get_selection (string key, tree& t, string& s, string format) {
00302   (void) format;
00303   return the_gui->get_selection (key, t, s);
00304 }
00305 
00306 void
00307 clear_selection (string key) {
00308   the_gui->clear_selection (key);
00309 }
00310 
00311 /******************************************************************************
00312 * X Pointers
00313 ******************************************************************************/
00314 
00315 // Definitions from X11/cursorfont.h
00316 static int
00317 fetch_X11_cursor_no (string name) {
00318   string pref= name(0,3);
00319   if (pref!="XC_") return -1;
00320   name= name (3,N(name));
00321   switch (name[0]) {
00322     case 'X':
00323       if (name=="X_cursor") return XC_X_cursor;
00324     break;
00325     case 'a':
00326       if (name=="arrow") return XC_arrow;
00327     break;
00328     case 'b':
00329       if (name=="based_arrow_down") return XC_based_arrow_down;
00330       if (name=="based_arrow_up") return XC_based_arrow_up;
00331       if (name=="boat") return XC_boat;
00332       if (name=="bogosity") return XC_bogosity;
00333       if (name=="bottom_left_corner") return XC_bottom_left_corner;
00334       if (name=="bottom_right_corner") return XC_bottom_right_corner;
00335       if (name=="bottom_side") return XC_bottom_side;
00336       if (name=="bottom_tee") return XC_bottom_tee;
00337       if (name=="box_spiral") return XC_box_spiral;
00338     break;
00339     case 'c':
00340       if (name=="center_ptr") return XC_center_ptr;
00341       if (name=="circle") return XC_circle;
00342       if (name=="clock") return XC_clock;
00343       if (name=="coffee_mug") return XC_coffee_mug;
00344       if (name=="cross") return XC_cross;
00345       if (name=="cross_reverse") return XC_cross_reverse;
00346       if (name=="crosshair") return XC_crosshair;
00347     break;
00348     case 'd':
00349       if (name=="diamond_cross") return XC_diamond_cross;
00350       if (name=="dot") return XC_dot;
00351       if (name=="dotbox") return XC_dotbox;
00352       if (name=="double_arrow") return XC_double_arrow;
00353       if (name=="draft_large") return XC_draft_large;
00354       if (name=="draft_small") return XC_draft_small;
00355       if (name=="draped_box") return XC_draped_box;
00356     break;
00357     case 'e':
00358       if (name=="exchange") return XC_exchange;
00359     break;
00360     case 'f':
00361       if (name=="fleur") return XC_fleur;
00362     break;
00363     case 'g':
00364       if (name=="gobbler") return XC_gobbler;
00365       if (name=="gumby") return XC_gumby;
00366     break;
00367     case 'h':
00368       if (name=="hand1") return XC_hand1;
00369       if (name=="hand2") return XC_hand2;
00370       if (name=="heart") return XC_heart;
00371     break;
00372     case 'i':
00373       if (name=="icon") return XC_icon;
00374       if (name=="iron_cross") return XC_iron_cross;
00375     break;
00376     case 'l':
00377       if (name=="left_ptr") return XC_left_ptr;
00378       if (name=="left_side") return XC_left_side;
00379       if (name=="left_tee") return XC_left_tee;
00380       if (name=="leftbutton") return XC_leftbutton;
00381       if (name=="ll_angle") return XC_ll_angle;
00382       if (name=="lr_angle") return XC_lr_angle;
00383     break;
00384     case 'm':
00385       if (name=="man") return XC_man;
00386       if (name=="middlebutton") return XC_middlebutton;
00387       if (name=="mouse") return XC_mouse;
00388     break;
00389     case 'p':
00390       if (name=="pencil") return XC_pencil;
00391       if (name=="pirate") return XC_pirate;
00392       if (name=="plus") return XC_plus;
00393     break;
00394     case 'q':
00395       if (name=="question_arrow") return XC_question_arrow;
00396     break;
00397     case 'r':
00398       if (name=="right_ptr") return XC_right_ptr;
00399       if (name=="right_side") return XC_right_side;
00400       if (name=="right_tee") return XC_right_tee;
00401       if (name=="rightbutton") return XC_rightbutton;
00402       if (name=="rtl_logo") return XC_rtl_logo;
00403     break;
00404     case 's':
00405       if (name=="sailboat") return XC_sailboat;
00406       if (name=="sb_down_arrow") return XC_sb_down_arrow;
00407       if (name=="sb_h_double_arrow") return XC_sb_h_double_arrow;
00408       if (name=="sb_left_arrow") return XC_sb_left_arrow;
00409       if (name=="sb_right_arrow") return XC_sb_right_arrow;
00410       if (name=="sb_up_arrow") return XC_sb_up_arrow;
00411       if (name=="sb_v_double_arrow") return XC_sb_v_double_arrow;
00412       if (name=="shuttle") return XC_shuttle;
00413       if (name=="sizing") return XC_sizing;
00414       if (name=="spider") return XC_spider;
00415       if (name=="spraycan") return XC_spraycan;
00416       if (name=="star") return XC_star;
00417     break;
00418     case 't':
00419       if (name=="target") return XC_target;
00420       if (name=="tcross") return XC_tcross;
00421       if (name=="top_left_arrow") return XC_top_left_arrow;
00422       if (name=="top_left_corner") return XC_top_left_corner;
00423       if (name=="top_right_corner") return XC_top_right_corner;
00424       if (name=="top_side") return XC_top_side;
00425       if (name=="top_tee") return XC_top_tee;
00426       if (name=="trek") return XC_trek;
00427     break;
00428     case 'u':
00429       if (name=="ul_angle") return XC_ul_angle;
00430       if (name=="umbrella") return XC_umbrella;
00431       if (name=="ur_angle") return XC_ur_angle;
00432     break;
00433     case 'w':
00434       if (name=="watch") return XC_watch;
00435     break;
00436     case 'x':
00437       if (name=="xterm") return XC_xterm;
00438     break;
00439   }
00440   return -1;
00441 }
00442 
00443 void
00444 x_gui_rep::set_mouse_pointer (widget w, string name) {
00445   int no= fetch_X11_cursor_no (name);
00446   if (no==-1) return;
00447   Cursor cursor=XCreateFontCursor(dpy, no);
00448   x_window win= get_x_window (w);
00449   if (win != NULL) XDefineCursor(dpy, win->win, cursor);
00450 }
00451 
00452 void
00453 x_gui_rep::set_mouse_pointer (widget w, string name, string mask_name) {
00454   static hashmap<string,tree> xpm_cache ("");
00455   if (mask_name=="") mask_name= name;
00456   x_drawable_rep* dra= tm_new<x_drawable_rep> (this, 1, 1);
00457   dra->xpm_initialize (name);
00458   if (mask_name!=name) dra->xpm_initialize (mask_name);
00459   tm_delete (dra);
00460   Pixmap curs= (Pixmap) xpm_bitmap [name];
00461   Pixmap mask= (Pixmap) xpm_bitmap [mask_name];
00462 
00463   if (!xpm_cache->contains (name))
00464     xpm_cache (name)= xpm_load (name);
00465 
00466   if (!xpm_cache->contains (mask_name))
00467     xpm_cache (mask_name)= xpm_load (mask_name);
00468 
00469   array<string> cnames_curs= xpm_colors (xpm_cache[name]);
00470   array<SI> hotspot= xpm_hotspot (xpm_cache[name]);
00471   ASSERT (N(hotspot) != 0, "missing hotspot");
00472   array<string> cnames_mask= xpm_colors (xpm_cache[mask_name]);
00473   char* bgcolor= as_charp (N(cnames_mask)>1 ? cnames_mask[1] :
00474                                          string ("white"));
00475   char* fgcolor= as_charp (N(cnames_curs)>1 ? cnames_curs[1] :
00476                                          string ("black"));
00477   if (!strcmp (bgcolor, "none")) bgcolor= as_charp (string ("white"));
00478   if (!strcmp (fgcolor, "none")) fgcolor= as_charp (string ("white"));
00479 
00480   XColor *bg= NULL, *fg= NULL;
00481   XColor exact1, closest1;
00482   XLookupColor(dpy, cols, fgcolor, &exact1, &closest1);
00483   if (XAllocColor (dpy, cols, &exact1)) fg= &exact1;
00484   else if (XAllocColor (dpy, cols, &closest1)) fg= &closest1;
00485   else FAILED ("unable to allocate fgcolor");
00486 
00487   XColor exact2, closest2;
00488   XLookupColor(dpy, cols, bgcolor, &exact2, &closest2);
00489   if (XAllocColor (dpy, cols, &exact2)) bg= &exact2;
00490   else if (XAllocColor (dpy, cols, &closest2)) bg= &closest2;
00491   else FAILED ("unable to allocate bgcolor");
00492 
00493   tm_delete_array (bgcolor);
00494   tm_delete_array (fgcolor);
00495 
00496   SI x= hotspot[0], y= hotspot[1];
00497   Cursor cursor=XCreatePixmapCursor (dpy, curs, mask, fg, bg, x, y);
00498   x_window win= get_x_window (w);
00499   if (win != NULL) XDefineCursor(dpy, win->win, cursor);
00500 }
00501 
00502 /******************************************************************************
00503 * Miscellaneous
00504 ******************************************************************************/
00505 
00506 void
00507 x_gui_rep::show_help_balloon (widget wid, SI x, SI y) {
00508   unmap_balloon ();
00509   balloon_wid = wid;
00510   balloon_win = NULL;
00511   balloon_x   = x;
00512   balloon_y   = y;
00513   balloon_time= texmacs_time ();
00514 }
00515 
00516 void
00517 x_gui_rep::map_balloon () {
00518   widget win_wid= popup_window_widget (balloon_wid, "Balloon");
00519   set_position (win_wid, balloon_x, balloon_y);
00520   balloon_win= (window) get_x_window (win_wid);
00521   balloon_win->set_visibility (true);
00522 }
00523 
00524 void
00525 x_gui_rep::unmap_balloon () {
00526   if (!is_nil (balloon_wid)) {
00527     if (balloon_win != NULL) {
00528       balloon_win->set_visibility (false);
00529       tm_delete (balloon_win);
00530       balloon_win= NULL;
00531     }
00532     balloon_wid= widget ();
00533   }
00534 }
00535 
00536 void
00537 x_gui_rep::show_wait_indicator (widget w, string message, string arg) {
00538   // NOTE: the wait indicator is directly displayed inside the window
00539   // corresponding to w. We explicitly shortcut the main event loop
00540   // by invalidating the wait widget and requesting a redraw.
00541   // Using a popup window does not work, because it would be necessary
00542   // to return to the main loop to map and redraw it.
00543   x_window ww= get_x_window (w);
00544   if (ww == NULL || message == "") return;
00545   if (arg != "") message= message * " " * arg * "...";
00546   SI width= 400*PIXEL, height= 160*PIXEL;
00547   widget wait_wid= wait_widget (width, height, message);
00548   SI mid_x= (ww->win_w>>1)*PIXEL, mid_y= -(ww->win_h>>1)*PIXEL + height;
00549   SI x= mid_x- width/2, y= mid_y- height/2;
00550   widget old_wid= ww->w;
00551   ww->w= wait_wid;
00552   set_position (wait_wid, x, y);
00553   set_identifier (wait_wid, (int) ww->win);
00554   send_invalidate_all (wait_wid);
00555   ww->repaint_invalid_regions ();
00556   ww->w= old_wid;
00557   XFlush (dpy);
00558   send_invalidate_all (old_wid);
00559 }
00560 
00561 void
00562 x_gui_rep::external_event (string type, time_t t) {
00563   (void) t;
00564   if (!is_nil (windows_l)) {
00565     Window win= windows_l->item;
00566     x_window x_win= (x_window) Window_to_window[win];
00567     x_win->key_event (type);
00568   }
00569 }
00570 
00571 bool
00572 x_gui_rep::check_event (int type) {
00573   bool status;
00574   XEvent ev;
00575   switch (type) {
00576   case INTERRUPT_EVENT:
00577     if (interrupted) return true;
00578     else {
00579       time_t now= texmacs_time ();
00580       if (now - interrupt_time < 0) return false;
00581       else interrupt_time= now + (100 / (XPending (dpy) + 1));
00582       interrupted= XCheckMaskEvent (dpy, KeyPressMask|ButtonPressMask, &ev);
00583       if (interrupted) XPutBackEvent (dpy, &ev);
00584       return interrupted;
00585     }
00586   case INTERRUPTED_EVENT:
00587     return interrupted;
00588   case ANY_EVENT:
00589     return (XPending (dpy)>0);
00590   case MOTION_EVENT:
00591     status= XCheckMaskEvent (dpy, PointerMotionMask, &ev);
00592     if (status) XPutBackEvent (dpy, &ev);
00593     return status;
00594   case DRAG_EVENT:
00595     status= XCheckMaskEvent (dpy, ButtonMotionMask, &ev);
00596     if (status) XPutBackEvent (dpy, &ev);
00597     return status;
00598   case MENU_EVENT:
00599     status= XCheckMaskEvent (dpy, ButtonMotionMask|ButtonReleaseMask, &ev);
00600     if (status) XPutBackEvent (dpy, &ev);
00601     return status;
00602   }
00603   return interrupted;
00604 }
00605 
00606 void
00607 beep () {
00608 #ifdef OS_WIN32
00609   XBeep ();
00610 #else
00611   cerr << '\a';
00612 #endif
00613 }
00614 
00615 void
00616 show_help_balloon (widget wid, SI x, SI y) {
00617   the_gui->show_help_balloon (wid, x, y);
00618 }
00619 
00620 void
00621 show_wait_indicator (widget w, string message, string arg) {
00622   the_gui->show_wait_indicator (w, message, arg);
00623 }
00624 
00625 void
00626 external_event (string type, time_t t) {
00627   the_gui->external_event (type, t);
00628 }
00629 
00630 void
00631 needs_update () {
00632 }
00633 
00634 bool
00635 check_event (int type) {
00636   return the_gui->check_event (type);
00637 }