/[emacs]/emacs/src/xterm.c
ViewVC logotype

Diff of /emacs/src/xterm.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.735 by rms, Tue May 28 20:27:59 2002 UTC revision 1.735.2.1 by miles, Fri Apr 4 06:21:09 2003 UTC
# Line 97  Boston, MA 02111-1307, USA.  */ Line 97  Boston, MA 02111-1307, USA.  */
97  #include <unistd.h>  #include <unistd.h>
98  #endif  #endif
99    
100    #ifdef USE_GTK
101    #include "gtkutil.h"
102    #endif
103    
104  #ifdef USE_LUCID  #ifdef USE_LUCID
105  extern int xlwmenu_window_p (Widget w, Window window);  extern int xlwmenu_window_p P_ ((Widget w, Window window));
106  extern void xlwmenu_redisplay P_ ((Widget));  extern void xlwmenu_redisplay P_ ((Widget));
107  #endif  #endif
108    
109  #ifdef USE_X_TOOLKIT  #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
110    
111  extern void free_frame_menubar P_ ((struct frame *));  extern void free_frame_menubar P_ ((struct frame *));
112  extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,  extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
113                                                      int));                                                      int));
114    #endif
115    
116    #ifdef USE_X_TOOLKIT
117  #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)  #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
118  #define HACK_EDITRES  #define HACK_EDITRES
119  extern void _XEditResCheckMessages ();  extern void _XEditResCheckMessages ();
# Line 138  extern void _XEditResCheckMessages (); Line 144  extern void _XEditResCheckMessages ();
144    
145  #endif /* USE_X_TOOLKIT */  #endif /* USE_X_TOOLKIT */
146    
147  #ifndef USE_X_TOOLKIT  #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
148  #define x_any_window_to_frame x_window_to_frame  #define x_any_window_to_frame x_window_to_frame
149  #define x_top_window_to_frame x_window_to_frame  #define x_top_window_to_frame x_window_to_frame
150  #endif  #endif
# Line 152  extern void _XEditResCheckMessages (); Line 158  extern void _XEditResCheckMessages ();
158    
159  #define abs(x)  ((x) < 0 ? -(x) : (x))  #define abs(x)  ((x) < 0 ? -(x) : (x))
160    
 #define BETWEEN(X, LOWER, UPPER)  ((X) >= (LOWER) && (X) < (UPPER))  
   
161    
 /* Fringe bitmaps.  */  
   
 enum fringe_bitmap_type  
 {  
   NO_FRINGE_BITMAP,  
   LEFT_TRUNCATION_BITMAP,  
   RIGHT_TRUNCATION_BITMAP,  
   OVERLAY_ARROW_BITMAP,  
   CONTINUED_LINE_BITMAP,  
   CONTINUATION_LINE_BITMAP,  
   ZV_LINE_BITMAP  
 };  
   
 /* Bitmap drawn to indicate lines not displaying text if  
    `indicate-empty-lines' is non-nil.  */  
162    
 #define zv_width 8  
 #define zv_height 72  
 #define zv_period 3  
 static unsigned char zv_bits[] = {  
   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,  
   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,  
   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,  
   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,  
   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,  
   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,  
   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,  
   0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};  
   
 /* An arrow like this: `<-'.  */  
   
 #define left_width 8  
 #define left_height 8  
 static unsigned char left_bits[] = {  
    0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};  
   
 /* Right truncation arrow bitmap `->'.  */  
   
 #define right_width 8  
 #define right_height 8  
 static unsigned char right_bits[] = {  
    0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};  
   
 /* Marker for continued lines.  */  
   
 #define continued_width 8  
 #define continued_height 8  
 static unsigned char continued_bits[] = {  
    0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};  
   
 /* Marker for continuation lines.  */  
   
 #define continuation_width 8  
 #define continuation_height 8  
 static unsigned char continuation_bits[] = {  
    0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};  
   
 /* Overlay arrow bitmap.  */  
   
 #if 0  
 /* A bomb.  */  
 #define ov_width 8  
 #define ov_height 8  
 static unsigned char ov_bits[] = {  
    0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};  
 #else  
 /* A triangular arrow.  */  
 #define ov_width 8  
 #define ov_height 8  
 static unsigned char ov_bits[] = {  
    0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};  
   
 #endif  
   
 extern Lisp_Object Qhelp_echo;  
   
   
163  /* Non-nil means Emacs uses toolkit scroll bars.  */  /* Non-nil means Emacs uses toolkit scroll bars.  */
164    
165  Lisp_Object Vx_toolkit_scroll_bars;  Lisp_Object Vx_toolkit_scroll_bars;
166    
 /* If a string, XTread_socket generates an event to display that string.  
    (The display is done in read_char.)  */  
     
 static Lisp_Object help_echo;  
 static Lisp_Object help_echo_window;  
 static Lisp_Object help_echo_object;  
 static int help_echo_pos;  
   
 /* Temporary variable for XTread_socket.  */  
   
 static Lisp_Object previous_help_echo;  
   
167  /* Non-zero means that a HELP_EVENT has been generated since Emacs  /* Non-zero means that a HELP_EVENT has been generated since Emacs
168     start.  */     start.  */
169    
170  static int any_help_event_p;  static int any_help_event_p;
171    
 /* Non-zero means autoselect window with the mouse cursor.  */  
   
 int mouse_autoselect_window;  
   
172  /* Last window where we saw the mouse.  Used by mouse-autoselect-window.  */  /* Last window where we saw the mouse.  Used by mouse-autoselect-window.  */
173  static Lisp_Object last_window;  static Lisp_Object last_window;
174    
 /* Non-zero means draw block and hollow cursor as wide as the glyph  
    under it.  For example, if a block cursor is over a tab, it will be  
    drawn as wide as that tab on the display.  */  
   
 int x_stretch_cursor_p;  
   
175  /* Non-zero means make use of UNDERLINE_POSITION font properties.  */  /* Non-zero means make use of UNDERLINE_POSITION font properties.  */
176    
177  int x_use_underline_position_properties;  int x_use_underline_position_properties;
# Line 299  XtAppContext Xt_app_con; Line 205  XtAppContext Xt_app_con;
205  static String Xt_default_resources[] = {0};  static String Xt_default_resources[] = {0};
206  #endif /* USE_X_TOOLKIT */  #endif /* USE_X_TOOLKIT */
207    
 /* Nominal cursor position -- where to draw output.    
    HPOS and VPOS are window relative glyph matrix coordinates.  
    X and Y are window relative pixel coordinates.  */  
   
 struct cursor_pos output_cursor;  
   
208  /* Non-zero means user is interacting with a toolkit scroll bar.  */  /* Non-zero means user is interacting with a toolkit scroll bar.  */
209    
210  static int toolkit_scroll_bar_interaction;  static int toolkit_scroll_bar_interaction;
# Line 331  static int toolkit_scroll_bar_interactio Line 231  static int toolkit_scroll_bar_interactio
231    
232  /* Where the mouse was last time we reported a mouse event.  */  /* Where the mouse was last time we reported a mouse event.  */
233    
 FRAME_PTR last_mouse_frame;  
234  static XRectangle last_mouse_glyph;  static XRectangle last_mouse_glyph;
235  static Lisp_Object last_mouse_press_frame;  static Lisp_Object last_mouse_press_frame;
236    
# Line 380  extern Lisp_Object Vcommand_line_args, V Line 279  extern Lisp_Object Vcommand_line_args, V
279    
280  extern Lisp_Object Vx_no_window_manager;  extern Lisp_Object Vx_no_window_manager;
281    
282  extern Lisp_Object Qface, Qmouse_face;  extern Lisp_Object Qface, Qmouse_face, Qeql;
283    
284  extern int errno;  extern int errno;
285    
# Line 391  extern EMACS_INT extra_keyboard_modifier Line 290  extern EMACS_INT extra_keyboard_modifier
290  /* The keysyms to use for the various modifiers.  */  /* The keysyms to use for the various modifiers.  */
291    
292  Lisp_Object Vx_alt_keysym, Vx_hyper_keysym, Vx_meta_keysym, Vx_super_keysym;  Lisp_Object Vx_alt_keysym, Vx_hyper_keysym, Vx_meta_keysym, Vx_super_keysym;
293    Lisp_Object Vx_keysym_table;
294  static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;  static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
295    
296  static Lisp_Object Qvendor_specific_keysyms;  static Lisp_Object Qvendor_specific_keysyms;
297  static Lisp_Object Qlatin_1, Qutf_8;  static Lisp_Object Qlatin_1, Qutf_8;
298    
299  extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));  extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
 extern Lisp_Object x_icon_type P_ ((struct frame *));  
   
   
 /* Enumeration for overriding/changing the face to use for drawing  
    glyphs in x_draw_glyphs.  */  
300    
 enum draw_glyphs_face  
 {  
   DRAW_NORMAL_TEXT,  
   DRAW_INVERSE_VIDEO,  
   DRAW_CURSOR,  
   DRAW_MOUSE_FACE,  
   DRAW_IMAGE_RAISED,  
   DRAW_IMAGE_SUNKEN  
 };  
301    
 static int cursor_in_mouse_face_p P_ ((struct window *));  
 static int clear_mouse_face P_ ((struct x_display_info *));  
302  static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));  static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
303  static void x_set_window_size_1 P_ ((struct frame *, int, int, int));  static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
304  static const XColor *x_color_cells P_ ((Display *, int *));  static const XColor *x_color_cells P_ ((Display *, int *));
305  static void x_update_window_end P_ ((struct window *, int, int));  static void x_update_window_end P_ ((struct window *, int, int));
 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));  
306  void x_delete_display P_ ((struct x_display_info *));  void x_delete_display P_ ((struct x_display_info *));
307  static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,  static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
308                                                  unsigned));                                                  unsigned));
 static int fast_find_position P_ ((struct window *, int, int *, int *,  
                                    int *, int *, Lisp_Object));  
 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,  
                                      int *, int *, int *, int *, int));  
 static void set_output_cursor P_ ((struct cursor_pos *));  
 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,  
                                            int *, int *, int *, int));  
 static void note_mode_line_or_margin_highlight P_ ((struct window *, int,  
                                                     int, int));  
 static void note_mouse_highlight P_ ((struct frame *, int, int));  
 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));  
 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));  
 static void show_mouse_face P_ ((struct x_display_info *,  
                                  enum draw_glyphs_face));  
309  static int x_io_error_quitter P_ ((Display *));  static int x_io_error_quitter P_ ((Display *));
310  int x_catch_errors P_ ((Display *));  int x_catch_errors P_ ((Display *));
311  void x_uncatch_errors P_ ((Display *, int));  void x_uncatch_errors P_ ((Display *, int));
# Line 451  void x_wm_set_icon_pixmap P_ ((struct fr Line 320  void x_wm_set_icon_pixmap P_ ((struct fr
320  void x_initialize P_ ((void));  void x_initialize P_ ((void));
321  static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));  static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
322  static int x_compute_min_glyph_bounds P_ ((struct frame *));  static int x_compute_min_glyph_bounds P_ ((struct frame *));
 static void x_draw_phys_cursor_glyph P_ ((struct window *,  
                                           struct glyph_row *,  
                                           enum draw_glyphs_face));  
323  static void x_update_end P_ ((struct frame *));  static void x_update_end P_ ((struct frame *));
324  static void XTframe_up_to_date P_ ((struct frame *));  static void XTframe_up_to_date P_ ((struct frame *));
325  static void XTset_terminal_modes P_ ((void));  static void XTset_terminal_modes P_ ((void));
326  static void XTreset_terminal_modes P_ ((void));  static void XTreset_terminal_modes P_ ((void));
 static void XTcursor_to P_ ((int, int, int, int));  
 static void x_write_glyphs P_ ((struct glyph *, int));  
 static void x_clear_end_of_line P_ ((int));  
327  static void x_clear_frame P_ ((void));  static void x_clear_frame P_ ((void));
 static void x_clear_cursor P_ ((struct window *));  
328  static void frame_highlight P_ ((struct frame *));  static void frame_highlight P_ ((struct frame *));
329  static void frame_unhighlight P_ ((struct frame *));  static void frame_unhighlight P_ ((struct frame *));
330  static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));  static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
331    static int  x_focus_changed P_ ((int,
332                                     int,
333                                     struct x_display_info *,
334                                     struct frame *,
335                                     struct input_event *,
336                                     int));
337    static int  x_detect_focus_change P_ ((struct x_display_info *,
338                                           XEvent *,
339                                           struct input_event *,
340                                           int));
341  static void XTframe_rehighlight P_ ((struct frame *));  static void XTframe_rehighlight P_ ((struct frame *));
342  static void x_frame_rehighlight P_ ((struct x_display_info *));  static void x_frame_rehighlight P_ ((struct x_display_info *));
343  static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));  static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
344  static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,  static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
345                                     enum text_cursor_kinds));                                     enum text_cursor_kinds));
 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,  
                                        XRectangle *));  
 static void expose_frame P_ ((struct frame *, int, int, int, int));  
 static int expose_window_tree P_ ((struct window *, XRectangle *));  
 static int expose_window P_ ((struct window *, XRectangle *));  
 static void expose_area P_ ((struct window *, struct glyph_row *,  
                              XRectangle *, enum glyph_row_area));  
 static int expose_line P_ ((struct window *, struct glyph_row *,  
                              XRectangle *));  
 static void x_update_cursor_in_window_tree P_ ((struct window *, int));  
 static void x_update_window_cursor P_ ((struct window *, int));  
 static void x_erase_phys_cursor P_ ((struct window *));  
 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));  
 static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,  
                                       enum fringe_bitmap_type, int left_p));  
346    
347  static void x_clip_to_row P_ ((struct window *, struct glyph_row *,  static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
348                                 GC, int));                                 GC, int));
 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));  
 static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));  
 static void notice_overwritten_cursor P_ ((struct window *, enum glyph_row_area,  
                                            int, int, int, int));  
349  static void x_flush P_ ((struct frame *f));  static void x_flush P_ ((struct frame *f));
350  static void x_update_begin P_ ((struct frame *));  static void x_update_begin P_ ((struct frame *));
351  static void x_update_window_begin P_ ((struct window *));  static void x_update_window_begin P_ ((struct window *));
 static void x_draw_vertical_border P_ ((struct window *));  
352  static void x_after_update_window_line P_ ((struct glyph_row *));  static void x_after_update_window_line P_ ((struct glyph_row *));
 static INLINE void take_vertical_position_into_account P_ ((struct it *));  
 static void x_produce_stretch_glyph P_ ((struct it *));  
353  static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));  static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
354  static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,  static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
355                                              enum scroll_bar_part *,                                              enum scroll_bar_part *,
# Line 507  static void x_scroll_bar_report_motion P Line 357  static void x_scroll_bar_report_motion P
357                                              unsigned long *));                                              unsigned long *));
358  static void x_check_fullscreen P_ ((struct frame *));  static void x_check_fullscreen P_ ((struct frame *));
359  static void x_check_fullscreen_move P_ ((struct frame *));  static void x_check_fullscreen_move P_ ((struct frame *));
360    static int handle_one_xevent P_ ((struct x_display_info *,
361                                      XEvent *,
362                                      struct input_event **,
363                                      int *,
364                                      int *));
365    
366    
367  /* Flush display of frame F, or of all frames if F is null.  */  /* Flush display of frame F, or of all frames if F is null.  */
368    
# Line 534  x_flush (f) Line 390  x_flush (f)
390     XTread_socket calls XPending.  Removing XFlush improves     XTread_socket calls XPending.  Removing XFlush improves
391     performance.  */     performance.  */
392    
393  #define XFlush(DISPLAY) (void) 0  #define XFlush(DISPLAY) (void) 0
394    
395    
396  /***********************************************************************  /***********************************************************************
# Line 546  x_flush (f) Line 402  x_flush (f)
402  /* This is a function useful for recording debugging information about  /* This is a function useful for recording debugging information about
403     the sequence of occurrences in this file.  */     the sequence of occurrences in this file.  */
404    
405  struct record  struct record
406  {  {
407    char *locus;    char *locus;
408    int type;    int type;
# Line 592  x_display_info_for_display (dpy) Line 448  x_display_info_for_display (dpy)
448  /***********************************************************************  /***********************************************************************
449                      Starting and ending an update                      Starting and ending an update
450   ***********************************************************************/   ***********************************************************************/
451                                                                            
452  /* Start an update of frame F.  This function is installed as a hook  /* Start an update of frame F.  This function is installed as a hook
453     for update_begin, i.e. it is called when update_begin is called.     for update_begin, i.e. it is called when update_begin is called.
454     This function is called prior to calls to x_update_window_begin for     This function is called prior to calls to x_update_window_begin for
# Line 617  x_update_window_begin (w) Line 473  x_update_window_begin (w)
473  {  {
474    struct frame *f = XFRAME (WINDOW_FRAME (w));    struct frame *f = XFRAME (WINDOW_FRAME (w));
475    struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);    struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
476      
477    updated_window = w;    updated_window = w;
478    set_output_cursor (&w->cursor);    set_output_cursor (&w->cursor);
479    
# Line 639  x_update_window_begin (w) Line 495  x_update_window_begin (w)
495           flag set.  So, rows containing mouse-face glyphs are never           flag set.  So, rows containing mouse-face glyphs are never
496           scrolled, and we don't have to switch the mouse highlight off           scrolled, and we don't have to switch the mouse highlight off
497           here to prevent it from being scrolled.  */           here to prevent it from being scrolled.  */
498          
499        /* Can we tell that this update does not affect the window        /* Can we tell that this update does not affect the window
500           where the mouse highlight is?  If so, no need to turn off.           where the mouse highlight is?  If so, no need to turn off.
501           Likewise, don't do anything if the frame is garbaged;           Likewise, don't do anything if the frame is garbaged;
# Line 664  x_update_window_begin (w) Line 520  x_update_window_begin (w)
520  }  }
521    
522    
523  /* Draw a vertical window border to the right of window W if W doesn't  /* Draw a vertical window border from (x,y0) to (x,y1)  */
    have vertical scroll bars.  */  
524    
525  static void  static void
526  x_draw_vertical_border (w)  x_draw_vertical_window_border (w, x, y0, y1)
527       struct window *w;       struct window *w;
528         int x, y0, y1;
529  {  {
530    struct frame *f = XFRAME (WINDOW_FRAME (w));    struct frame *f = XFRAME (WINDOW_FRAME (w));
531        
532    /* Redraw borders between horizontally adjacent windows.  Don't    XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
533       do it for frames with vertical scroll bars because either the               f->output_data.x->normal_gc, x, y0, x, y1);
      right scroll bar of a window, or the left scroll bar of its  
      neighbor will suffice as a border.  */  
   if (!WINDOW_RIGHTMOST_P (w)  
       && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))  
     {  
       int x0, x1, y0, y1;  
   
       window_box_edges (w, -1, &x0, &y0, &x1, &y1);  
       x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);  
       y1 -= 1;  
         
       XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),  
                  f->output_data.x->normal_gc, x1, y0, x1, y1);  
     }  
534  }  }
535      
     
536  /* End update of window W (which is equal to updated_window).  /* End update of window W (which is equal to updated_window).
537    
538     Draw vertical borders between horizontally adjacent windows, and     Draw vertical borders between horizontally adjacent windows, and
# Line 711  x_update_window_end (w, cursor_on_p, mou Line 552  x_update_window_end (w, cursor_on_p, mou
552       int cursor_on_p, mouse_face_overwritten_p;       int cursor_on_p, mouse_face_overwritten_p;
553  {  {
554    struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));    struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
555          
556    if (!w->pseudo_window_p)    if (!w->pseudo_window_p)
557      {      {
558        BLOCK_INPUT;        BLOCK_INPUT;
559    
560        if (cursor_on_p)        if (cursor_on_p)
561          x_display_and_set_cursor (w, 1, output_cursor.hpos,          display_and_set_cursor (w, 1, output_cursor.hpos,
562                                    output_cursor.vpos,                                  output_cursor.vpos,
563                                    output_cursor.x, output_cursor.y);                                  output_cursor.x, output_cursor.y);
564          
565        x_draw_vertical_border (w);        x_draw_vertical_border (w);
566        UNBLOCK_INPUT;        UNBLOCK_INPUT;
567      }      }
568      
569    /* If a row with mouse-face was overwritten, arrange for    /* If a row with mouse-face was overwritten, arrange for
570       XTframe_up_to_date to redisplay the mouse highlight.  */       XTframe_up_to_date to redisplay the mouse highlight.  */
571    if (mouse_face_overwritten_p)    if (mouse_face_overwritten_p)
# Line 733  x_update_window_end (w, cursor_on_p, mou Line 574  x_update_window_end (w, cursor_on_p, mou
574        dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;        dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
575        dpyinfo->mouse_face_window = Qnil;        dpyinfo->mouse_face_window = Qnil;
576      }      }
577          
578    updated_window = NULL;    updated_window = NULL;
579  }  }
580    
# Line 748  x_update_end (f) Line 589  x_update_end (f)
589    /* Mouse highlight may be displayed again.  */    /* Mouse highlight may be displayed again.  */
590    FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;    FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
591    
592    #ifndef XFlush
593    BLOCK_INPUT;    BLOCK_INPUT;
594    XFlush (FRAME_X_DISPLAY (f));    XFlush (FRAME_X_DISPLAY (f));
595    UNBLOCK_INPUT;    UNBLOCK_INPUT;
596    #endif
597  }  }
598    
599    
# Line 795  x_after_update_window_line (desired_row) Line 638  x_after_update_window_line (desired_row)
638    struct window *w = updated_window;    struct window *w = updated_window;
639    struct frame *f;    struct frame *f;
640    int width, height;    int width, height;
641      
642    xassert (w);    xassert (w);
643      
644    if (!desired_row->mode_line_p && !w->pseudo_window_p)    if (!desired_row->mode_line_p && !w->pseudo_window_p)
645      {      {
646        BLOCK_INPUT;        BLOCK_INPUT;
647        x_draw_row_fringe_bitmaps (w, desired_row);        draw_row_fringe_bitmaps (w, desired_row);
648        UNBLOCK_INPUT;        UNBLOCK_INPUT;
649      }      }
650          
651    /* When a window has disappeared, make sure that no rest of    /* When a window has disappeared, make sure that no rest of
652       full-width rows stays visible in the internal border.  Could       full-width rows stays visible in the internal border.  Could
653       check here if updated_window is the leftmost/rightmost window,       check here if updated_window is the leftmost/rightmost window,
# Line 825  x_after_update_window_line (desired_row) Line 668  x_after_update_window_line (desired_row)
668        if (WINDOWP (f->tool_bar_window)        if (WINDOWP (f->tool_bar_window)
669            && w == XWINDOW (f->tool_bar_window))            && w == XWINDOW (f->tool_bar_window))
670          y -= width;          y -= width;
671          
672        BLOCK_INPUT;        BLOCK_INPUT;
673        x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),        x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
674                      0, y, width, height, False);                      0, y, width, height, False);
# Line 836  x_after_update_window_line (desired_row) Line 679  x_after_update_window_line (desired_row)
679      }      }
680  }  }
681    
   
 /* Draw the bitmap WHICH in one of the left or right fringes of  
    window W.  ROW is the glyph row for which to display the bitmap; it  
    determines the vertical position at which the bitmap has to be  
    drawn.  */  
   
682  static void  static void
683  x_draw_fringe_bitmap (w, row, which, left_p)  x_draw_fringe_bitmap (w, row, p)
684       struct window *w;       struct window *w;
685       struct glyph_row *row;       struct glyph_row *row;
686       enum fringe_bitmap_type which;       struct draw_fringe_bitmap_params *p;
      int left_p;  
687  {  {
688    struct frame *f = XFRAME (WINDOW_FRAME (w));    struct frame *f = XFRAME (WINDOW_FRAME (w));
689    Display *display = FRAME_X_DISPLAY (f);    Display *display = FRAME_X_DISPLAY (f);
690    Window window = FRAME_X_WINDOW (f);    Window window = FRAME_X_WINDOW (f);
   int x, y, wd, h, dy;  
   int b1, b2;  
   unsigned char *bits = NULL;  
   Pixmap pixmap;  
691    GC gc = f->output_data.x->normal_gc;    GC gc = f->output_data.x->normal_gc;
692    struct face *face;    struct face *face = p->face;
   int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));  
693    
694    /* Must clip because of partially visible lines.  */    /* Must clip because of partially visible lines.  */
695    x_clip_to_row (w, row, gc, 1);    x_clip_to_row (w, row, gc, 1);
696    
697    /* Convert row to frame coordinates.  */    if (p->bx >= 0)
   y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);  
   
   switch (which)  
     {  
     case NO_FRINGE_BITMAP:  
       wd = 0;  
       h = 0;  
       break;  
   
     case LEFT_TRUNCATION_BITMAP:  
       wd = left_width;  
       h = left_height;  
       bits = left_bits;  
       break;  
         
     case OVERLAY_ARROW_BITMAP:  
       wd = ov_width;  
       h = ov_height;  
       bits = ov_bits;  
       break;  
         
     case RIGHT_TRUNCATION_BITMAP:  
       wd = right_width;  
       h = right_height;  
       bits = right_bits;  
       break;  
   
     case CONTINUED_LINE_BITMAP:  
       wd = continued_width;  
       h = continued_height;  
       bits = continued_bits;  
       break;  
         
     case CONTINUATION_LINE_BITMAP:  
       wd = continuation_width;  
       h = continuation_height;  
       bits = continuation_bits;  
       break;  
   
     case ZV_LINE_BITMAP:  
       wd = zv_width;  
       h = zv_height - (y % zv_period);  
       bits = zv_bits + (y % zv_period);  
       break;  
   
     default:  
       abort ();  
     }  
   
   /* Clip bitmap if too high.  */  
   if (h > row->height)  
     h = row->height;  
   
   /* Set dy to the offset in the row to start drawing the bitmap.  */  
   dy = (row->height - h) / 2;  
   
   face = FACE_FROM_ID (f, FRINGE_FACE_ID);  
   PREPARE_FACE_FOR_DISPLAY (f, face);  
   
   /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill  
      the fringe.  */  
   b1 = b2 = -1;  
   if (left_p)  
698      {      {
       if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))  
         wd = FRAME_X_LEFT_FRINGE_WIDTH (f);  
       x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)  
            - wd  
            - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);  
       if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)  
         {  
           /* If W has a vertical border to its left, don't draw over it.  */  
           int border = ((XFASTINT (w->left) > 0  
                          && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))  
                         ? 1 : 0);  
           b1 = (window_box_left (w, -1)  
                 - FRAME_X_LEFT_FRINGE_WIDTH (f)  
                 + border);  
           b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);  
         }  
     }  
   else  
     {  
       if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))  
         wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);  
       x = (window_box_right (w, -1)  
            + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);  
       /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill  
          the fringe.  */  
       if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)  
         {  
           b1 = window_box_right (w, -1);  
           b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);  
         }  
     }  
   
   if (b1 >= 0)  
     {  
       int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);  
         
699        /* In case the same realized face is used for fringes and        /* In case the same realized face is used for fringes and
700           for something displayed in the text (e.g. face `region' on           for something displayed in the text (e.g. face `region' on
701           mono-displays, the fill style may have been changed to           mono-displays, the fill style may have been changed to
# Line 972  x_draw_fringe_bitmap (w, row, which, lef Line 704  x_draw_fringe_bitmap (w, row, which, lef
704          XSetFillStyle (display, face->gc, FillOpaqueStippled);          XSetFillStyle (display, face->gc, FillOpaqueStippled);
705        else        else
706          XSetForeground (display, face->gc, face->background);          XSetForeground (display, face->gc, face->background);
707          
708        XFillRectangle (display, window, face->gc,        XFillRectangle (display, window, face->gc,
709                        b1,                        p->bx, p->by, p->nx, p->ny);
710                        WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,  
                                                        row->y)),  
                       b2,  
                       row->visible_height);  
711        if (!face->stipple)        if (!face->stipple)
712          XSetForeground (display, face->gc, face->foreground);          XSetForeground (display, face->gc, face->foreground);
713      }      }
714    
715    if (which != NO_FRINGE_BITMAP)    if (p->which != NO_FRINGE_BITMAP)
716      {      {
717          unsigned char *bits = fringe_bitmaps[p->which].bits + p->dh;
718          Pixmap pixmap;
719          int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
720    
721        /* Draw the bitmap.  I believe these small pixmaps can be cached        /* Draw the bitmap.  I believe these small pixmaps can be cached
722           by the server.  */           by the server.  */
723        pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,        pixmap = XCreatePixmapFromBitmapData (display, window, bits, p->wd, p->h,
724                                              face->foreground,                                              face->foreground,
725                                              face->background, depth);                                              face->background, depth);
726        XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);        XCopyArea (display, pixmap, window, gc, 0, 0,
727                     p->wd, p->h, p->x, p->y);
728        XFreePixmap (display, pixmap);        XFreePixmap (display, pixmap);
729      }      }
     
   XSetClipMask (display, gc, None);  
 }  
730    
731      XSetClipMask (display, gc, None);
 /* Draw fringe bitmaps for glyph row ROW on window W.  Call this  
    function with input blocked.  */  
   
 static void  
 x_draw_row_fringe_bitmaps (w, row)  
      struct window *w;  
      struct glyph_row *row;  
 {  
   struct frame *f = XFRAME (w->frame);  
   enum fringe_bitmap_type bitmap;  
   
   xassert (interrupt_input_blocked);  
   
   /* If row is completely invisible, because of vscrolling, we  
      don't have to draw anything.  */  
   if (row->visible_height <= 0)  
     return;  
   
   if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)  
     {  
       /* Decide which bitmap to draw in the left fringe.  */  
       if (row->overlay_arrow_p)  
         bitmap = OVERLAY_ARROW_BITMAP;  
       else if (row->truncated_on_left_p)  
         bitmap = LEFT_TRUNCATION_BITMAP;  
       else if (MATRIX_ROW_CONTINUATION_LINE_P (row))  
         bitmap = CONTINUATION_LINE_BITMAP;  
       else if (row->indicate_empty_line_p)  
         bitmap = ZV_LINE_BITMAP;  
       else  
         bitmap = NO_FRINGE_BITMAP;  
   
       x_draw_fringe_bitmap (w, row, bitmap, 1);  
     }  
   
   if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)  
     {  
       /* Decide which bitmap to draw in the right fringe.  */  
       if (row->truncated_on_right_p)  
         bitmap = RIGHT_TRUNCATION_BITMAP;  
       else if (row->continued_p)  
         bitmap = CONTINUED_LINE_BITMAP;  
       else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)  
         bitmap = ZV_LINE_BITMAP;  
       else  
         bitmap = NO_FRINGE_BITMAP;  
   
       x_draw_fringe_bitmap (w, row, bitmap, 0);  
     }  
732  }  }
733    
734    
# Line 1072  XTreset_terminal_modes () Line 754  XTreset_terminal_modes ()
754    
755    
756  /***********************************************************************  /***********************************************************************
                             Output Cursor  
  ***********************************************************************/  
   
 /* Set the global variable output_cursor to CURSOR.  All cursor  
    positions are relative to updated_window.  */  
   
 static void  
 set_output_cursor (cursor)  
     struct cursor_pos *cursor;  
 {  
   output_cursor.hpos = cursor->hpos;  
   output_cursor.vpos = cursor->vpos;  
   output_cursor.x = cursor->x;  
   output_cursor.y = cursor->y;  
 }  
   
   
 /* Set a nominal cursor position.  
   
    HPOS and VPOS are column/row positions in a window glyph matrix.  X  
    and Y are window text area relative pixel positions.  
     
    If this is done during an update, updated_window will contain the  
    window that is being updated and the position is the future output  
    cursor position for that window.  If updated_window is null, use  
    selected_window and display the cursor at the given position.  */  
   
 static void  
 XTcursor_to (vpos, hpos, y, x)  
      int vpos, hpos, y, x;  
 {  
   struct window *w;  
   
   /* If updated_window is not set, work on selected_window.  */  
   if (updated_window)  
     w = updated_window;  
   else  
     w = XWINDOW (selected_window);  
   
   /* Set the output cursor.  */  
   output_cursor.hpos = hpos;  
   output_cursor.vpos = vpos;  
   output_cursor.x = x;  
   output_cursor.y = y;  
   
   /* If not called as part of an update, really display the cursor.  
      This will also set the cursor position of W.  */  
   if (updated_window == NULL)  
     {  
       BLOCK_INPUT;  
       x_display_cursor (w, 1, hpos, vpos, x, y);  
       XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));  
       UNBLOCK_INPUT;  
     }  
 }  
   
   
   
 /***********************************************************************  
757                             Display Iterator                             Display Iterator
758   ***********************************************************************/   ***********************************************************************/
759    
760  /* Function prototypes of this page.  */  /* Function prototypes of this page.  */
761    
762  static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,  static int x_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
                                                        struct glyph *,  
                                                        XChar2b *,  
                                                        int *));  
 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,  
                                                       int, XChar2b *, int,  
                                                       int));  
 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));  
 static void x_encode_char P_ ((int, XChar2b *, struct font_info *));  
 static void x_append_glyph P_ ((struct it *));  
 static void x_append_composite_glyph P_ ((struct it *));  
 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,  
                                         int, int, double));  
 static void x_produce_glyphs P_ ((struct it *));  
 static void x_produce_image_glyph P_ ((struct it *it));  
763    
764    
765  /* Get metrics of character CHAR2B in FONT.  Value is null if CHAR2B  /* Get metrics of character CHAR2B in FONT.  Value is null if CHAR2B
766     is not contained in the font.  */     is not contained in the font.  */
767    
768  static INLINE XCharStruct *  static XCharStruct *
769  x_per_char_metric (font, char2b)  x_per_char_metric (font, char2b, font_type)
770       XFontStruct *font;       XFontStruct *font;
771       XChar2b *char2b;       XChar2b *char2b;
772         int font_type;  /* unused on X */
773  {  {
774    /* The result metric information.  */    /* The result metric information.  */
775    XCharStruct *pcm = NULL;    XCharStruct *pcm = NULL;
# Line 1227  x_per_char_metric (font, char2b) Line 837  x_per_char_metric (font, char2b)
837  /* Encode CHAR2B using encoding information from FONT_INFO.  CHAR2B is  /* Encode CHAR2B using encoding information from FONT_INFO.  CHAR2B is
838     the two-byte form of C.  Encoding is returned in *CHAR2B.  */     the two-byte form of C.  Encoding is returned in *CHAR2B.  */
839    
840  static INLINE void  static int
841  x_encode_char (c, char2b, font_info)  x_encode_char (c, char2b, font_info, two_byte_p)
842       int c;       int c;
843       XChar2b *char2b;       XChar2b *char2b;
844       struct font_info *font_info;       struct font_info *font_info;
845         int *two_byte_p;
846  {  {
847    int charset = CHAR_CHARSET (c);    int charset = CHAR_CHARSET (c);
848    XFontStruct *font = font_info->font;    XFontStruct *font = font_info->font;
# Line 1248  x_encode_char (c, char2b, font_info) Line 859  x_encode_char (c, char2b, font_info)
859          {          {
860            ccl->reg[0] = charset;            ccl->reg[0] = charset;
861            ccl->reg[1] = char2b->byte2;            ccl->reg[1] = char2b->byte2;
862              ccl->reg[2] = -1;
863          }          }
864        else        else
865          {          {
# Line 1255  x_encode_char (c, char2b, font_info) Line 867  x_encode_char (c, char2b, font_info)
867            ccl->reg[1] = char2b->byte1;            ccl->reg[1] = char2b->byte1;
868            ccl->reg[2] = char2b->byte2;            ccl->reg[2] = char2b->byte2;
869          }          }
870          
871        ccl_driver (ccl, NULL, NULL, 0, 0, NULL);        ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
872          
873        /* We assume that MSBs are appropriately set/reset by CCL        /* We assume that MSBs are appropriately set/reset by CCL
874           program.  */           program.  */
875        if (font->max_byte1 == 0) /* 1-byte font */        if (font->max_byte1 == 0) /* 1-byte font */
# Line 1270  x_encode_char (c, char2b, font_info) Line 882  x_encode_char (c, char2b, font_info)
882        /* Fixed encoding scheme.  See fontset.h for the meaning of the        /* Fixed encoding scheme.  See fontset.h for the meaning of the
883           encoding numbers.  */           encoding numbers.  */
884        int enc = font_info->encoding[charset];        int enc = font_info->encoding[charset];
885          
886        if ((enc == 1 || enc == 2)        if ((enc == 1 || enc == 2)
887            && CHARSET_DIMENSION (charset) == 2)            && CHARSET_DIMENSION (charset) == 2)
888          char2b->byte1 |= 0x80;          char2b->byte1 |= 0x80;
889          
890        if (enc == 1 || enc == 3)        if (enc == 1 || enc == 3)
891          char2b->byte2 |= 0x80;          char2b->byte2 |= 0x80;
892      }      }
 }  
   
   
 /* Get face and two-byte form of character C in face FACE_ID on frame  
    F.  The encoding of C is returned in *CHAR2B.  MULTIBYTE_P non-zero  
    means we want to display multibyte text.  DISPLAY_P non-zero means  
    make sure that X resources for the face returned are allocated.  
    Value is a pointer to a realized face that is ready for display if  
    DISPLAY_P is non-zero.  */  
   
 static INLINE struct face *  
 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)  
      struct frame *f;  
      int c, face_id;  
      XChar2b *char2b;  
      int multibyte_p, display_p;  
 {  
   struct face *face = FACE_FROM_ID (f, face_id);  
   
   if (!multibyte_p)  
     {  
       /* Unibyte case.  We don't have to encode, but we have to make  
          sure to use a face suitable for unibyte.  */  
       char2b->byte1 = 0;  
       char2b->byte2 = c;  
       face_id = FACE_FOR_CHAR (f, face, c);  
       face = FACE_FROM_ID (f, face_id);  
     }  
   else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)  
     {  
       /* Case of ASCII in a face known to fit ASCII.  */  
       char2b->byte1 = 0;  
       char2b->byte2 = c;  
     }  
   else  
     {  
       int c1, c2, charset;  
         
       /* Split characters into bytes.  If c2 is -1 afterwards, C is  
          really a one-byte character so that byte1 is zero.  */  
       SPLIT_CHAR (c, charset, c1, c2);  
       if (c2 > 0)  
         char2b->byte1 = c1, char2b->byte2 = c2;  
       else  
         char2b->byte1 = 0, char2b->byte2 = c1;  
   
       /* Maybe encode the character in *CHAR2B.  */  
       if (face->font != NULL)  
         {  
           struct font_info *font_info  
             = FONT_INFO_FROM_ID (f, face->font_info_id);  
           if (font_info)  
             x_encode_char (c, char2b, font_info);  
         }  
     }  
   
   /* Make sure X resources of the face are allocated.  */  
   if (display_p)  
     {  
       xassert (face != NULL);  
       PREPARE_FACE_FOR_DISPLAY (f, face);  
     }  
     
   return face;  
 }  
   
   
 /* Get face and two-byte form of character glyph GLYPH on frame F.  
    The encoding of GLYPH->u.ch is returned in *CHAR2B.  Value is  
    a pointer to a realized face that is ready for display.  */  
   
 static INLINE struct face *  
 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)  
      struct frame *f;  
      struct glyph *glyph;  
      XChar2b *char2b;  
      int *two_byte_p;  
 {  
   struct face *face;  
   
   xassert (glyph->type == CHAR_GLYPH);  
   face = FACE_FROM_ID (f, glyph->face_id);  
893    
894    if (two_byte_p)    if (two_byte_p)
895      *two_byte_p = 0;      *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
   
   if (!glyph->multibyte_p)  
     {  
       /* Unibyte case.  We don't have to encode, but we have to make  
          sure to use a face suitable for unibyte.  */  
       char2b->byte1 = 0;  
       char2b->byte2 = glyph->u.ch;  
     }  
   else if (glyph->u.ch < 128  
            && glyph->face_id < BASIC_FACE_ID_SENTINEL)  
     {  
       /* Case of ASCII in a face known to fit ASCII.  */  
       char2b->byte1 = 0;  
       char2b->byte2 = glyph->u.ch;  
     }  
   else  
     {  
       int c1, c2, charset;  
         
       /* Split characters into bytes.  If c2 is -1 afterwards, C is  
          really a one-byte character so that byte1 is zero.  */  
       SPLIT_CHAR (glyph->u.ch, charset, c1, c2);  
       if (c2 > 0)  
         char2b->byte1 = c1, char2b->byte2 = c2;  
       else  
         char2b->byte1 = 0, char2b->byte2 = c1;  
   
       /* Maybe encode the character in *CHAR2B.  */  
       if (charset != CHARSET_ASCII)  
         {  
           struct font_info *font_info  
             = FONT_INFO_FROM_ID (f, face->font_info_id);  
           if (font_info)  
             {  
               x_encode_char (glyph->u.ch, char2b, font_info);  
               if (two_byte_p)  
                 *two_byte_p  
                   = ((XFontStruct *) (font_info->font))->max_byte1 > 0;  
             }  
         }  
     }  
   
   /* Make sure X resources of the face are allocated.  */  
   xassert (face != NULL);  
   PREPARE_FACE_FOR_DISPLAY (f, face);  
   return face;  
 }  
   
   
 /* Store one glyph for IT->char_to_display in IT->glyph_row.    
    Called from x_produce_glyphs when IT->glyph_row is non-null.  */  
   
 static INLINE void  
 x_append_glyph (it)  
      struct it *it;  
 {  
   struct glyph *glyph;  
   enum glyph_row_area area = it->area;  
     
   xassert (it->glyph_row);  
   xassert (it->char_to_display != '\n' && it->char_to_display != '\t');  
     
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];  
   if (glyph < it->glyph_row->glyphs[area + 1])  
     {  
       glyph->charpos = CHARPOS (it->position);  
       glyph->object = it->object;  
       glyph->pixel_width = it->pixel_width;  
       glyph->voffset = it->voffset;  
       glyph->type = CHAR_GLYPH;  
       glyph->multibyte_p = it->multibyte_p;  
       glyph->left_box_line_p = it->start_of_box_run_p;  
       glyph->right_box_line_p = it->end_of_box_run_p;  
       glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent  
                                       || it->phys_descent > it->descent);  
       glyph->padding_p = 0;  
       glyph->glyph_not_available_p = it->glyph_not_available_p;  
       glyph->face_id = it->face_id;  
       glyph->u.ch = it->char_to_display;  
       ++it->glyph_row->used[area];  
     }  
 }  
   
 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.    
    Called from x_produce_glyphs when IT->glyph_row is non-null.  */  
   
 static INLINE void  
 x_append_composite_glyph (it)  
      struct it *it;  
 {  
   struct glyph *glyph;  
   enum glyph_row_area area = it->area;  
     
   xassert (it->glyph_row);  
     
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];  
   if (glyph < it->glyph_row->glyphs[area + 1])  
     {  
       glyph->charpos = CHARPOS (it->position);  
       glyph->object = it->object;  
       glyph->pixel_width = it->pixel_width;  
       glyph->voffset = it->voffset;  
       glyph->type = COMPOSITE_GLYPH;  
       glyph->multibyte_p = it->multibyte_p;  
       glyph->left_box_line_p = it->start_of_box_run_p;  
       glyph->right_box_line_p = it->end_of_box_run_p;  
       glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent  
                                       || it->phys_descent > it->descent);  
       glyph->padding_p = 0;  
       glyph->glyph_not_available_p = 0;  
       glyph->face_id = it->face_id;  
       glyph->u.cmp_id = it->cmp_id;  
       ++it->glyph_row->used[area];  
     }  
 }  
   
   
 /* Change IT->ascent and IT->height according to the setting of  
    IT->voffset.  */  
   
 static INLINE void  
 take_vertical_position_into_account (it)  
      struct it *it;  
 {  
   if (it->voffset)  
     {  
       if (it->voffset < 0)  
         /* Increase the ascent so that we can display the text higher  
            in the line.  */  
         it->ascent += abs (it->voffset);  
       else  
         /* Increase the descent so that we can display the text lower  
            in the line.  */  
         it->descent += it->voffset;  
     }  
 }  
   
   
 /* Produce glyphs/get display metrics for the image IT is loaded with.  
    See the description of struct display_iterator in dispextern.h for  
    an overview of struct display_iterator.  */  
   
 static void  
 x_produce_image_glyph (it)  
      struct it *it;  
 {  
   struct image *img;  
   struct face *face;  
   
   xassert (it->what == IT_IMAGE);  
896    
897    face = FACE_FROM_ID (it->f, it->face_id);    return FONT_TYPE_UNKNOWN;
   img = IMAGE_FROM_ID (it->f, it->image_id);  
   xassert (img);  
   
   /* Make sure X resources of the face and image are loaded.  */  
   PREPARE_FACE_FOR_DISPLAY (it->f, face);  
   prepare_image_for_display (it->f, img);  
   
   it->ascent = it->phys_ascent = image_ascent (img, face);  
   it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;  
   it->pixel_width = img->width + 2 * img->hmargin;  
   
   it->nglyphs = 1;  
     
   if (face->box != FACE_NO_BOX)  
     {  
       if (face->box_line_width > 0)  
         {  
           it->ascent += face->box_line_width;  
           it->descent += face->box_line_width;  
         }  
         
       if (it->start_of_box_run_p)  
         it->pixel_width += abs (face->box_line_width);  
       if (it->end_of_box_run_p)  
         it->pixel_width += abs (face->box_line_width);  
     }  
   
   take_vertical_position_into_account (it);  
     
   if (it->glyph_row)  
     {  
       struct glyph *glyph;  
       enum glyph_row_area area = it->area;  
         
       glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];  
       if (glyph < it->glyph_row->glyphs[area + 1])  
         {  
           glyph->charpos = CHARPOS (it->position);  
           glyph->object = it->object;  
           glyph->pixel_width = it->pixel_width;  
           glyph->voffset = it->voffset;  
           glyph->type = IMAGE_GLYPH;  
           glyph->multibyte_p = it->multibyte_p;  
           glyph->left_box_line_p = it->start_of_box_run_p;  
           glyph->right_box_line_p = it->end_of_box_run_p;  
           glyph->overlaps_vertically_p = 0;  
           glyph->padding_p = 0;  
           glyph->glyph_not_available_p = 0;  
           glyph->face_id = it->face_id;  
           glyph->u.img_id = img->id;  
           ++it->glyph_row->used[area];  
         }  
     }  
898  }  }
899    
900    
 /* Append a stretch glyph to IT->glyph_row.  OBJECT is the source  
    of the glyph, WIDTH and HEIGHT are the width and height of the  
    stretch.  ASCENT is the percentage/100 of HEIGHT to use for the  
    ascent of the glyph (0 <= ASCENT <= 1).  */  
     
 static void  
 x_append_stretch_glyph (it, object, width, height, ascent)  
      struct it *it;  
      Lisp_Object object;  
      int width, height;  
      double ascent;  
 {  
   struct glyph *glyph;  
   enum glyph_row_area area = it->area;  
   
   xassert (ascent >= 0 && ascent <= 1);  
     
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];  
   if (glyph < it->glyph_row->glyphs[area + 1])  
     {  
       glyph->charpos = CHARPOS (it->position);  
       glyph->object = object;  
       glyph->pixel_width = width;  
       glyph->voffset = it->voffset;  
       glyph->type = STRETCH_GLYPH;  
       glyph->multibyte_p = it->multibyte_p;  
       glyph->left_box_line_p = it->start_of_box_run_p;  
       glyph->right_box_line_p = it->end_of_box_run_p;  
       glyph->overlaps_vertically_p = 0;  
       glyph->padding_p = 0;  
       glyph->glyph_not_available_p = 0;  
       glyph->face_id = it->face_id;  
       glyph->u.stretch.ascent = height * ascent;  
       glyph->u.stretch.height = height;  
       ++it->glyph_row->used[area];  
     }  
 }  
   
   
 /* Produce a stretch glyph for iterator IT.  IT->object is the value  
    of the glyph property displayed.  The value must be a list  
    `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs  
    being recognized:  
   
    1. `:width WIDTH' specifies that the space should be WIDTH *  
    canonical char width wide.  WIDTH may be an integer or floating  
    point number.  
   
    2. `:relative-width FACTOR' specifies that the width of the stretch  
    should be computed from the width of the first character having the  
    `glyph' property, and should be FACTOR times that width.  
   
    3. `:align-to HPOS' specifies that the space should be wide enough  
    to reach HPOS, a value in canonical character units.  
   
    Exactly one of the above pairs must be present.    
   
    4. `:height HEIGHT' specifies that the height of the stretch produced  
    should be HEIGHT, measured in canonical character units.  
   
    5. `:relative-height FACTOR' specifies that the height of the  
    stretch should be FACTOR times the height of the characters having  
    the glyph property.  
   
    Either none or exactly one of 4 or 5 must be present.  
   
    6. `:ascent ASCENT'  specifies that ASCENT percent of the height  
    of the stretch should be used for the ascent of the stretch.  
    ASCENT must be in the range 0 <= ASCENT <= 100.  */  
   
 #define NUMVAL(X)                               \  
      ((INTEGERP (X) || FLOATP (X))              \  
       ? XFLOATINT (X)                           \  
       : - 1)  
   
   
 static void  
 x_produce_stretch_glyph (it)  
      struct it *it;  
 {  
   /* (space :width WIDTH :height HEIGHT.  */  
 #if GLYPH_DEBUG  
   extern Lisp_Object Qspace;  
 #endif  
   extern Lisp_Object QCwidth, QCheight, QCascent;  
   extern Lisp_Object QCrelative_width, QCrelative_height;  
   extern Lisp_Object QCalign_to;  
   Lisp_Object prop, plist;  
   double width = 0, height = 0, ascent = 0;  
   struct face *face = FACE_FROM_ID (it->f, it->face_id);  
   XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);  
   
   PREPARE_FACE_FOR_DISPLAY (it->f, face);  
     
   /* List should start with `space'.  */  
   xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));  
   plist = XCDR (it->object);  
   
   /* Compute the width of the stretch.  */  
   if (prop = Fplist_get (plist, QCwidth),  
       NUMVAL (prop) > 0)  
     /* Absolute width `:width WIDTH' specified and valid.  */  
     width = NUMVAL (prop) * CANON_X_UNIT (it->f);  
   else if (prop = Fplist_get (plist, QCrelative_width),  
            NUMVAL (prop) > 0)  
     {  
       /* Relative width `:relative-width FACTOR' specified and valid.  
          Compute the width of the characters having the `glyph'  
          property.  */  
       struct it it2;  
       unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));  
         
       it2 = *it;  
       if (it->multibyte_p)  
         {  
           int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)  
                         - IT_BYTEPOS (*it));  
           it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);  
         }  
       else  
         it2.c = *p, it2.len = 1;  
   
       it2.glyph_row = NULL;  
       it2.what = IT_CHARACTER;  
       x_produce_glyphs (&it2);  
       width = NUMVAL (prop) * it2.pixel_width;  
     }  
   else if (prop = Fplist_get (plist, QCalign_to),  
            NUMVAL (prop) > 0)  
     width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;  
   else  
     /* Nothing specified -> width defaults to canonical char width.  */  
     width = CANON_X_UNIT (it->f);  
     
   /* Compute height.  */  
   if (prop = Fplist_get (plist, QCheight),  
       NUMVAL (prop) > 0)  
     height = NUMVAL (prop) * CANON_Y_UNIT (it->f);  
   else if (prop = Fplist_get (plist, QCrelative_height),  
            NUMVAL (prop) > 0)  
     height = FONT_HEIGHT (font) * NUMVAL (prop);  
   else  
     height = FONT_HEIGHT (font);  
   
   /* Compute percentage of height used for ascent.  If  
      `:ascent ASCENT' is present and valid, use that.  Otherwise,  
      derive the ascent from the font in use.  */  
   if (prop = Fplist_get (plist, QCascent),  
       NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)  
     ascent = NUMVAL (prop) / 100.0;  
   else  
     ascent = (double) font->ascent / FONT_HEIGHT (font);  
   
   if (width <= 0)  
     width = 1;  
   if (height <= 0)  
     height = 1;  
   
   if (it->glyph_row)  
     {  
       Lisp_Object object = it->stack[it->sp - 1].string;  
       if (!STRINGP (object))  
         object = it->w->buffer;  
       x_append_stretch_glyph (it, object, width, height, ascent);  
     }  
   
   it->pixel_width = width;  
   it->ascent = it->phys_ascent = height * ascent;  
   it->descent = it->phys_descent = height - it->ascent;  
   it->nglyphs = 1;  
   
   if (face->box != FACE_NO_BOX)  
     {  
       if (face->box_line_width > 0)  
         {  
           it->ascent += face->box_line_width;  
           it->descent += face->box_line_width;  
         }  
         
       if (it->start_of_box_run_p)  
         it->pixel_width += abs (face->box_line_width);  
       if (it->end_of_box_run_p)  
         it->pixel_width += abs (face->box_line_width);  
     }  
     
   take_vertical_position_into_account (it);  
 }  
   
 /* Return proper value to be used as baseline offset of font that has  
    ASCENT and DESCENT to draw characters by the font at the vertical  
    center of the line of frame F.  
   
    Here, out task is to find the value of BOFF in the following figure;  
   
         -------------------------+-----------+-  
          -+-+---------+-+        |           |  
           | |         | |        |           |  
           | |         | |        F_ASCENT    F_HEIGHT  
           | |         | ASCENT   |           |  
      HEIGHT |         | |        |           |  
           | |         |-|-+------+-----------|------- baseline  
           | |         | | BOFF   |           |  
           | |---------|-+-+      |           |  
           | |         | DESCENT  |           |  
          -+-+---------+-+        F_DESCENT   |  
         -------------------------+-----------+-  
   
         -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT  
         BOFF = DESCENT +  (F_HEIGHT - HEIGHT) / 2 - F_DESCENT  
         DESCENT = FONT->descent  
         HEIGHT = FONT_HEIGHT (FONT)  
         F_DESCENT = (F->output_data.x->font->descent  
                      - F->output_data.x->baseline_offset)  
         F_HEIGHT = FRAME_LINE_HEIGHT (F)  
 */  
   
 #define VCENTER_BASELINE_OFFSET(FONT, F)                        \  
   ((FONT)->descent                                              \  
    + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))            \  
       + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2   \  
    - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))  
   
 /* Produce glyphs/get display metrics for the display element IT is  
    loaded with.  See the description of struct display_iterator in  
    dispextern.h for an overview of struct display_iterator.  */  
   
 static void  
 x_produce_glyphs (it)  
      struct it *it;  
 {  
   it->glyph_not_available_p = 0;  
   
   if (it->what == IT_CHARACTER)  
     {  
       XChar2b char2b;  
       XFontStruct *font;  
       struct face *face = FACE_FROM_ID (it->f, it->face_id);  
       XCharStruct *pcm;  
       int font_not_found_p;  
       struct font_info *font_info;  
       int boff;                 /* baseline offset */  
       /* We may change it->multibyte_p upon unibyte<->multibyte  
          conversion.  So, save the current value now and restore it  
          later.  
   
          Note: It seems that we don't have to record multibyte_p in  
          struct glyph because the character code itself tells if or  
          not the character is multibyte.  Thus, in the future, we must  
          consider eliminating the field `multibyte_p' in the struct  
          glyph.  */  
       int saved_multibyte_p = it->multibyte_p;  
   
       /* Maybe translate single-byte characters to multibyte, or the  
          other way.  */  
       it->char_to_display = it->c;  
       if (!ASCII_BYTE_P (it->c))  
         {  
           if (unibyte_display_via_language_environment  
               && SINGLE_BYTE_CHAR_P (it->c)  
               && (it->c >= 0240  
                   || !NILP (Vnonascii_translation_table)))  
             {  
               it->char_to_display = unibyte_char_to_multibyte (it->c);  
               it->multibyte_p = 1;  
               it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);  
               face = FACE_FROM_ID (it->f, it->face_id);  
             }  
           else if (!SINGLE_BYTE_CHAR_P (it->c)  
                    && !it->multibyte_p)  
             {  
               it->multibyte_p = 1;  
               it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);  
               face = FACE_FROM_ID (it->f, it->face_id);  
             }  
         }  
         
       /* Get font to use.  Encode IT->char_to_display.  */  
       x_get_char_face_and_encoding (it->f, it->char_to_display,  
                                     it->face_id, &char2b,  
                                     it->multibyte_p, 0);  
       font = face->font;  
   
       /* When no suitable font found, use the default font.  */  
       font_not_found_p = font == NULL;  
       if (font_not_found_p)  
         {  
           font = FRAME_FONT (it->f);  
           boff = it->f->output_data.x->baseline_offset;  
           font_info = NULL;  
         }  
       else  
         {  
           font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);  
           boff = font_info->baseline_offset;  
           if (font_info->vertical_centering)  
             boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;  
         }  
   
       if (it->char_to_display >= ' '  
           && (!it->multibyte_p || it->char_to_display < 128))  
         {  
           /* Either unibyte or ASCII.  */  
           int stretched_p;  
   
           it->nglyphs = 1;  
   
           pcm = x_per_char_metric (font, &char2b);  
           it->ascent = font->ascent + boff;  
           it->descent = font->descent - boff;  
   
           if (pcm)  
             {  
               it->phys_ascent = pcm->ascent + boff;  
               it->phys_descent = pcm->descent - boff;  
               it->pixel_width = pcm->width;  
             }  
           else  
             {  
               it->glyph_not_available_p = 1;  
               it->phys_ascent = font->ascent + boff;  
               it->phys_descent = font->descent - boff;  
               it->pixel_width = FONT_WIDTH (font);  
             }  
   
           /* If this is a space inside a region of text with  
              `space-width' property, change its width.  */  
           stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);  
           if (stretched_p)  
             it->pixel_width *= XFLOATINT (it->space_width);  
   
           /* If face has a box, add the box thickness to the character  
              height.  If character has a box line to the left and/or  
              right, add the box line width to the character's width.  */  
           if (face->box != FACE_NO_BOX)  
             {  
               int thick = face->box_line_width;  
                 
               if (thick > 0)  
                 {  
                   it->ascent += thick;  
                   it->descent += thick;  
                 }  
               else  
                 thick = -thick;  
   
               if (it->start_of_box_run_p)  
                 it->pixel_width += thick;  
               if (it->end_of_box_run_p)  
                 it->pixel_width += thick;  
             }  
   
           /* If face has an overline, add the height of the overline  
              (1 pixel) and a 1 pixel margin to the character height.  */  
           if (face->overline_p)  
             it->ascent += 2;  
   
           take_vertical_position_into_account (it);  
     
           /* If we have to actually produce glyphs, do it.  */  
           if (it->glyph_row)  
             {  
               if (stretched_p)  
                 {  
                   /* Translate a space with a `space-width' property  
                      into a stretch glyph.  */  
                   double ascent = (double) font->ascent / FONT_HEIGHT (font);  
                   x_append_stretch_glyph (it, it->object, it->pixel_width,  
                                           it->ascent + it->descent, ascent);  
                 }  
               else  
                 x_append_glyph (it);  
   
               /* If characters with lbearing or rbearing are displayed  
                  in this line, record that fact in a flag of the  
                  glyph row.  This is used to optimize X output code.  */  
               if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))  
                 it->glyph_row->contains_overlapping_glyphs_p = 1;  
             }  
         }  
       else if (it->char_to_display == '\n')  
         {  
           /* A newline has no width but we need the height of the line.  */  
           it->pixel_width = 0;  
           it->nglyphs = 0;  
           it->ascent = it->phys_ascent = font->ascent + boff;  
           it->descent = it->phys_descent = font->descent - boff;  
         
           if (face->box != FACE_NO_BOX  
               && face->box_line_width > 0)  
             {  
               it->ascent += face->box_line_width;  
               it->descent += face->box_line_width;  
             }  
         }  
       else if (it->char_to_display == '\t')  
         {  
           int tab_width = it->tab_width * CANON_X_UNIT (it->f);  
           int x = it->current_x + it->continuation_lines_width;  
           int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;  
   
           /* If the distance from the current position to the next tab  
              stop is less than a canonical character width, use the  
              tab stop after that.  */  
           if (next_tab_x - x < CANON_X_UNIT (it->f))  
             next_tab_x += tab_width;  
         
           it->pixel_width = next_tab_x - x;  
           it->nglyphs = 1;  
           it->ascent = it->phys_ascent = font->ascent + boff;  
           it->descent = it->phys_descent = font->descent - boff;  
             
           if (it->glyph_row)  
             {  
               double ascent = (double) it->ascent / (it->ascent + it->descent);  
               x_append_stretch_glyph (it, it->object, it->pixel_width,  
                                       it->ascent + it->descent, ascent);  
             }  
         }  
       else  
         {  
           /* A multi-byte character.  Assume that the display width of the  
              character is the width of the character multiplied by the  
              width of the font.  */  
   
           /* If we found a font, this font should give us the right  
              metrics.  If we didn't find a font, use the frame's  
              default font and calculate the width of the character  
              from the charset width; this is what old redisplay code  
              did.  */  
           pcm = x_per_char_metric (font, &char2b);  
           if (font_not_found_p || !pcm)  
             {  
               int charset = CHAR_CHARSET (it->char_to_display);  
   
               it->glyph_not_available_p = 1;  
               it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))  
                                  * CHARSET_WIDTH (charset));  
               it->phys_ascent = font->ascent + boff;  
               it->phys_descent = font->descent - boff;  
             }  
           else  
             {  
               it->pixel_width = pcm->width;  
               it->phys_ascent = pcm->ascent + boff;  
               it->phys_descent = pcm->descent - boff;  
               if (it->glyph_row  
                   && (pcm->lbearing < 0  
                       || pcm->rbearing > pcm->width))  
                 it->glyph_row->contains_overlapping_glyphs_p = 1;  
             }  
           it->nglyphs = 1;  
           it->ascent = font->ascent + boff;  
           it->descent = font->descent - boff;  
           if (face->box != FACE_NO_BOX)  
             {  
               int thick = face->box_line_width;  
   
               if (thick > 0)  
                 {  
                   it->ascent += thick;  
                   it->descent += thick;  
                 }  
               else  
                 thick = - thick;  
             
               if (it->start_of_box_run_p)  
                 it->pixel_width += thick;  
               if (it->end_of_box_run_p)  
                 it->pixel_width += thick;  
             }  
     
           /* If face has an overline, add the height of the overline  
              (1 pixel) and a 1 pixel margin to the character height.  */  
           if (face->overline_p)  
             it->ascent += 2;  
   
           take_vertical_position_into_account (it);  
     
           if (it->glyph_row)  
             x_append_glyph (it);  
         }  
       it->multibyte_p = saved_multibyte_p;  
     }  
   else if (it->what == IT_COMPOSITION)  
     {  
       /* Note: A composition is represented as one glyph in the  
          glyph matrix.  There are no padding glyphs.  */  
       XChar2b char2b;  
       XFontStruct *font;  
       struct face *face = FACE_FROM_ID (it->f, it->face_id);  
       XCharStruct *pcm;  
       int font_not_found_p;  
       struct font_info *font_info;  
       int boff;                 /* baseline offset */  
       struct composition *cmp = composition_table[it->cmp_id];  
   
       /* Maybe translate single-byte characters to multibyte.  */  
       it->char_to_display = it->c;  
       if (unibyte_display_via_language_environment  
           && SINGLE_BYTE_CHAR_P (it->c)  
           && (it->c >= 0240  
               || (it->c >= 0200  
                   && !NILP (Vnonascii_translation_table))))  
         {  
           it->char_to_display = unibyte_char_to_multibyte (it->c);  
         }  
         
       /* Get face and font to use.  Encode IT->char_to_display.  */  
       it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);  
       face = FACE_FROM_ID (it->f, it->face_id);  
       x_get_char_face_and_encoding (it->f, it->char_to_display,  
                                     it->face_id, &char2b, it->multibyte_p, 0);  
       font = face->font;  
   
       /* When no suitable font found, use the default font.  */  
       font_not_found_p = font == NULL;  
       if (font_not_found_p)  
         {  
           font = FRAME_FONT (it->f);  
           boff = it->f->output_data.x->baseline_offset;  
           font_info = NULL;  
         }  
       else  
         {  
           font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);  
           boff = font_info->baseline_offset;  
           if (font_info->vertical_centering)  
             boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;  
         }  
   
       /* There are no padding glyphs, so there is only one glyph to  
          produce for the composition.  Important is that pixel_width,  
          ascent and descent are the values of what is drawn by  
          draw_glyphs (i.e. the values of the overall glyphs composed).  */  
       it->nglyphs = 1;  
   
       /* If we have not yet calculated pixel size data of glyphs of  
          the composition for the current face font, calculate them  
          now.  Theoretically, we have to check all fonts for the  
          glyphs, but that requires much time and memory space.  So,  
          here we check only the font of the first glyph.  This leads  
          to incorrect display very rarely, and C-l (recenter) can  
          correct the display anyway.  */  
       if (cmp->font != (void *) font)  
         {  
           /* Ascent and descent of the font of the first character of  
              this composition (adjusted by baseline offset).  Ascent  
              and descent of overall glyphs should not be less than  
              them respectively.  */  
           int font_ascent = font->ascent + boff;  
           int font_descent = font->descent - boff;  
           /* Bounding box of the overall glyphs.  */  
           int leftmost, rightmost, lowest, highest;  
           int i, width, ascent, descent;  
   
           cmp->font = (void *) font;  
   
           /* Initialize the bounding box.  */  
           if (font_info  
               && (pcm = x_per_char_metric (font, &char2b)))  
             {  
               width = pcm->width;  
               ascent = pcm->ascent;  
               descent = pcm->descent;  
             }  
           else  
             {  
               width = FONT_WIDTH (font);  
               ascent = font->ascent;  
               descent = font->descent;  
             }  
             
           rightmost = width;  
           lowest = - descent + boff;  
           highest = ascent + boff;  
           leftmost = 0;  
             
           if (font_info  
               && font_info->default_ascent  
               && CHAR_TABLE_P (Vuse_default_ascent)  
               && !NILP (Faref (Vuse_default_ascent,  
                                make_number (it->char_to_display))))  
             highest = font_info->default_ascent + boff;  
   
           /* Draw the first glyph at the normal position.  It may be  
              shifted to right later if some other glyphs are drawn at  
              the left.  */  
           cmp->offsets[0] = 0;  
           cmp->offsets[1] = boff;  
   
           /* Set cmp->offsets for the remaining glyphs.  */  
           for (i = 1; i < cmp->glyph_len; i++)  
             {  
               int left, right, btm, top;  
               int ch = COMPOSITION_GLYPH (cmp, i);  
               int face_id = FACE_FOR_CHAR (it->f, face, ch);  
                 
               face = FACE_FROM_ID (it->f, face_id);  
               x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,  
                                             it->multibyte_p, 0);  
               font = face->font;  
               if (font == NULL)  
                 {  
                   font = FRAME_FONT (it->f);  
                   boff = it->f->output_data.x->baseline_offset;  
                   font_info = NULL;  
                 }  
               else  
                 {  
                   font_info  
                     = FONT_INFO_FROM_ID (it->f, face->font_info_id);  
                   boff = font_info->baseline_offset;  
                   if (font_info->vertical_centering)  
                     boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;  
                 }  
   
               if (font_info  
                   && (pcm = x_per_char_metric (font, &char2b)))  
                 {  
                   width = pcm->width;  
                   ascent = pcm->ascent;  
                   descent = pcm->descent;  
                 }  
               else  
                 {  
                   width = FONT_WIDTH (font);  
                   ascent = 1;  
                   descent = 0;  
                 }  
   
               if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)  
                 {  
                   /* Relative composition with or without  
                      alternate chars.  */  
                   left = (leftmost + rightmost - width) / 2;  
                   btm = - descent + boff;  
                   if (font_info && font_info->relative_compose  
                       && (! CHAR_TABLE_P (Vignore_relative_composition)  
                           || NILP (Faref (Vignore_relative_composition,  
                                           make_number (ch)))))  
                     {  
   
                       if (- descent >= font_info->relative_compose)  
                         /* One extra pixel between two glyphs.  */  
                         btm = highest + 1;  
                       else if (ascent <= 0)  
                         /* One extra pixel between two glyphs.  */  
                         btm = lowest - 1 - ascent - descent;  
                     }  
                 }  
               else  
                 {  
                   /* A composition rule is specified by an integer  
                      value that encodes global and new reference  
                      points (GREF and NREF).  GREF and NREF are  
                      specified by numbers as below:  
   
                         0---1---2 -- ascent  
                         |       |  
                         |       |  
                         |       |  
                         9--10--11 -- center  
                         |       |  
                      ---3---4---5--- baseline  
                         |       |  
                         6---7---8 -- descent  
                   */  
                   int rule = COMPOSITION_RULE (cmp, i);  
                   int gref, nref, grefx, grefy, nrefx, nrefy;  
   
                   COMPOSITION_DECODE_RULE (rule, gref, nref);  
                   grefx = gref % 3, nrefx = nref % 3;  
                   grefy = gref / 3, nrefy = nref / 3;  
   
                   left = (leftmost  
                           + grefx * (rightmost - leftmost) / 2  
                           - nrefx * width / 2);  
                   btm = ((grefy == 0 ? highest  
                           : grefy == 1 ? 0  
                           : grefy == 2 ? lowest  
                           : (highest + lowest) / 2)  
                          - (nrefy == 0 ? ascent + descent  
                             : nrefy == 1 ? descent - boff  
                             : nrefy == 2 ? 0  
                             : (ascent + descent) / 2));  
                 }  
   
               cmp->offsets[i * 2] = left;  
               cmp->offsets[i * 2 + 1] = btm + descent;  
   
               /* Update the bounding box of the overall glyphs. */  
               right = left + width;  
               top = btm + descent + ascent;  
               if (left < leftmost)  
                 leftmost = left;  
               if (right > rightmost)  
                 rightmost = right;  
               if (top > highest)  
                 highest = top;  
               if (btm < lowest)  
                 lowest = btm;  
             }  
   
           /* If there are glyphs whose x-offsets are negative,  
              shift all glyphs to the right and make all x-offsets  
              non-negative.  */  
           if (leftmost < 0)  
             {  
               for (i = 0; i < cmp->glyph_len; i++)  
                 cmp->offsets[i * 2] -= leftmost;  
               rightmost -= leftmost;  
             }  
   
           cmp->pixel_width = rightmost;  
           cmp->ascent = highest;  
           cmp->descent = - lowest;  
           if (cmp->ascent < font_ascent)  
             cmp->ascent = font_ascent;  
           if (cmp->descent < font_descent)  
             cmp->descent = font_descent;  
         }  
   
       it->pixel_width = cmp->pixel_width;  
       it->ascent = it->phys_ascent = cmp->ascent;  
       it->descent = it->phys_descent = cmp->descent;  
   
       if (face->box != FACE_NO_BOX)  
         {  
           int thick = face->box_line_width;  
   
           if (thick > 0)  
             {  
               it->ascent += thick;  
               it->descent += thick;  
             }  
           else  
             thick = - thick;  
             
           if (it->start_of_box_run_p)  
             it->pixel_width += thick;  
           if (it->end_of_box_run_p)  
             it->pixel_width += thick;  
         }  
     
       /* If face has an overline, add the height of the overline  
          (1 pixel) and a 1 pixel margin to the character height.  */  
       if (face->overline_p)  
         it->ascent += 2;  
   
       take_vertical_position_into_account (it);  
     
       if (it->glyph_row)  
         x_append_composite_glyph (it);  
     }  
   else if (it->what == IT_IMAGE)  
     x_produce_image_glyph (it);  
   else if (it->what == IT_STRETCH)  
     x_produce_stretch_glyph (it);  
   
   /* Accumulate dimensions.  Note: can't assume that it->descent > 0  
      because this isn't true for images with `:ascent 100'.  */  
   xassert (it->ascent >= 0 && it->descent >= 0);  
   if (it->area == TEXT_AREA)  
     it->current_x += it->pixel_width;  
     
   it->descent += it->extra_line_spacing;  
     
   it->max_ascent = max (it->max_ascent, it->ascent);  
   it->max_descent = max (it->max_descent, it->descent);  
   it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);  
   it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);  
 }  
   
   
 /* Estimate the pixel height of the mode or top line on frame F.  
    FACE_ID specifies what line's height to estimate.  */  
   
 int  
 x_estimate_mode_line_height (f, face_id)  
      struct frame *f;  
      enum face_id face_id;  
 {  
   int height = FONT_HEIGHT (FRAME_FONT (f));  
   
   /* This function is called so early when Emacs starts that the face  
      cache and mode line face are not yet initialized.  */  
   if (FRAME_FACE_CACHE (f))  
       {  
         struct face *face = FACE_FROM_ID (f, face_id);  
         if (face)  
           {  
             if (face->font)  
               height = FONT_HEIGHT (face->font);  
             if (face->box_line_width > 0)  
               height += 2 * face->box_line_width;  
           }  
       }  
     
   return height;  
 }  
   
901    
902  /***********************************************************************  /***********************************************************************
903                              Glyph display                              Glyph display
904   ***********************************************************************/   ***********************************************************************/
905    
 /* A sequence of glyphs to be drawn in the same face.  
   
    This data structure is not really completely X specific, so it  
    could possibly, at least partially, be useful for other systems.  It  
    is currently not part of the external redisplay interface because  
    it's not clear what other systems will need.  */  
   
 struct glyph_string  
 {  
   /* X-origin of the string.  */  
   int x;  
   
   /* Y-origin and y-position of the base line of this string.  */  
   int y, ybase;  
   
   /* The width of the string, not including a face extension.  */  
   int width;  
   
   /* The width of the string, including a face extension.  */  
   int background_width;  
   
   /* The height of this string.  This is the height of the line this  
      string is drawn in, and can be different from the height of the  
      font the string is drawn in.  */  
   int height;  
   
   /* Number of pixels this string overwrites in front of its x-origin.  
      This number is zero if the string has an lbearing >= 0; it is  
      -lbearing, if the string has an lbearing < 0.  */  
   int left_overhang;  
   
   /* Number of pixels this string overwrites past its right-most  
      nominal x-position, i.e. x + width.  Zero if the string's  
      rbearing is <= its nominal width, rbearing - width otherwise.  */  
   int right_overhang;  
   
   /* The frame on which the glyph string is drawn.  */  
   struct frame *f;  
   
   /* The window on which the glyph string is drawn.  */  
   struct window *w;  
   
   /* X display and window for convenience.  */  
   Display *display;  
   Window window;  
   
   /* The glyph row for which this string was built.  It determines the  
      y-origin and height of the string.  */  
   struct glyph_row *row;  
   
   /* The area within row.  */  
   enum glyph_row_area area;  
   
   /* Characters to be drawn, and number of characters.  */  
   XChar2b *char2b;  
   int nchars;  
   
   /* A face-override for drawing cursors, mouse face and similar.  */  
   enum draw_glyphs_face hl;  
   
   /* Face in which this string is to be drawn.  */  
   struct face *face;  
   
   /* Font in which this string is to be drawn.  */  
   XFontStruct *font;  
   
   /* Font info for this string.  */  
   struct font_info *font_info;  
   
   /* Non-null means this string describes (part of) a composition.  
      All characters from char2b are drawn composed.  */  
   struct composition *cmp;  
   
   /* Index of this glyph string's first character in the glyph  
      definition of CMP.  If this is zero, this glyph string describes  
      the first character of a composition.  */  
   int gidx;  
   
   /* 1 means this glyph strings face has to be drawn to the right end  
      of the window's drawing area.  */  
   unsigned extends_to_end_of_line_p : 1;  
   
   /* 1 means the background of this string has been drawn.  */  
   unsigned background_filled_p : 1;  
   
   /* 1 means glyph string must be drawn with 16-bit functions.  */  
   unsigned two_byte_p : 1;  
   
   /* 1 means that the original font determined for drawing this glyph  
      string could not be loaded.  The member `font' has been set to  
      the frame's default font in this case.  */  
   unsigned font_not_found_p : 1;  
   
   /* 1 means that the face in which this glyph string is drawn has a  
      stipple pattern.  */  
   unsigned stippled_p : 1;  
   
   /* 1 means only the foreground of this glyph string must be drawn,  
      and we should use the physical height of the line this glyph  
      string appears in as clip rect.  */  
   unsigned for_overlaps_p : 1;  
   
   /* The GC to use for drawing this glyph string.  */  
   GC gc;  
   
   /* A pointer to the first glyph in the string.  This glyph  
      corresponds to char2b[0].  Needed to draw rectangles if  
      font_not_found_p is 1.  */  
   struct glyph *first_glyph;  
   
   /* Image, if any.  */  
   struct image *img;  
   
   struct glyph_string *next, *prev;  
 };  
   
   
 #if GLYPH_DEBUG  
   
 static void  
 x_dump_glyph_string (s)  
      struct glyph_string *s;  
 {  
   fprintf (stderr, "glyph string\n");  
   fprintf (stderr, "  x, y, w, h = %d, %d, %d, %d\n",  
            s->x, s->y, s->width, s->height);  
   fprintf (stderr, "  ybase = %d\n", s->ybase);  
   fprintf (stderr, "  hl = %d\n", s->hl);  
   fprintf (stderr, "  left overhang = %d, right = %d\n",  
            s->left_overhang, s->right_overhang);  
   fprintf (stderr, "  nchars = %d\n", s->nchars);  
   fprintf (stderr, "  extends to end of line = %d\n",  
            s->extends_to_end_of_line_p);  
   fprintf (stderr, "  font height = %d\n", FONT_HEIGHT (s->font));  
   fprintf (stderr, "  bg width = %d\n", s->background_width);  
 }  
   
 #endif /* GLYPH_DEBUG */  
906    
907    
   
 static void x_append_glyph_string_lists P_ ((struct glyph_string **,  
                                              struct glyph_string **,  
                                              struct glyph_string *,  
                                              struct glyph_string *));  
 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,  
                                               struct glyph_string **,  
                                               struct glyph_string *,  
                                               struct glyph_string *));  
 static void x_append_glyph_string P_ ((struct glyph_string **,  
                                        struct glyph_string **,  
                                        struct glyph_string *));  
 static int x_left_overwritten P_ ((struct glyph_string *));  
 static int x_left_overwriting P_ ((struct glyph_string *));  
 static int x_right_overwritten P_ ((struct glyph_string *));  
 static int x_right_overwriting P_ ((struct glyph_string *));  
 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,  
                                     int));  
 static void x_init_glyph_string P_ ((struct glyph_string *,  
                                         XChar2b *, struct window *,  
                                         struct glyph_row *,  
                                         enum glyph_row_area, int,  
                                         enum draw_glyphs_face));  
 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,  
                               enum glyph_row_area, int, int,  
                               enum draw_glyphs_face, int));  
908  static void x_set_glyph_string_clipping P_ ((struct glyph_string *));  static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
909  static void x_set_glyph_string_gc P_ ((struct glyph_string *));  static void x_set_glyph_string_gc P_ ((struct glyph_string *));
910  static void x_draw_glyph_string_background P_ ((struct glyph_string *,  static void x_draw_glyph_string_background P_ ((struct glyph_string *,
# Line 2555  static void x_compute_glyph_string_overh Line 917  static void x_compute_glyph_string_overh
917  static void x_set_cursor_gc P_ ((struct glyph_string *));  static void x_set_cursor_gc P_ ((struct glyph_string *));
918  static void x_set_mode_line_face_gc P_ ((struct glyph_string *));  static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
919  static void x_set_mouse_face_gc P_ ((struct glyph_string *));  static void x_set_mouse_face_gc P_ ((struct glyph_string *));
 static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,  
                                        int *, int *));  
 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));  
920  static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,  static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
921                                        unsigned long *, double, int));                                        unsigned long *, double, int));
922  static void x_setup_relief_color P_ ((struct frame *, struct relief *,  static void x_setup_relief_color P_ ((struct frame *, struct relief *,
# Line 2567  static void x_draw_image_glyph_string P_ Line 926  static void x_draw_image_glyph_string P_
926  static void x_draw_image_relief P_ ((struct glyph_string *));  static void x_draw_image_relief P_ ((struct glyph_string *));
927  static void x_draw_image_foreground P_ ((struct glyph_string *));  static void x_draw_image_foreground P_ ((struct glyph_string *));
928  static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));  static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
 static void x_fill_image_glyph_string P_ ((struct glyph_string *));  
929  static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,  static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
930                                             int, int, int));                                             int, int, int));
931  static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,  static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
932                                      int, int, int, int, XRectangle *));                                      int, int, int, int, XRectangle *));
933  static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,  static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
934                                   int, int, int, XRectangle *));                                   int, int, int, XRectangle *));
 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,  
                                         enum glyph_row_area));  
 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,  
                                             struct glyph_row *,  
                                             enum glyph_row_area, int, int));  
935    
936  #if GLYPH_DEBUG  #if GLYPH_DEBUG
937  static void x_check_font P_ ((struct frame *, XFontStruct *));  static void x_check_font P_ ((struct frame *, XFontStruct *));
938  #endif  #endif
939    
940    
 /* Append the list of glyph strings with head H and tail T to the list  
    with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the result.  */  
   
 static INLINE void  
 x_append_glyph_string_lists (head, tail, h, t)  
      struct glyph_string **head, **tail;  
      struct glyph_string *h, *t;  
 {  
   if (h)  
     {  
       if (*head)  
         (*tail)->next = h;  
       else  
         *head = h;  
       h->prev = *tail;  
       *tail = t;  
     }  
 }  
   
   
 /* Prepend the list of glyph strings with head H and tail T to the  
    list with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the  
    result.  */  
   
 static INLINE void  
 x_prepend_glyph_string_lists (head, tail, h, t)  
      struct glyph_string **head, **tail;  
      struct glyph_string *h, *t;  
 {  
   if (h)  
     {  
       if (*head)  
         (*head)->prev = t;  
       else  
         *tail = t;  
       t->next = *head;  
       *head = h;  
     }  
 }  
   
   
 /* Append glyph string S to the list with head *HEAD and tail *TAIL.  
    Set *HEAD and *TAIL to the resulting list.  */  
   
 static INLINE void  
 x_append_glyph_string (head, tail, s)  
      struct glyph_string **head, **tail;  
      struct glyph_string *s;  
 {  
   s->next = s->prev = NULL;  
   x_append_glyph_string_lists (head, tail, s, s);  
 }  
   
   
941  /* Set S->gc to a suitable GC for drawing glyph string S in cursor  /* Set S->gc to a suitable GC for drawing glyph string S in cursor
942     face.  */     face.  */
943    
# Line 2694  x_set_cursor_gc (s) Line 993  x_set_cursor_gc (s)
993    
994    
995  /* Set up S->gc of glyph string S for drawing text in mouse face.  */  /* Set up S->gc of glyph string S for drawing text in mouse face.  */
996      
997  static void  static void
998  x_set_mouse_face_gc (s)  x_set_mouse_face_gc (s)
999       struct glyph_string *s;       struct glyph_string *s;
1000  {      {
1001    int face_id;    int face_id;
1002    struct face *face;    struct face *face;
1003    
# Line 2707  x_set_mouse_face_gc (s) Line 1006  x_set_mouse_face_gc (s)
1006    face = FACE_FROM_ID (s->f, face_id);    face = FACE_FROM_ID (s->f, face_id);
1007    if (face == NULL)    if (face == NULL)
1008      face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);      face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1009      
1010    if (s->first_glyph->type == CHAR_GLYPH)    if (s->first_glyph->type == CHAR_GLYPH)
1011      face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);      face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1012    else    else
# Line 2724  x_set_mouse_face_gc (s) Line 1023  x_set_mouse_face_gc (s)
1023           but font FONT.  */           but font FONT.  */
1024        XGCValues xgcv;        XGCValues xgcv;
1025        unsigned long mask;        unsigned long mask;
1026          
1027        xgcv.background = s->face->background;        xgcv.background = s->face->background;
1028        xgcv.foreground = s->face->foreground;        xgcv.foreground = s->face->foreground;
1029        IF_DEBUG (x_check_font (s->f, s->font));        IF_DEBUG (x_check_font (s->f, s->font));
1030        xgcv.font = s->font->fid;        xgcv.font = s->font->fid;
1031        xgcv.graphics_exposures = False;        xgcv.graphics_exposures = False;
1032        mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;        mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
1033          
1034        if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)        if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1035          XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,          XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1036                     mask, &xgcv);                     mask, &xgcv);
1037        else        else
1038          FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc          FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
1039            = XCreateGC (s->display, s->window, mask, &xgcv);            = XCreateGC (s->display, s->window, mask, &xgcv);
1040          
1041        s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;        s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1042      }      }
1043    
# Line 2753  x_set_mouse_face_gc (s) Line 1052  x_set_mouse_face_gc (s)
1052  static INLINE void  static INLINE void
1053  x_set_mode_line_face_gc (s)  x_set_mode_line_face_gc (s)
1054       struct glyph_string *s;       struct glyph_string *s;
1055  {      {
1056    s->gc = s->face->gc;    s->gc = s->face->gc;
1057  }  }
1058    
# Line 2767  x_set_glyph_string_gc (s) Line 1066  x_set_glyph_string_gc (s)
1066       struct glyph_string *s;       struct glyph_string *s;
1067  {  {
1068    PREPARE_FACE_FOR_DISPLAY (s->f, s->face);    PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1069      
1070    if (s->hl == DRAW_NORMAL_TEXT)    if (s->hl == DRAW_NORMAL_TEXT)
1071      {      {
1072        s->gc = s->face->gc;        s->gc = s->face->gc;
# Line 2805  x_set_glyph_string_gc (s) Line 1104  x_set_glyph_string_gc (s)
1104  }  }
1105    
1106    
 /* Return in *R the clipping rectangle for glyph string S.  */  
   
 static void  
 x_get_glyph_string_clip_rect (s, r)  
      struct glyph_string *s;  
      XRectangle *r;  
 {  
   if (s->row->full_width_p)  
     {  
       /* Draw full-width.  X coordinates are relative to S->w->left.  */  
       int canon_x = CANON_X_UNIT (s->f);  
         
       r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;  
       r->width = XFASTINT (s->w->width) * canon_x;  
   
       if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))  
         {  
           int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;  
           if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))  
             r->x -= width;  
         }  
         
       r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);  
         
       /* Unless displaying a mode or menu bar line, which are always  
          fully visible, clip to the visible part of the row.  */  
       if (s->w->pseudo_window_p)  
         r->height = s->row->visible_height;  
       else  
         r->height = s->height;  
     }  
   else  
     {  
       /* This is a text line that may be partially visible.  */  
       r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);  
       r->width = window_box_width (s->w, s->area);  
       r->height = s->row->visible_height;  
     }  
   
   /* If S draws overlapping rows, it's sufficient to use the top and  
      bottom of the window for clipping because this glyph string  
      intentionally draws over other lines.  */  
   if (s->for_overlaps_p)  
     {  
       r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);  
       r->height = window_text_bottom_y (s->w) - r->y;  
     }  
   else  
     {  
       /* Don't use S->y for clipping because it doesn't take partially  
          visible lines into account.  For example, it can be negative for  
          partially visible lines at the top of a window.  */  
       if (!s->row->full_width_p  
           && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))  
         r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);  
       else  
         r->y = max (0, s->row->y);  
   
       /* If drawing a tool-bar window, draw it over the internal border  
          at the top of the window.  */  
       if (s->w == XWINDOW (s->f->tool_bar_window))  
         r->y -= s->f->output_data.x->internal_border_width;  
     }  
   
   r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);  
 }  
   
   
1107  /* Set clipping for output of glyph string S.  S may be part of a mode  /* Set clipping for output of glyph string S.  S may be part of a mode
1108     line or menu if we don't have X toolkit support.  */     line or menu if we don't have X toolkit support.  */
1109    
# Line 2881  x_set_glyph_string_clipping (s) Line 1112  x_set_glyph_string_clipping (s)
1112       struct glyph_string *s;       struct glyph_string *s;
1113  {  {
1114    XRectangle r;    XRectangle r;
1115    x_get_glyph_string_clip_rect (s, &r);    get_glyph_string_clip_rect (s, &r);
1116    XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);    XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
1117  }  }
1118    
1119    
1120  /* Compute left and right overhang of glyph string S.  If S is a glyph  /* RIF:
1121       Compute left and right overhang of glyph string S.  If S is a glyph
1122     string for a composition, assume overhangs don't exist.  */     string for a composition, assume overhangs don't exist.  */
1123    
1124  static INLINE void  static void
1125  x_compute_glyph_string_overhangs (s)  x_compute_glyph_string_overhangs (s)
1126       struct glyph_string *s;       struct glyph_string *s;
1127  {  {
# Line 2906  x_compute_glyph_string_overhangs (s) Line 1138  x_compute_glyph_string_overhangs (s)
1138  }  }
1139    
1140    
 /* Compute overhangs and x-positions for glyph string S and its  
    predecessors, or successors.  X is the starting x-position for S.  
    BACKWARD_P non-zero means process predecessors.  */  
     
 static void  
 x_compute_overhangs_and_x (s, x, backward_p)  
      struct glyph_string *s;  
      int x;  
      int backward_p;  
 {  
   if (backward_p)  
     {  
       while (s)  
         {  
           x_compute_glyph_string_overhangs (s);  
           x -= s->width;  
           s->x = x;  
           s = s->prev;  
         }  
     }  
   else  
     {  
       while (s)  
         {  
           x_compute_glyph_string_overhangs (s);  
           s->x = x;  
           x += s->width;  
           s = s->next;  
         }  
     }  
 }  
   
   
 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on  
    frame F.  Overhangs of glyphs other than type CHAR_GLYPH are  
    assumed to be zero.  */  
   
 static void  
 x_get_glyph_overhangs (glyph, f, left, right)  
      struct glyph *glyph;  
      struct frame *f;  
      int *left, *right;  
 {  
   *left = *right = 0;  
     
   if (glyph->type == CHAR_GLYPH)  
     {  
       XFontStruct *font;  
       struct face *face;  
       struct font_info *font_info;  
       XChar2b char2b;  
       XCharStruct *pcm;  
   
       face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);  
       font = face->font;  
       font_info = FONT_INFO_FROM_ID (f, face->font_info_id);  
       if (font  
           && (pcm = x_per_char_metric (font, &char2b)))  
         {  
           if (pcm->rbearing > pcm->width)  
             *right = pcm->rbearing - pcm->width;  
           if (pcm->lbearing < 0)  
             *left = -pcm->lbearing;  
         }  
     }  
 }  
   
   
 /* Return the index of the first glyph preceding glyph string S that  
    is overwritten by S because of S's left overhang.  Value is -1  
    if no glyphs are overwritten.  */  
   
 static int  
 x_left_overwritten (s)  
      struct glyph_string *s;  
 {  
   int k;  
       
   if (s->left_overhang)  
     {  
       int x = 0, i;  
       struct glyph *glyphs = s->row->glyphs[s->area];  
       int first = s->first_glyph - glyphs;  
   
       for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)  
         x -= glyphs[i].pixel_width;  
   
       k = i + 1;  
     }  
   else  
     k = -1;  
   
   return k;  
 }  
   
   
 /* Return the index of the first glyph preceding glyph string S that  
    is overwriting S because of its right overhang.  Value is -1 if no  
    glyph in front of S overwrites S.  */  
   
 static int  
 x_left_overwriting (s)  
      struct glyph_string *s;  
 {  
   int i, k, x;  
   struct glyph *glyphs = s->row->glyphs[s->area];  
   int first = s->first_glyph - glyphs;  
   
   k = -1;  
   x = 0;  
   for (i = first - 1; i >= 0; --i)  
     {  
       int left, right;  
       x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);  
       if (x + right > 0)  
         k = i;  
       x -= glyphs[i].pixel_width;  
     }  
   
   return k;  
 }  
   
   
 /* Return the index of the last glyph following glyph string S that is  
    not overwritten by S because of S's right overhang.  Value is -1 if  
    no such glyph is found.  */  
   
 static int  
 x_right_overwritten (s)  
      struct glyph_string *s;  
 {  
   int k = -1;  
   
   if (s->right_overhang)  
     {  
       int x = 0, i;  
       struct glyph *glyphs = s->row->glyphs[s->area];  
       int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);  
       int end = s->row->used[s->area];  
         
       for (i = first; i < end && s->right_overhang > x; ++i)  
         x += glyphs[i].pixel_width;  
   
       k = i;  
     }  
   
   return k;  
 }  
   
   
 /* Return the index of the last glyph following glyph string S that  
    overwrites S because of its left overhang.  Value is negative  
    if no such glyph is found.  */  
   
 static int  
 x_right_overwriting (s)  
      struct glyph_string *s;  
 {  
   int i, k, x;  
   int end = s->row->used[s->area];  
   struct glyph *glyphs = s->row->glyphs[s->area];  
   int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);  
   
   k = -1;  
   x = 0;  
   for (i = first; i < end; ++i)  
     {  
       int left, right;  
       x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);  
       if (x - left < 0)  
         k = i;  
       x += glyphs[i].pixel_width;  
     }  
   
   return k;  
 }  
   
   
1141  /* Fill rectangle X, Y, W, H with background color of glyph string S.  */  /* Fill rectangle X, Y, W, H with background color of glyph string S.  */
1142    
1143  static INLINE void  static INLINE void
# Line 3208  x_draw_glyph_string_foreground (s) Line 1262  x_draw_glyph_string_foreground (s)
1262              XDrawImageString (s->display, s->window, s->gc, x,              XDrawImageString (s->display, s->window, s->gc, x,
1263                                s->ybase - boff, char1b, s->nchars);                                s->ybase - boff, char1b, s->nchars);
1264          }          }
1265    
1266          if (s->face->overstrike)
1267            {
1268              /* For overstriking (to simulate bold-face), draw the
1269                 characters again shifted to the right by one pixel.  */
1270              if (s->two_byte_p)
1271                XDrawString16 (s->display, s->window, s->gc, x + 1,
1272                               s->ybase - boff, s->char2b, s->nchars);
1273              else
1274                XDrawString (s->display, s->window, s->gc, x + 1,
1275                             s->ybase - boff, char1b, s->nchars);
1276            }
1277      }      }
1278  }  }
1279    
# Line 3243  x_draw_composite_glyph_string_foreground Line 1309  x_draw_composite_glyph_string_foreground
1309    else    else
1310      {      {
1311        for (i = 0; i < s->nchars; i++, ++s->gidx)        for (i = 0; i < s->nchars; i++, ++s->gidx)
1312          XDrawString16 (s->display, s->window, s->gc,          {
1313                         x + s->cmp->offsets[s->gidx * 2],            XDrawString16 (s->display, s->window, s->gc,
1314                         s->ybase - s->cmp->offsets[s->gidx * 2 + 1],                           x + s->cmp->offsets[s->gidx * 2],
1315                         s->char2b + i, 1);                           s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
1316                             s->char2b + i, 1);
1317              if (s->face->overstrike)
1318                XDrawString16 (s->display, s->window, s->gc,
1319                               x + s->cmp->offsets[s->gidx * 2] + 1,
1320                               s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
1321                               s->char2b + i, 1);
1322            }
1323      }      }
1324  }  }
1325    
# Line 3270  x_frame_of_widget (widget) Line 1343  x_frame_of_widget (widget)
1343    struct x_display_info *dpyinfo;    struct x_display_info *dpyinfo;
1344    Lisp_Object tail;    Lisp_Object tail;
1345    struct frame *f;    struct frame *f;
1346      
1347    dpyinfo = x_display_info_for_display (XtDisplay (widget));    dpyinfo = x_display_info_for_display (XtDisplay (widget));
1348      
1349    /* Find the top-level shell of the widget.  Note that this function    /* Find the top-level shell of the widget.  Note that this function
1350       can be called when the widget is not yet realized, so XtWindow       can be called when the widget is not yet realized, so XtWindow
1351       (widget) == 0.  That's the reason we can't simply use       (widget) == 0.  That's the reason we can't simply use
# Line 3413  cvt_string_to_pixel (dpy, args, nargs, f Line 1486  cvt_string_to_pixel (dpy, args, nargs, f
1486      {      {
1487        String params[1];        String params[1];
1488        Cardinal nparams = 1;        Cardinal nparams = 1;
1489          
1490        params[0] = color_name;        params[0] = color_name;
1491        XtAppWarningMsg (XtDisplayToApplicationContext (dpy),        XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
1492                         "badValue", "cvt_string_to_pixel",                         "badValue", "cvt_string_to_pixel",
# Line 3429  cvt_string_to_pixel (dpy, args, nargs, f Line 1502  cvt_string_to_pixel (dpy, args, nargs, f
1502            to->size = sizeof (Pixel);            to->size = sizeof (Pixel);
1503            return False;            return False;
1504          }          }
1505          
1506        *(Pixel *) to->addr = pixel;        *(Pixel *) to->addr = pixel;
1507      }      }
1508    else    else
# Line 3437  cvt_string_to_pixel (dpy, args, nargs, f Line 1510  cvt_string_to_pixel (dpy, args, nargs, f
1510        cvt_string_to_pixel_value = pixel;        cvt_string_to_pixel_value = pixel;
1511        to->addr = (XtPointer) &cvt_string_to_pixel_value;        to->addr = (XtPointer) &cvt_string_to_pixel_value;
1512      }      }
1513      
1514    to->size = sizeof (Pixel);    to->size = sizeof (Pixel);
1515    return True;    return True;
1516  }  }
# Line 3500  x_color_cells (dpy, ncells) Line 1573  x_color_cells (dpy, ncells)
1573      {      {
1574        Screen *screen = dpyinfo->screen;        Screen *screen = dpyinfo->screen;
1575        int i;        int i;
1576          
1577        dpyinfo->ncolor_cells        dpyinfo->ncolor_cells
1578          = XDisplayCells (dpy, XScreenNumberOfScreen (screen));          = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
1579        dpyinfo->color_cells        dpyinfo->color_cells
1580          = (XColor *) xmalloc (dpyinfo->ncolor_cells          = (XColor *) xmalloc (dpyinfo->ncolor_cells
1581                                * sizeof *dpyinfo->color_cells);                                * sizeof *dpyinfo->color_cells);
1582          
1583        for (i = 0; i < dpyinfo->ncolor_cells; ++i)        for (i = 0; i < dpyinfo->ncolor_cells; ++i)
1584          dpyinfo->color_cells[i].pixel = i;          dpyinfo->color_cells[i].pixel = i;
1585          
1586        XQueryColors (dpy, dpyinfo->cmap,        XQueryColors (dpy, dpyinfo->cmap,
1587                      dpyinfo->color_cells, dpyinfo->ncolor_cells);                      dpyinfo->color_cells, dpyinfo->ncolor_cells);
1588      }      }
# Line 3556  x_query_color (f, color) Line 1629  x_query_color (f, color)
1629  {  {
1630    x_query_colors (f, color, 1);    x_query_colors (f, color, 1);
1631  }  }
1632        
1633    
1634  /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP.  If an  /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP.  If an
1635     exact match can't be allocated, try the nearest color available.     exact match can't be allocated, try the nearest color available.
# Line 3596  x_alloc_nearest_color_1 (dpy, cmap, colo Line 1669  x_alloc_nearest_color_1 (dpy, cmap, colo
1669                nearest_delta = delta;                nearest_delta = delta;
1670              }              }
1671          }          }
1672          
1673        color->red   = cells[nearest].red;        color->red   = cells[nearest].red;
1674        color->green = cells[nearest].green;        color->green = cells[nearest].green;
1675        color->blue  = cells[nearest].blue;        color->blue  = cells[nearest].blue;
# Line 3609  x_alloc_nearest_color_1 (dpy, cmap, colo Line 1682  x_alloc_nearest_color_1 (dpy, cmap, colo
1682           change in the colormap, so clear the color cache.  */           change in the colormap, so clear the color cache.  */
1683        struct x_display_info *dpyinfo = x_display_info_for_display (dpy);        struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
1684        XColor *cached_color;        XColor *cached_color;
1685          
1686        if (dpyinfo->color_cells        if (dpyinfo->color_cells
1687            && (cached_color = &dpyinfo->color_cells[color->pixel],            && (cached_color = &dpyinfo->color_cells[color->pixel],
1688                (cached_color->red != color->red                (cached_color->red != color->red
# Line 3626  x_alloc_nearest_color_1 (dpy, cmap, colo Line 1699  x_alloc_nearest_color_1 (dpy, cmap, colo
1699    if (rc)    if (rc)
1700      register_color (color->pixel);      register_color (color->pixel);
1701  #endif /* DEBUG_X_COLORS */  #endif /* DEBUG_X_COLORS */
1702      
1703    return rc;    return rc;
1704  }  }
1705    
# Line 3775  x_alloc_lighter_color (f, display, cmap, Line 1848  x_alloc_lighter_color (f, display, cmap,
1848            /* If we end up with the same color as before, try adding            /* If we end up with the same color as before, try adding
1849               delta to the RGB values.  */               delta to the RGB values.  */
1850            x_free_colors (f, &new.pixel, 1);            x_free_colors (f, &new.pixel, 1);
1851              
1852            new.red = min (0xffff, delta + color.red);            new.red = min (0xffff, delta + color.red);
1853            new.green = min (0xffff, delta + color.green);            new.green = min (0xffff, delta + color.green);
1854            new.blue = min (0xffff, delta + color.blue);            new.blue = min (0xffff, delta + color.blue);
# Line 3785  x_alloc_lighter_color (f, display, cmap, Line 1858  x_alloc_lighter_color (f, display, cmap,
1858          success_p = 1;          success_p = 1;
1859        *pixel = new.pixel;        *pixel = new.pixel;
1860      }      }
1861      
1862    return success_p;    return success_p;
1863  }  }
1864    
# Line 3796  x_alloc_lighter_color (f, display, cmap, Line 1869  x_alloc_lighter_color (f, display, cmap,
1869     DELTA lighter or darker than the relief's background which is found     DELTA lighter or darker than the relief's background which is found
1870     in S->f->output_data.x->relief_background.  If such a color cannot     in S->f->output_data.x->relief_background.  If such a color cannot
1871     be allocated, use DEFAULT_PIXEL, instead.  */     be allocated, use DEFAULT_PIXEL, instead.  */
1872      
1873  static void  static void
1874  x_setup_relief_color (f, relief, factor, delta, default_pixel)  x_setup_relief_color (f, relief, factor, delta, default_pixel)
1875       struct frame *f;       struct frame *f;
# Line 3836  x_setup_relief_color (f, relief, factor, Line 1909  x_setup_relief_color (f, relief, factor,
1909        relief->allocated_p = 1;        relief->allocated_p = 1;
1910        xgcv.foreground = relief->pixel = pixel;        xgcv.foreground = relief->pixel = pixel;
1911      }      }
1912      
1913    if (relief->gc == 0)    if (relief->gc == 0)
1914      {      {
1915        xgcv.stipple = dpyinfo->gray;        xgcv.stipple = dpyinfo->gray;
# Line 3866  x_setup_relief_colors (s) Line 1939  x_setup_relief_colors (s)
1939    else    else
1940      {      {
1941        XGCValues xgcv;        XGCValues xgcv;
1942          
1943        /* Get the background color of the face.  */        /* Get the background color of the face.  */
1944        XGetGCValues (s->display, s->gc, GCBackground, &xgcv);        XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
1945        color = xgcv.background;        color = xgcv.background;
# Line 3896  static void Line 1969  static void
1969  x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,  x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
1970                      raised_p, left_p, right_p, clip_rect)                      raised_p, left_p, right_p, clip_rect)
1971       struct frame *f;       struct frame *f;
1972       int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;       int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
1973       XRectangle *clip_rect;       XRectangle *clip_rect;
1974  {  {
1975    Display *dpy = FRAME_X_DISPLAY (f);    Display *dpy = FRAME_X_DISPLAY (f);
1976    Window window = FRAME_X_WINDOW (f);    Window window = FRAME_X_WINDOW (f);
1977    int i;    int i;
1978    GC gc;    GC gc;
1979      
1980    if (raised_p)    if (raised_p)
1981      gc = f->output_data.x->white_relief.gc;      gc = f->output_data.x->white_relief.gc;
1982    else    else
# Line 3928  x_draw_relief_rect (f, left_x, top_y, ri Line 2001  x_draw_relief_rect (f, left_x, top_y, ri
2001    else    else
2002      gc = f->output_data.x->white_relief.gc;      gc = f->output_data.x->white_relief.gc;
2003    XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);    XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2004      
2005    /* Bottom.  */    /* Bottom.  */
2006    for (i = 0; i < width; ++i)    for (i = 0; i < width; ++i)
2007      XDrawLine (dpy, window, gc,      XDrawLine (dpy, window, gc,
2008                 left_x + i * left_p, bottom_y - i,                 left_x + i * left_p, bottom_y - i,
2009                 right_x + 1 - i * right_p, bottom_y - i);                 right_x + 1 - i * right_p, bottom_y - i);
2010      
2011    /* Right.  */    /* Right.  */
2012    if (right_p)    if (right_p)
2013      for (i = 0; i < width; ++i)      for (i = 0; i < width; ++i)
# Line 3956  static void Line 2029  static void
2029  x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,  x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2030                   left_p, right_p, clip_rect)                   left_p, right_p, clip_rect)
2031       struct glyph_string *s;       struct glyph_string *s;
2032       int left_x, top_y, right_x, bottom_y, left_p, right_p;       int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
2033       XRectangle *clip_rect;       XRectangle *clip_rect;
2034  {  {
2035    XGCValues xgcv;    XGCValues xgcv;
2036      
2037    XGetGCValues (s->display, s->gc, GCForeground, &xgcv);    XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2038    XSetForeground (s->display, s->gc, s->face->box_color);    XSetForeground (s->display, s->gc, s->face->box_color);
2039    XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);    XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
2040      
2041    /* Top.  */    /* Top.  */
2042    XFillRectangle (s->display, s->window, s->gc,    XFillRectangle (s->display, s->window, s->gc,
2043                    left_x, top_y, right_x - left_x + 1, width);                    left_x, top_y, right_x - left_x + 1, width);
# Line 3977  x_draw_box_rect (s, left_x, top_y, right Line 2050  x_draw_box_rect (s, left_x, top_y, right
2050    /* Bottom.  */    /* Bottom.  */
2051    XFillRectangle (s->display, s->window, s->gc,    XFillRectangle (s->display, s->window, s->gc,
2052                    left_x, bottom_y - width + 1, right_x - left_x + 1, width);                    left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2053      
2054    /* Right.  */    /* Right.  */
2055    if (right_p)    if (right_p)
2056      XFillRectangle (s->display, s->window, s->gc,      XFillRectangle (s->display, s->window, s->gc,
# Line 4007  x_draw_glyph_string_box (s) Line 2080  x_draw_glyph_string_box (s)
2080        if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))        if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
2081          last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);          last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
2082      }      }
2083      
2084    /* The glyph that may have a right box line.  */    /* The glyph that may have a right box line.  */
2085    last_glyph = (s->cmp || s->img    last_glyph = (s->cmp || s->img
2086                  ? s->first_glyph                  ? s->first_glyph
# Line 4031  x_draw_glyph_string_box (s) Line 2104  x_draw_glyph_string_box (s)
2104                   && (s->next == NULL                   && (s->next == NULL
2105                       || s->next->hl != s->hl)));                       || s->next->hl != s->hl)));
2106    
2107    x_get_glyph_string_clip_rect (s, &clip_rect);    get_glyph_string_clip_rect (s, &clip_rect);
2108    
2109    if (s->face->box == FACE_SIMPLE_BOX)    if (s->face->box == FACE_SIMPLE_BOX)
2110      x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,      x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
# Line 4086  x_draw_image_foreground (s) Line 2159  x_draw_image_foreground (s)
2159            xgcv.clip_y_origin = y;            xgcv.clip_y_origin = y;
2160            xgcv.function = GXcopy;            xgcv.function = GXcopy;
2161            XChangeGC (s->display, s->gc, mask, &xgcv);            XChangeGC (s->display, s->gc, mask, &xgcv);
2162              
2163            x_get_glyph_string_clip_rect (s, &clip_rect);            get_glyph_string_clip_rect (s, &clip_rect);
2164            image_rect.x = x;            image_rect.x = x;
2165            image_rect.y = y;            image_rect.y = y;
2166            image_rect.width = s->img->width;            image_rect.width = s->img->width;
# Line 4100  x_draw_image_foreground (s) Line 2173  x_draw_image_foreground (s)
2173          {          {
2174            XRectangle clip_rect, image_rect, r;            XRectangle clip_rect, image_rect, r;
2175    
2176            x_get_glyph_string_clip_rect (s, &clip_rect);            get_glyph_string_clip_rect (s, &clip_rect);
2177            image_rect.x = x;            image_rect.x = x;
2178            image_rect.y = y;            image_rect.y = y;
2179            image_rect.width = s->img->width;            image_rect.width = s->img->width;
# Line 4108  x_draw_image_foreground (s) Line 2181  x_draw_image_foreground (s)
2181            if (x_intersect_rectangles (&clip_rect, &image_rect, &r))            if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2182              XCopyArea (s->display, s->img->pixmap, s->window, s->gc,              XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2183                         r.x - x, r.y - y, r.width, r.height, r.x, r.y);                         r.x - x, r.y - y, r.width, r.height, r.x, r.y);
2184              
2185            /* When the image has a mask, we can expect that at            /* When the image has a mask, we can expect that at
2186               least part of a mouse highlight or a block cursor will               least part of a mouse highlight or a block cursor will
2187               be visible.  If the image doesn't have a mask, make               be visible.  If the image doesn't have a mask, make
# Line 4141  x_draw_image_relief (s) Line 2214  x_draw_image_relief (s)
2214    XRectangle r;    XRectangle r;
2215    int x;    int x;
2216    int y = s->ybase - image_ascent (s->img, s->face);    int y = s->ybase - image_ascent (s->img, s->face);
2217      
2218    /* If first glyph of S has a left box line, start drawing it to the    /* If first glyph of S has a left box line, start drawing it to the
2219       right of that line.  */       right of that line.  */
2220    if (s->face->box != FACE_NO_BOX    if (s->face->box != FACE_NO_BOX
# Line 4149  x_draw_image_relief (s) Line 2222  x_draw_image_relief (s)
2222      x = s->x + abs (s->face->box_line_width);      x = s->x + abs (s->face->box_line_width);
2223    else    else
2224      x = s->x;      x = s->x;
2225      
2226    /* If there is a margin around the image, adjust x- and y-position    /* If there is a margin around the image, adjust x- and y-position
2227       by that margin.  */       by that margin.  */
2228    x += s->img->hmargin;    x += s->img->hmargin;
2229    y += s->img->vmargin;    y += s->img->vmargin;
2230      
2231    if (s->hl == DRAW_IMAGE_SUNKEN    if (s->hl == DRAW_IMAGE_SUNKEN
2232        || s->hl == DRAW_IMAGE_RAISED)        || s->hl == DRAW_IMAGE_RAISED)
2233      {      {
# Line 4166  x_draw_image_relief (s) Line 2239  x_draw_image_relief (s)
2239        thick = abs (s->img->relief);        thick = abs (s->img->relief);
2240        raised_p = s->img->relief > 0;        raised_p = s->img->relief > 0;
2241      }      }
2242      
2243    x0 = x - thick;    x0 = x - thick;
2244    y0 = y - thick;    y0 = y - thick;
2245    x1 = x + s->img->width + thick - 1;    x1 = x + s->img->width + thick - 1;
2246    y1 = y + s->img->height + thick - 1;    y1 = y + s->img->height + thick - 1;
2247      
2248    x_setup_relief_colors (s);    x_setup_relief_colors (s);
2249    x_get_glyph_string_clip_rect (s, &r);    get_glyph_string_clip_rect (s, &r);
2250    x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);    x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
2251  }  }
2252    
# Line 4228  x_draw_image_foreground_1 (s, pixmap) Line 2301  x_draw_image_foreground_1 (s, pixmap)
2301          {          {
2302            XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,            XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2303                       0, 0, s->img->width, s->img->height, x, y);                       0, 0, s->img->width, s->img->height, x, y);
2304              
2305            /* When the image has a mask, we can expect that at            /* When the image has a mask, we can expect that at
2306               least part of a mouse highlight or a block cursor will               least part of a mouse highlight or a block cursor will
2307               be visible.  If the image doesn't have a mask, make               be visible.  If the image doesn't have a mask, make
# Line 4271  x_draw_glyph_string_bg_rect (s, x, y, w, Line 2344  x_draw_glyph_string_bg_rect (s, x, y, w,
2344  }  }
2345    
2346    
2347  /* Draw image glyph string S.    /* Draw image glyph string S.
2348    
2349              s->y              s->y
2350     s->x      +-------------------------     s->x      +-------------------------
# Line 4297  x_draw_image_glyph_string (s) Line 2370  x_draw_image_glyph_string (s)
2370    
2371    height = s->height - 2 * box_line_vwidth;    height = s->height - 2 * box_line_vwidth;
2372    
2373    
2374    /* Fill background with face under the image.  Do it only if row is    /* Fill background with face under the image.  Do it only if row is
2375       taller than image or if image has a clip mask to reduce       taller than image or if image has a clip mask to reduce
2376       flickering.  */       flickering.  */
# Line 4312  x_draw_image_glyph_string (s) Line 2386  x_draw_image_glyph_string (s)
2386          x = s->x + box_line_hwidth;          x = s->x + box_line_hwidth;
2387        else        else
2388          x = s->x;          x = s->x;
2389          
2390        y = s->y + box_line_vwidth;        y = s->y + box_line_vwidth;
2391          
2392        if (s->img->mask)        if (s->img->mask)
2393          {          {
2394            /* Create a pixmap as large as the glyph string.  Fill it            /* Create a pixmap as large as the glyph string.  Fill it
# Line 4327  x_draw_image_glyph_string (s) Line 2401  x_draw_image_glyph_string (s)
2401            pixmap = XCreatePixmap (s->display, s->window,            pixmap = XCreatePixmap (s->display, s->window,
2402                                    s->background_width,                                    s->background_width,
2403                                    s->height, depth);                                    s->height, depth);
2404              
2405            /* Don't clip in the following because we're working on the            /* Don't clip in the following because we're working on the
2406               pixmap.  */               pixmap.  */
2407            XSetClipMask (s->display, s->gc, None);            XSetClipMask (s->display, s->gc, None);
# Line 4354  x_draw_image_glyph_string (s) Line 2428  x_draw_image_glyph_string (s)
2428          }          }
2429        else        else
2430          x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);          x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2431          
2432        s->background_filled_p = 1;        s->background_filled_p = 1;
2433      }      }
2434    
# Line 4413  x_draw_stretch_glyph_string (s) Line 2487  x_draw_stretch_glyph_string (s)
2487              }              }
2488            else            else
2489              gc = s->face->gc;              gc = s->face->gc;
2490      
2491            x_get_glyph_string_clip_rect (s, &r);            get_glyph_string_clip_rect (s, &r);
2492            XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);            XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
2493              
2494            if (s->face->stipple)            if (s->face->stipple)
2495              {              {
2496                /* Fill background with a stipple pattern.  */                /* Fill background with a stipple pattern.  */
# Line 4437  x_draw_stretch_glyph_string (s) Line 2511  x_draw_stretch_glyph_string (s)
2511    else if (!s->background_filled_p)    else if (!s->background_filled_p)
2512      x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,      x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
2513                                   s->height);                                   s->height);
2514      
2515    s->background_filled_p = 1;    s->background_filled_p = 1;
2516  }  }
2517    
# Line 4530  x_draw_glyph_string (s) Line 2604  x_draw_glyph_string (s)
2604    
2605               ROUND ((maximum descent) / 2), with               ROUND ((maximum descent) / 2), with
2606               ROUND(x) = floor (x + 0.5)  */               ROUND(x) = floor (x + 0.5)  */
2607              
2608            if (x_use_underline_position_properties            if (x_use_underline_position_properties
2609                && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))                && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
2610              y = s->ybase + (long) tem;              y = s->ybase + (long) tem;
# Line 4538  x_draw_glyph_string (s) Line 2612  x_draw_glyph_string (s)
2612              y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;              y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
2613            else            else
2614              y = s->y + s->height - h;              y = s->y + s->height - h;
2615          
2616            if (s->face->underline_defaulted_p)            if (s->face->underline_defaulted_p)
2617              XFillRectangle (s->display, s->window, s->gc,              XFillRectangle (s->display, s->window, s->gc,
2618                              s->x, y, s->width, h);                              s->x, y, s->width, h);
# Line 4571  x_draw_glyph_string (s) Line 2645  x_draw_glyph_string (s)
2645                XSetForeground (s->display, s->gc, xgcv.foreground);                XSetForeground (s->display, s->gc, xgcv.foreground);
2646              }              }
2647          }          }
2648      
2649        /* Draw strike-through.  */        /* Draw strike-through.  */
2650        if (s->face->strike_through_p)        if (s->face->strike_through_p)
2651          {          {
# Line 4591  x_draw_glyph_string (s) Line 2665  x_draw_glyph_string (s)
2665                XSetForeground (s->display, s->gc, xgcv.foreground);                XSetForeground (s->display, s->gc, xgcv.foreground);
2666              }              }
2667          }          }
2668      
2669        /* Draw relief if not yet drawn.  */        /* Draw relief if not yet drawn.  */
2670        if (!relief_drawn_p && s->face->box != FACE_NO_BOX)        if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2671          x_draw_glyph_string_box (s);          x_draw_glyph_string_box (s);
2672      }      }
2673      
2674    /* Reset clipping.  */    /* Reset clipping.  */
2675    XSetClipMask (s->display, s->gc, None);    XSetClipMask (s->display, s->gc, None);
2676  }  }
2677    
2678    /* Shift display to make room for inserted glyphs.   */
2679    
2680  static int x_fill_composite_glyph_string P_ ((struct glyph_string *,  void
2681                                                struct face **, int));  x_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
2682         struct frame *f;
2683         int x, y, width, height, shift_by;
 /* Fill glyph string S with composition components specified by S->cmp.  
     
    FACES is an array of faces for all components of this composition.  
    S->gidx is the index of the first component for S.  
    OVERLAPS_P non-zero means S should draw the foreground only, and  
    use its physical height for clipping.  
   
    Value is the index of a component not in S.  */  
   
 static int  
 x_fill_composite_glyph_string (s, faces, overlaps_p)  
      struct glyph_string *s;  
      struct face **faces;  
      int overlaps_p;  
 {  
   int i;  
   
   xassert (s);  
   
   s->for_overlaps_p = overlaps_p;  
     
   s->face = faces[s->gidx];  
   s->font = s->face->font;  
   s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);  
   
   /* For all glyphs of this composition, starting at the offset  
      S->gidx, until we reach the end of the definition or encounter a  
      glyph that requires the different face, add it to S.  */  
   ++s->nchars;  
   for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)  
     ++s->nchars;  
   
   /* All glyph strings for the same composition has the same width,  
      i.e. the width set for the first component of the composition.  */  
   
   s->width = s->first_glyph->pixel_width;  
   
   /* If the specified font could not be loaded, use the frame's  
      default font, but record the fact that we couldn't load it in  
      the glyph string so that we can draw rectangles for the  
      characters of the glyph string.  */  
   if (s->font == NULL)  
     {  
       s->font_not_found_p = 1;  
       s->font = FRAME_FONT (s->f);  
     }  
   
   /* Adjust base line for subscript/superscript text.  */  
   s->ybase += s->first_glyph->voffset;  
     
   xassert (s->face && s->face->gc);  
   
   /* This glyph string must always be drawn with 16-bit functions.  */  
   s->two_byte_p = 1;  
   
   return s->gidx + s->nchars;  
 }  
   
   
 /* Fill glyph string S from a sequence of character glyphs.  
     
    FACE_ID is the face id of the string.  START is the index of the  
    first glyph to consider, END is the index of the last + 1.  
    OVERLAPS_P non-zero means S should draw the foreground only, and  
    use its physical height for clipping.  
   
    Value is the index of the first glyph not in S.  */  
   
 static int  
 x_fill_glyph_string (s, face_id, start, end, overlaps_p)  
      struct glyph_string *s;  
      int face_id;  
      int start, end, overlaps_p;  
 {  
   struct glyph *glyph, *last;  
   int voffset;  
   int glyph_not_available_p;  
     
   xassert (s->f == XFRAME (s->w->frame));  
   xassert (s->nchars == 0);  
   xassert (start >= 0 && end > start);  
   
   s->for_overlaps_p = overlaps_p,  
   glyph = s->row->glyphs[s->area] + start;  
   last = s->row->glyphs[s->area] + end;  
   voffset = glyph->voffset;  
     
   glyph_not_available_p = glyph->glyph_not_available_p;  
   
   while (glyph < last  
          && glyph->type == CHAR_GLYPH  
          && glyph->voffset == voffset  
          /* Same face id implies same font, nowadays.  */  
          && glyph->face_id == face_id  
          && glyph->glyph_not_available_p == glyph_not_available_p)  
     {  
       int two_byte_p;  
   
       s->face = x_get_glyph_face_and_encoding (s->f, glyph,  
                                                s->char2b + s->nchars,  
                                                &two_byte_p);  
       s->two_byte_p = two_byte_p;  
       ++s->nchars;  
       xassert (s->nchars <= end - start);  
       s->width += glyph->pixel_width;  
       ++glyph;  
     }  
   
   s->font = s->face->font;  
   s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);  
     
   /* If the specified font could not be loaded, use the frame's font,  
      but record the fact that we couldn't load it in  
      S->font_not_found_p so that we can draw rectangles for the  
      characters of the glyph string.  */  
   if (s->font == NULL || glyph_not_available_p)  
     {  
       s->font_not_found_p = 1;  
       s->font = FRAME_FONT (s->f);  
     }  
   
   /* Adjust base line for subscript/superscript text.  */  
   s->ybase += voffset;  
   
   xassert (s->face && s->face->gc);  
   return glyph - s->row->glyphs[s->area];  
 }  
   
   
 /* Fill glyph string S from image glyph S->first_glyph.  */  
   
 static void  
 x_fill_image_glyph_string (s)  
      struct glyph_string *s;  
 {  
   xassert (s->first_glyph->type == IMAGE_GLYPH);  
   s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);  
   xassert (s->img);  
   s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);  
   s->font = s->face->font;  
   s->width = s->first_glyph->pixel_width;  
     
   /* Adjust base line for subscript/superscript text.  */  
   s->ybase += s->first_glyph->voffset;  
 }  
   
   
 /* Fill glyph string S from a sequence of stretch glyphs.  
   
    ROW is the glyph row in which the glyphs are found, AREA is the  
    area within the row.  START is the index of the first glyph to  
    consider, END is the index of the last + 1.  
   
    Value is the index of the first glyph not in S.  */  
   
 static int  
 x_fill_stretch_glyph_string (s, row, area, start, end)  
      struct glyph_string *s;  
      struct glyph_row *row;  
      enum glyph_row_area area;  
      int start, end;  
 {  
   struct glyph *glyph, *last;  
   int voffset, face_id;  
     
   xassert (s->first_glyph->type == STRETCH_GLYPH);  
     
   glyph = s->row->glyphs[s->area] + start;  
   last = s->row->glyphs[s->area] + end;  
   face_id = glyph->face_id;  
   s->face = FACE_FROM_ID (s->f, face_id);  
   s->font = s->face->font;  
   s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);  
   s->width = glyph->pixel_width;  
   voffset = glyph->voffset;  
   
   for (++glyph;  
        (glyph < last  
         && glyph->type == STRETCH_GLYPH  
         && glyph->voffset == voffset  
         && glyph->face_id == face_id);  
        ++glyph)  
     s->width += glyph->pixel_width;  
     
   /* Adjust base line for subscript/superscript text.  */  
   s->ybase += voffset;  
   
   /* The case that face->gc == 0 is handled when drawing the glyph  
      string by calling PREPARE_FACE_FOR_DISPLAY.  */  
   xassert (s->face);  
   return glyph - s->row->glyphs[s->area];  
 }  
   
   
 /* Initialize glyph string S.  CHAR2B is a suitably allocated vector  
    of XChar2b structures for S; it can't be allocated in  
    x_init_glyph_string because it must be allocated via `alloca'.  W  
    is the window on which S is drawn.  ROW and AREA are the glyph row  
    and area within the row from which S is constructed.  START is the  
    index of the first glyph structure covered by S.  HL is a  
    face-override for drawing S.  */  
     
 static void  
 x_init_glyph_string (s, char2b, w, row, area, start, hl)  
      struct glyph_string *s;  
      XChar2b *char2b;  
      struct window *w;  
      struct glyph_row *row;  
      enum glyph_row_area area;  
      int start;  
      enum draw_glyphs_face hl;  
 {  
   bzero (s, sizeof *s);  
   s->w = w;  
   s->f = XFRAME (w->frame);  
   s->display = FRAME_X_DISPLAY (s->f);  
   s->window = FRAME_X_WINDOW (s->f);  
   s->char2b = char2b;  
   s->hl = hl;  
   s->row = row;  
   s->area = area;  
   s->first_glyph = row->glyphs[area] + start;  
   s->height = row->height;  
   s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);  
   
   /* Display the internal border below the tool-bar window.  */  
   if (s->w == XWINDOW (s->f->tool_bar_window))  
     s->y -= s->f->output_data.x->internal_border_width;  
     
   s->ybase = s->y + row->ascent;  
 }  
   
   
 /* Set background width of glyph string S.  START is the index of the  
    first glyph following S.  LAST_X is the right-most x-position + 1  
    in the drawing area.  */  
   
 static INLINE void  
 x_set_glyph_string_background_width (s, start, last_x)  
      struct glyph_string *s;  
      int start;  
      int last_x;  
 {  
   /* If the face of this glyph string has to be drawn to the end of  
      the drawing area, set S->extends_to_end_of_line_p.  */  
   struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);  
     
   if (start == s->row->used[s->area]  
       && s->area == TEXT_AREA  
       && ((s->hl == DRAW_NORMAL_TEXT  
            && (s->row->fill_line_p  
                || s->face->background != default_face->background  
                || s->face->stipple != default_face->stipple  
                || s->row->mouse_face_p))  
           || s->hl == DRAW_MOUSE_FACE  
           || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)  
               && s->row->fill_line_p)))  
       s->extends_to_end_of_line_p = 1;  
     
   /* If S extends its face to the end of the line, set its  
      background_width to the distance to the right edge of the drawing  
      area.  */  
   if (s->extends_to_end_of_line_p)  
     s->background_width = last_x - s->x + 1;  
   else  
     s->background_width = s->width;  
 }  
   
   
 /* Add a glyph string for a stretch glyph to the list of strings  
    between HEAD and TAIL.  START is the index of the stretch glyph in  
    row area AREA of glyph row ROW.  END is the index of the last glyph  
    in that glyph row area.  X is the current output position assigned  
    to the new glyph string constructed.  HL overrides that face of the  
    glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn.  LAST_X  
    is the right-most x-position of the drawing area.  */  
   
 /* SunOS 4 bundled cc, barfed on continuations in the arg lists here  
    and below -- keep them on one line.  */  
 #define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \  
      do                                                                     \  
        {                                                                    \  
          s = (struct glyph_string *) alloca (sizeof *s);                    \  
          x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL);            \  
          START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END);    \  
          x_append_glyph_string (&HEAD, &TAIL, s);                           \  
          s->x = (X);                                                        \  
        }                                                                    \  
      while (0)  
   
   
 /* Add a glyph string for an image glyph to the list of strings  
    between HEAD and TAIL.  START is the index of the image glyph in  
    row area AREA of glyph row ROW.  END is the index of the last glyph  
    in that glyph row area.  X is the current output position assigned  
    to the new glyph string constructed.  HL overrides that face of the  
    glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn.  LAST_X  
    is the right-most x-position of the drawing area.  */  
   
 #define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \  
      do                                                                 \  
        {                                                                \  
          s = (struct glyph_string *) alloca (sizeof *s);                \  
          x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL);        \  
          x_fill_image_glyph_string (s);                                 \  
          x_append_glyph_string (&HEAD, &TAIL, s);                       \  
          ++START;                                                       \  
          s->x = (X);                                                    \  
        }                                                                \  
      while (0)  
   
   
 /* Add a glyph string for a sequence of character glyphs to the list  
    of strings between HEAD and TAIL.  START is the index of the first  
    glyph in row area AREA of glyph row ROW that is part of the new  
    glyph string.  END is the index of the last glyph in that glyph row  
    area.  X is the current output position assigned to the new glyph  
    string constructed.  HL overrides that face of the glyph; e.g. it  
    is DRAW_CURSOR if a cursor has to be drawn.  LAST_X is the  
    right-most x-position of the drawing area.  */  
   
 #define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \  
      do                                                                    \  
        {                                                                   \  
          int c, face_id;                                                   \  
          XChar2b *char2b;                                                  \  
                                                                            \  
          c = (ROW)->glyphs[AREA][START].u.ch;                              \  
          face_id = (ROW)->glyphs[AREA][START].face_id;                     \  
                                                                            \  
          s = (struct glyph_string *) alloca (sizeof *s);                   \  
          char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b);     \  
          x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL);         \  
          x_append_glyph_string (&HEAD, &TAIL, s);                          \  
          s->x = (X);                                                       \  
          START = x_fill_glyph_string (s, face_id, START, END,              \  
                                           OVERLAPS_P);                     \  
        }                                                                   \  
      while (0)  
       
   
 /* Add a glyph string for a composite sequence to the list of strings  
    between HEAD and TAIL.  START is the index of the first glyph in  
    row area AREA of glyph row ROW that is part of the new glyph  
    string.  END is the index of the last glyph in that glyph row area.  
    X is the current output position assigned to the new glyph string  
    constructed.  HL overrides that face of the glyph; e.g. it is  
    DRAW_CURSOR if a cursor has to be drawn.  LAST_X is the right-most  
    x-position of the drawing area.  */  
   
 #define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P)     \  
   do {                                                                    \  
     int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id;                     \  
     int face_id = (ROW)->glyphs[AREA][START].face_id;                     \  
     struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id);   \  
     struct composition *cmp = composition_table[cmp_id];                  \  
     int glyph_len = cmp->glyph_len;                                       \  
     XChar2b *char2b;                                                      \  
     struct face **faces;                                                  \  
     struct glyph_string *first_s = NULL;                                  \  
     int n;                                                                \  
                                                                           \  
     base_face = base_face->ascii_face;                                    \  
     char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len);           \  
     faces = (struct face **) alloca ((sizeof *faces) * glyph_len);        \  
     /* At first, fill in `char2b' and `faces'.  */                        \  
     for (n = 0; n < glyph_len; n++)                                       \  
       {                                                                   \  
         int c = COMPOSITION_GLYPH (cmp, n);                               \  
         int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \  
         faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id);        \  
         x_get_char_face_and_encoding (XFRAME (w->frame), c,               \  
                                       this_face_id, char2b + n, 1, 1);    \  
       }                                                                   \  
                                                                           \  
     /* Make glyph_strings for each glyph sequence that is drawable by     \  
        the same face, and append them to HEAD/TAIL.  */                   \  
     for (n = 0; n < cmp->glyph_len;)                                      \  
       {                                                                   \  
         s = (struct glyph_string *) alloca (sizeof *s);                   \  
         x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL);     \  
         x_append_glyph_string (&(HEAD), &(TAIL), s);                      \  
         s->cmp = cmp;                                                     \  
         s->gidx = n;                                                      \  
         s->x = (X);                                                       \  
                                                                           \  
         if (n == 0)                                                       \  
           first_s = s;                                                    \  
                                                                           \  
         n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P);         \  
       }                                                                   \  
                                                                           \  
     ++START;                                                              \  
     s = first_s;                                                          \  
   } while (0)  
       
   
 /* Build a list of glyph strings between HEAD and TAIL for the glyphs  
    of AREA of glyph row ROW on window W between indices START and END.  
    HL overrides the face for drawing glyph strings, e.g. it is  
    DRAW_CURSOR to draw a cursor.  X and LAST_X are start and end  
    x-positions of the drawing area.  
   
    This is an ugly monster macro construct because we must use alloca  
    to allocate glyph strings (because x_draw_glyphs can be called  
    asynchronously).  */  
   
 #define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \  
      do                                                                    \  
        {                                                                   \  
          HEAD = TAIL = NULL;                                               \  
          while (START < END)                                               \  
            {                                                               \  
              struct glyph *first_glyph = (ROW)->glyphs[AREA] + START;      \  
              switch (first_glyph->type)                                    \  
                {                                                           \  
                case CHAR_GLYPH:                                            \  
                  BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \  
                                            TAIL, HL, X, LAST_X,            \  
                                            OVERLAPS_P);                    \  
                  break;                                                    \  
                                                                            \  
                case COMPOSITE_GLYPH:                                       \  
                  BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END,   \  
                                                  HEAD, TAIL, HL, X, LAST_X,\  
                                                  OVERLAPS_P);              \  
                  break;                                                    \  
                                                                            \  
                case STRETCH_GLYPH:                                         \  
                  BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END,     \  
                                              HEAD, TAIL, HL, X, LAST_X);   \  
                  break;                                                    \  
                                                                            \  
                case IMAGE_GLYPH:                                           \  
                  BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \  
                                            TAIL, HL, X, LAST_X);           \  
                  break;                                                    \  
                                                                            \  
                default:                                                    \  
                  abort ();                                                 \  
                }                                                           \  
                                                                            \  
              x_set_glyph_string_background_width (s, START, LAST_X);       \  
              (X) += s->width;                                              \  
             }                                                              \  
        }                                                                   \  
      while (0)  
   
   
 /* Draw glyphs between START and END in AREA of ROW on window W,  
    starting at x-position X.  X is relative to AREA in W.  HL is a  
    face-override with the following meaning:  
   
    DRAW_NORMAL_TEXT     draw normally  
    DRAW_CURSOR          draw in cursor face  
    DRAW_MOUSE_FACE      draw in mouse face.  
    DRAW_INVERSE_VIDEO   draw in mode line face  
    DRAW_IMAGE_SUNKEN    draw an image with a sunken relief around it  
    DRAW_IMAGE_RAISED    draw an image with a raised relief around it  
   
    If OVERLAPS_P is non-zero, draw only the foreground of characters  
    and clip to the physical height of ROW.  
   
    Value is the x-position reached, relative to AREA of W.  */  
       
 static int  
 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)  
      struct window *w;  
      int x;  
      struct glyph_row *row;  
      enum glyph_row_area area;  
      int start, end;  
      enum draw_glyphs_face hl;  
      int overlaps_p;  
 {  
   struct glyph_string *head, *tail;  
   struct glyph_string *s;  
   int last_x, area_width;  
   int x_reached;  
   int i, j;  
   
   /* Let's rather be paranoid than getting a SEGV.  */  
   end = min (end, row->used[area]);  
   start = max (0, start);  
   start = min (end, start);  
   
   /* Translate X to frame coordinates.  Set last_x to the right  
      end of the drawing area.  */  
   if (row->full_width_p)  
     {  
       /* X is relative to the left edge of W, without scroll bars  
          or fringes.  */  
       struct frame *f = XFRAME (w->frame);  
       int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);  
   
       x += window_left_x;  
       area_width = XFASTINT (w->width) * CANON_X_UNIT (f);  
       last_x = window_left_x + area_width;  
   
       if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))  
         {  
           int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);  
           if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))  
             last_x += width;  
           else  
             x -= width;  
         }  
   
       x += FRAME_INTERNAL_BORDER_WIDTH (f);  
       last_x += FRAME_INTERNAL_BORDER_WIDTH (f);  
     }  
   else  
     {  
       x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);  
       area_width = window_box_width (w, area);  
       last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);  
     }  
   
   /* Build a doubly-linked list of glyph_string structures between  
      head and tail from what we have to draw.  Note that the macro  
      BUILD_GLYPH_STRINGS will modify its start parameter.  That's  
      the reason we use a separate variable `i'.  */  
   i = start;  
   BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,  
                        overlaps_p);  
   if (tail)  
     x_reached = tail->x + tail->background_width;  
   else  
     x_reached = x;  
   
   /* If there are any glyphs with lbearing < 0 or rbearing > width in  
      the row, redraw some glyphs in front or following the glyph  
      strings built above.  */  
   if (head && !overlaps_p && row->contains_overlapping_glyphs_p)  
     {  
       int dummy_x = 0;  
       struct glyph_string *h, *t;  
   
       /* Compute overhangs for all glyph strings.  */  
       for (s = head; s; s = s->next)  
         x_compute_glyph_string_overhangs (s);  
   
       /* Prepend glyph strings for glyphs in front of the first glyph  
          string that are overwritten because of the first glyph  
          string's left overhang.  The background of all strings  
          prepended must be drawn because the first glyph string  
          draws over it.  */  
       i = x_left_overwritten (head);  
       if (i >= 0)  
         {  
           j = i;  
           BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,  
                                DRAW_NORMAL_TEXT, dummy_x, last_x,  
                                overlaps_p);  
           start = i;  
           x_compute_overhangs_and_x (t, head->x, 1);  
           x_prepend_glyph_string_lists (&head, &tail, h, t);  
         }  
   
       /* Prepend glyph strings for glyphs in front of the first glyph  
          string that overwrite that glyph string because of their  
          right overhang.  For these strings, only the foreground must  
          be drawn, because it draws over the glyph string at `head'.  
          The background must not be drawn because this would overwrite  
          right overhangs of preceding glyphs for which no glyph  
          strings exist.  */  
       i = x_left_overwriting (head);  
       if (i >= 0)  
         {  
           BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,  
                                DRAW_NORMAL_TEXT, dummy_x, last_x,  
                                overlaps_p);  
           for (s = h; s; s = s->next)  
             s->background_filled_p = 1;  
           x_compute_overhangs_and_x (t, head->x, 1);  
           x_prepend_glyph_string_lists (&head, &tail, h, t);  
         }  
   
       /* Append glyphs strings for glyphs following the last glyph  
          string tail that are overwritten by tail.  The background of  
          these strings has to be drawn because tail's foreground draws  
          over it.  */  
       i = x_right_overwritten (tail);  
       if (i >= 0)  
         {  
           BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,  
                                DRAW_NORMAL_TEXT, x, last_x,  
                                overlaps_p);  
           x_compute_overhangs_and_x (h, tail->x + tail->width, 0);  
           x_append_glyph_string_lists (&head, &tail, h, t);  
         }  
   
       /* Append glyph strings for glyphs following the last glyph  
          string tail that overwrite tail.  The foreground of such  
          glyphs has to be drawn because it writes into the background  
          of tail.  The background must not be drawn because it could  
          paint over the foreground of following glyphs.  */  
       i = x_right_overwriting (tail);  
       if (i >= 0)  
         {  
           BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,  
                                DRAW_NORMAL_TEXT, x, last_x,  
                                overlaps_p);  
           for (s = h; s; s = s->next)  
             s->background_filled_p = 1;  
           x_compute_overhangs_and_x (h, tail->x + tail->width, 0);  
           x_append_glyph_string_lists (&head, &tail, h, t);  
         }  
     }  
   
   /* Draw all strings.  */  
   for (s = head; s; s = s->next)  
     x_draw_glyph_string (s);  
   
   if (area == TEXT_AREA  
       && !row->full_width_p  
       /* When drawing overlapping rows, only the glyph strings'  
          foreground is drawn, which doesn't erase a cursor  
          completely. */  
       && !overlaps_p)  
     {  
       int x0 = head ? head->x : x;  
       int x1 = tail ? tail->x + tail->background_width : x;  
         
       x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);  
       x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);  
         
       if (XFASTINT (w->left_margin_width) != 0)  
         {  
           int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);  
           x0 -= left_area_width;  
           x1 -= left_area_width;  
         }  
   
       notice_overwritten_cursor (w, area, x0, x1,  
                                  row->y, MATRIX_ROW_BOTTOM_Y (row));  
     }  
   
   /* Value is the x-position up to which drawn, relative to AREA of W.  
      This doesn't include parts drawn because of overhangs.  */  
   x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);  
   if (!row->full_width_p)  
     {  
       if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)  
         x_reached -= window_box_width (w, LEFT_MARGIN_AREA);  
       if (area > TEXT_AREA)  
         x_reached -= window_box_width (w, TEXT_AREA);  
     }  
     
   return x_reached;  
 }  
   
   
 /* Fix the display of area AREA of overlapping row ROW in window W.  */  
   
 static void  
 x_fix_overlapping_area (w, row, area)  
      struct window *w;  
      struct glyph_row *row;  
      enum glyph_row_area area;  
 {  
   int i, x;  
     
   BLOCK_INPUT;  
     
   if (area == LEFT_MARGIN_AREA)  
     x = 0;  
   else if (area == TEXT_AREA)  
     x = row->x + window_box_width (w, LEFT_MARGIN_AREA);  
   else  
     x = (window_box_width (w, LEFT_MARGIN_AREA)  
          + window_box_width (w, TEXT_AREA));  
   
   for (i = 0; i < row->used[area];)  
     {  
       if (row->glyphs[area][i].overlaps_vertically_p)  
         {  
           int start = i, start_x = x;  
   
           do  
             {  
               x += row->glyphs[area][i].pixel_width;  
               ++i;  
             }  
           while (i < row->used[area]  
                  && row->glyphs[area][i].overlaps_vertically_p);  
   
           x_draw_glyphs (w, start_x, row, area, start, i,  
                          DRAW_NORMAL_TEXT, 1);  
         }  
       else  
         {  
           x += row->glyphs[area][i].pixel_width;  
           ++i;  
         }  
     }  
     
   UNBLOCK_INPUT;  
 }  
   
   
 /* Output LEN glyphs starting at START at the nominal cursor position.  
    Advance the nominal cursor over the text.  The global variable  
    updated_window contains the window being updated, updated_row is  
    the glyph row being updated, and updated_area is the area of that  
    row being updated.  */  
   
 static void  
 x_write_glyphs (start, len)  
      struct glyph *start;  
      int len;  
 {  
   int x, hpos;  
   
   xassert (updated_window && updated_row);  
   BLOCK_INPUT;  
     
   /* Write glyphs.  */  
   
   hpos = start - updated_row->glyphs[updated_area];  
   x = x_draw_glyphs (updated_window, output_cursor.x,  
                      updated_row, updated_area,  
                      hpos, hpos + len,  
                      DRAW_NORMAL_TEXT, 0);  
   
   /* Invalidate old phys cursor if the glyph at its hpos is redrawn.  */  
   if (updated_area == TEXT_AREA  
       && updated_window->phys_cursor_on_p  
       && updated_window->phys_cursor.vpos == output_cursor.vpos  
       && updated_window->phys_cursor.hpos >= hpos  
       && updated_window->phys_cursor.hpos < hpos + len)  
     updated_window->phys_cursor_on_p = 0;  
   
   UNBLOCK_INPUT;  
     
   /* Advance the output cursor.  */  
   output_cursor.hpos += len;  
   output_cursor.x = x;  
 }  
   
   
 /* Insert LEN glyphs from START at the nominal cursor position.   */  
   
 static void  
 x_insert_glyphs (start, len)  
      struct glyph *start;  
      register int len;  
2684  {  {
   struct frame *f;  
   struct window *w;  
   int line_height, shift_by_width, shifted_region_width;  
   struct glyph_row *row;  
   struct glyph *glyph;  
   int frame_x, frame_y, hpos;  
   
   xassert (updated_window && updated_row);  
   BLOCK_INPUT;  
   w = updated_window;  
   f = XFRAME (WINDOW_FRAME (w));  
   
   /* Get the height of the line we are in.  */  
   row = updated_row;  
   line_height = row->height;  
   
   /* Get the width of the glyphs to insert.  */  
   shift_by_width = 0;  
   for (glyph = start; glyph < start + len; ++glyph)  
     shift_by_width += glyph->pixel_width;  
   
   /* Get the width of the region to shift right.  */  
   shifted_region_width = (window_box_width (w, updated_area)  
                           - output_cursor.x  
                           - shift_by_width);  
   
   /* Shift right.  */  
   frame_x = window_box_left (w, updated_area) + output_cursor.x;  
   frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);  
2685    XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),    XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
2686               f->output_data.x->normal_gc,               f->output_data.x->normal_gc,
2687               frame_x, frame_y,               x, y, width, height,
2688               shifted_region_width, line_height,               x + shift_by, y);
              frame_x + shift_by_width, frame_y);  
   
   /* Write the glyphs.  */  
   hpos = start - row->glyphs[updated_area];  
   x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,  
                  DRAW_NORMAL_TEXT, 0);  
     
   /* Advance the output cursor.  */  
   output_cursor.hpos += len;  
   output_cursor.x += shift_by_width;  
   UNBLOCK_INPUT;  
2689  }  }
2690    
   
2691  /* Delete N glyphs at the nominal cursor position.  Not implemented  /* Delete N glyphs at the nominal cursor position.  Not implemented
2692     for X frames.  */     for X frames.  */
2693    
# Line 5428  x_clear_area (dpy, window, x, y, width, Line 2715  x_clear_area (dpy, window, x, y, width,
2715  }  }
2716    
2717    
 /* Erase the current text line from the nominal cursor position  
    (inclusive) to pixel column TO_X (exclusive).  The idea is that  
    everything from TO_X onward is already erased.  
   
    TO_X is a pixel position relative to updated_area of  
    updated_window.  TO_X == -1 means clear to the end of this area.  */  
   
 static void  
 x_clear_end_of_line (to_x)  
      int to_x;  
 {  
   struct frame *f;  
   struct window *w = updated_window;  
   int max_x, min_y, max_y;  
   int from_x, from_y, to_y;  
     
   xassert (updated_window && updated_row);  
   f = XFRAME (w->frame);  
     
   if (updated_row->full_width_p)  
     {  
       max_x = XFASTINT (w->width) * CANON_X_UNIT (f);  
       if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)  
           && !w->pseudo_window_p)  
         max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);  
     }  
   else  
     max_x = window_box_width (w, updated_area);  
   max_y = window_text_bottom_y (w);  
   
   /* TO_X == 0 means don't do anything.  TO_X < 0 means clear to end  
      of window.  For TO_X > 0, truncate to end of drawing area.  */  
   if (to_x == 0)  
     return;  
   else if (to_x < 0)  
     to_x = max_x;  
   else  
     to_x = min (to_x, max_x);  
   
   to_y = min (max_y, output_cursor.y + updated_row->height);  
     
   /* Notice if the cursor will be cleared by this operation.  */  
   if (!updated_row->full_width_p)  
     notice_overwritten_cursor (w, updated_area,  
                                output_cursor.x, -1,  
                                updated_row->y,  
                                MATRIX_ROW_BOTTOM_Y (updated_row));  
   
   from_x = output_cursor.x;  
       
   /* Translate to frame coordinates.  */  
   if (updated_row->full_width_p)  
     {  
       from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);  
       to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);  
     }  
   else  
     {  
       from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);  
       to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);  
     }  
     
   min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);  
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));  
   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);  
     
   /* Prevent inadvertently clearing to end of the X window.  */  
   if (to_x > from_x && to_y > from_y)  
     {  
       BLOCK_INPUT;  
       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),  
                     from_x, from_y, to_x - from_x, to_y - from_y,  
                     False);  
       UNBLOCK_INPUT;  
     }  
 }  
   
   
2718  /* Clear entire frame.  If updating_frame is non-null, clear that  /* Clear entire frame.  If updating_frame is non-null, clear that
2719     frame.  Otherwise clear the selected frame.  */     frame.  Otherwise clear the selected frame.  */
2720    
# Line 5535  x_clear_frame () Line 2744  x_clear_frame ()
2744    x_scroll_bar_clear (f);    x_scroll_bar_clear (f);
2745    
2746    XFlush (FRAME_X_DISPLAY (f));    XFlush (FRAME_X_DISPLAY (f));
2747    
2748    #ifdef USE_GTK
2749      xg_frame_cleared (f);
2750    #endif
2751    
2752    UNBLOCK_INPUT;    UNBLOCK_INPUT;
2753  }  }
2754    
# Line 5563  timeval_subtract (result, x, y) Line 2777  timeval_subtract (result, x, y)
2777        y.tv_usec -= 1000000 * nsec;        y.tv_usec -= 1000000 * nsec;
2778        y.tv_sec += nsec;        y.tv_sec += nsec;
2779      }      }
2780      
2781    if (x.tv_usec - y.tv_usec > 1000000)    if (x.tv_usec - y.tv_usec > 1000000)
2782      {      {
2783        int nsec = (y.tv_usec - x.tv_usec) / 1000000;        int nsec = (y.tv_usec - x.tv_usec) / 1000000;
# Line 5647  XTflash (f) Line 2861  XTflash (f)
2861                            width, flash_height);                            width, flash_height);
2862          }          }
2863        else        else
2864          /* If it is short, flash it all.  */          /* If it is short, flash it all.  */
2865          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
2866                          flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),                          flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
2867                          width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));                          width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
# Line 5701  XTflash (f) Line 2915  XTflash (f)
2915                            width, flash_height);                            width, flash_height);
2916          }          }
2917        else        else
2918          /* If it is short, flash it all.  */          /* If it is short, flash it all.  */
2919          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
2920                          flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),                          flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
2921                          width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));                          width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
# Line 5723  void Line 2937  void
2937  XTring_bell ()  XTring_bell ()
2938  {  {
2939    struct frame *f = SELECTED_FRAME ();    struct frame *f = SELECTED_FRAME ();
2940      
2941    if (FRAME_X_DISPLAY (f))    if (FRAME_X_DISPLAY (f))
2942      {      {
2943  #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)  #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
# Line 5811  x_scroll_run (w, run) Line 3025  x_scroll_run (w, run)
3025      }      }
3026    
3027    BLOCK_INPUT;    BLOCK_INPUT;
3028      
3029    /* Cursor off.  Will be switched on again in x_update_window_end.  */    /* Cursor off.  Will be switched on again in x_update_window_end.  */
3030    updated_window = w;    updated_window = w;
3031    x_clear_cursor (w);    x_clear_cursor (w);
# Line 5822  x_scroll_run (w, run) Line 3036  x_scroll_run (w, run)
3036               x, from_y,               x, from_y,
3037               width, height,               width, height,
3038               x, to_y);               x, to_y);
3039      
3040    UNBLOCK_INPUT;    UNBLOCK_INPUT;
3041  }  }
3042    
# Line 5831  x_scroll_run (w, run) Line 3045  x_scroll_run (w, run)
3045  /***********************************************************************  /***********************************************************************
3046                             Exposure Events                             Exposure Events
3047   ***********************************************************************/   ***********************************************************************/
                                                                           
 /* Redisplay an exposed area of frame F.  X and Y are the upper-left  
    corner of the exposed rectangle.  W and H are width and height of  
    the exposed area.  All are pixel values.  W or H zero means redraw  
    the entire frame.  */  
   
 static void  
 expose_frame (f, x, y, w, h)  
      struct frame *f;  
      int x, y, w, h;  
 {  
   XRectangle r;  
   int mouse_face_overwritten_p = 0;  
   
   TRACE ((stderr, "expose_frame "));  
   
   /* No need to redraw if frame will be redrawn soon.  */  
   if (FRAME_GARBAGED_P (f))  
     {  
       TRACE ((stderr, " garbaged\n"));  
       return;  
     }  
   
   /* If basic faces haven't been realized yet, there is no point in  
      trying to redraw anything.  This can happen when we get an expose  
      event while Emacs is starting, e.g. by moving another window.  */  
   if (FRAME_FACE_CACHE (f) == NULL  
       || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)  
     {  
       TRACE ((stderr, " no faces\n"));  
       return;  
     }  
   
   if (w == 0 || h == 0)  
     {  
       r.x = r.y = 0;  
       r.width = CANON_X_UNIT (f) * f->width;  
       r.height = CANON_Y_UNIT (f) * f->height;  
     }  
   else  
     {  
       r.x = x;  
       r.y = y;  
       r.width = w;  
       r.height = h;  
     }  
   
   TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));  
   mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);  
   
   if (WINDOWP (f->tool_bar_window))  
     mouse_face_overwritten_p  
       |= expose_window (XWINDOW (f->tool_bar_window), &r);  
   
 #ifndef USE_X_TOOLKIT  
   if (WINDOWP (f->menu_bar_window))  
     mouse_face_overwritten_p  
       |= expose_window (XWINDOW (f->menu_bar_window), &r);  
 #endif /* not USE_X_TOOLKIT */  
   
   /* Some window managers support a focus-follows-mouse style with  
      delayed raising of frames.  Imagine a partially obscured frame,  
      and moving the mouse into partially obscured mouse-face on that  
      frame.  The visible part of the mouse-face will be highlighted,  
      then the WM raises the obscured frame.  With at least one WM, KDE  
      2.1, Emacs is not getting any event for the raising of the frame  
      (even tried with SubstructureRedirectMask), only Expose events.  
      These expose events will draw text normally, i.e. not  
      highlighted.  Which means we must redo the highlight here.  
      Subsume it under ``we love X''.  --gerd 2001-08-15  */  
   if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))  
     {  
       struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);  
       if (f == dpyinfo->mouse_face_mouse_frame)  
         {  
           int x = dpyinfo->mouse_face_mouse_x;  
           int y = dpyinfo->mouse_face_mouse_y;  
           clear_mouse_face (dpyinfo);  
           note_mouse_highlight (f, x, y);  
         }  
     }  
 }  
   
   
 /* Redraw (parts) of all windows in the window tree rooted at W that  
    intersect R.  R contains frame pixel coordinates.  Value is  
    non-zero if the exposure overwrites mouse-face.  */  
   
 static int  
 expose_window_tree (w, r)  
      struct window *w;  
      XRectangle *r;  
 {  
   struct frame *f = XFRAME (w->frame);  
   int mouse_face_overwritten_p = 0;  
     
   while (w && !FRAME_GARBAGED_P (f))  
     {  
       if (!NILP (w->hchild))  
         mouse_face_overwritten_p  
           |= expose_window_tree (XWINDOW (w->hchild), r);  
       else if (!NILP (w->vchild))  
         mouse_face_overwritten_p  
           |= expose_window_tree (XWINDOW (w->vchild), r);  
       else  
         mouse_face_overwritten_p |= expose_window (w, r);  
         
       w = NILP (w->next) ? NULL : XWINDOW (w->next);  
     }  
   
   return mouse_face_overwritten_p;  
 }  
   
   
 /* Redraw the part of glyph row area AREA of glyph row ROW on window W  
    which intersects rectangle R.  R is in window-relative coordinates.  */  
   
 static void  
 expose_area (w, row, r, area)  
      struct window *w;  
      struct glyph_row *row;  
      XRectangle *r;  
      enum glyph_row_area area;  
 {  
   struct glyph *first = row->glyphs[area];  
   struct glyph *end = row->glyphs[area] + row->used[area];  
   struct glyph *last;  
   int first_x, start_x, x;  
   
   if (area == TEXT_AREA && row->fill_line_p)  
     /* If row extends face to end of line write the whole line.  */  
     x_draw_glyphs (w, 0, row, area, 0, row->used[area],  
                    DRAW_NORMAL_TEXT, 0);  
   else  
     {  
       /* Set START_X to the window-relative start position for drawing glyphs of  
          AREA.  The first glyph of the text area can be partially visible.  
          The first glyphs of other areas cannot.  */  
       if (area == LEFT_MARGIN_AREA)  
         start_x = 0;  
       else if (area == TEXT_AREA)  
         start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);  
       else  
         start_x = (window_box_width (w, LEFT_MARGIN_AREA)  
                    + window_box_width (w, TEXT_AREA));  
       x = start_x;  
   
       /* Find the first glyph that must be redrawn.  */  
       while (first < end  
              && x + first->pixel_width < r->x)  
         {  
           x += first->pixel_width;  
           ++first;  
         }  
         
       /* Find the last one.  */  
       last = first;  
       first_x = x;  
       while (last < end  
              && x < r->x + r->width)  
         {  
           x += last->pixel_width;  
           ++last;  
         }  
         
       /* Repaint.  */  
       if (last > first)  
         x_draw_glyphs (w, first_x - start_x, row, area,  
                        first - row->glyphs[area],  
                        last - row->glyphs[area],  
                        DRAW_NORMAL_TEXT, 0);  
     }  
 }  
         
   
 /* Redraw the parts of the glyph row ROW on window W intersecting  
    rectangle R.  R is in window-relative coordinates.  Value is  
    non-zero if mouse-face was overwritten.  */  
   
 static int  
 expose_line (w, row, r)  
      struct window *w;  
      struct glyph_row *row;  
      XRectangle *r;  
 {  
   xassert (row->enabled_p);  
     
   if (row->mode_line_p || w->pseudo_window_p)  
     x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],  
                    DRAW_NORMAL_TEXT, 0);  
   else  
     {  
       if (row->used[LEFT_MARGIN_AREA])  
         expose_area (w, row, r, LEFT_MARGIN_AREA);  
       if (row->used[TEXT_AREA])  
         expose_area (w, row, r, TEXT_AREA);  
       if (row->used[RIGHT_MARGIN_AREA])  
         expose_area (w, row, r, RIGHT_MARGIN_AREA);  
       x_draw_row_fringe_bitmaps (w, row);  
     }  
   
   return row->mouse_face_p;  
 }  
   
   
 /* Return non-zero if W's cursor intersects rectangle R.  */  
   
 static int  
 x_phys_cursor_in_rect_p (w, r)  
      struct window *w;  
      XRectangle *r;  
 {  
   XRectangle cr, result;  
   struct glyph *cursor_glyph;  
   
   cursor_glyph = get_phys_cursor_glyph (w);  
   if (cursor_glyph)  
     {  
       cr.x = w->phys_cursor.x;  
       cr.y = w->phys_cursor.y;  
       cr.width = cursor_glyph->pixel_width;  
       cr.height = w->phys_cursor_height;  
       return x_intersect_rectangles (&cr, r, &result);  
     }  
   else  
     return 0;  
 }  
   
   
 /* Redraw the part of window W intersection rectangle FR.  Pixel  
    coordinates in FR are frame-relative.  Call this function with  
    input blocked.  Value is non-zero if the exposure overwrites  
    mouse-face.  */  
   
 static int  
 expose_window (w, fr)  
      struct window *w;  
      XRectangle *fr;  
 {  
   struct frame *f = XFRAME (w->frame);  
   XRectangle wr, r;  
   int mouse_face_overwritten_p = 0;  
   
   /* If window is not yet fully initialized, do nothing.  This can  
      happen when toolkit scroll bars are used and a window is split.  
      Reconfiguring the scroll bar will generate an expose for a newly  
      created window.  */  
   if (w->current_matrix == NULL)  
     return 0;  
   
   /* When we're currently updating the window, display and current  
      matrix usually don't agree.  Arrange for a thorough display  
      later.  */  
   if (w == updated_window)  
     {  
       SET_FRAME_GARBAGED (f);  
       return 0;  
     }  
   
   /* Frame-relative pixel rectangle of W.  */  
   wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);  
   wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);  
   wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);  
   wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);  
   
   if (x_intersect_rectangles (fr, &wr, &r))  
     {  
       int yb = window_text_bottom_y (w);  
       struct glyph_row *row;  
       int cursor_cleared_p;  
     
       TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",  
               r.x, r.y, r.width, r.height));  
   
       /* Convert to window coordinates.  */  
       r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);  
       r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);  
   
       /* Turn off the cursor.  */  
       if (!w->pseudo_window_p  
           && x_phys_cursor_in_rect_p (w, &r))  
         {  
           x_clear_cursor (w);  
           cursor_cleared_p = 1;  
         }  
       else  
         cursor_cleared_p = 0;  
   
       /* Find the first row intersecting the rectangle R.  */  
       for (row = w->current_matrix->rows;  
            row->enabled_p;  
            ++row)  
         {  
           int y0 = row->y;  
           int y1 = MATRIX_ROW_BOTTOM_Y (row);  
             
           if ((y0 >= r.y && y0 < r.y + r.height)  
               || (y1 > r.y && y1 < r.y + r.height)  
               || (r.y >= y0 && r.y < y1)  
               || (r.y + r.height > y0 && r.y + r.height < y1))  
             {  
               if (expose_line (w, row, &r))  
                 mouse_face_overwritten_p = 1;  
             }  
                 
           if (y1 >= yb)  
             break;  
         }  
   
       /* Display the mode line if there is one.  */  
       if (WINDOW_WANTS_MODELINE_P (w)  
           && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),  
               row->enabled_p)  
           && row->y < r.y + r.height)  
         {  
           if (expose_line (w, row, &r))  
             mouse_face_overwritten_p = 1;  
         }  
   
       if (!w->pseudo_window_p)  
         {  
           /* Draw border between windows.  */  
           x_draw_vertical_border (w);  
         
           /* Turn the cursor on again.  */  
           if (cursor_cleared_p)  
             x_update_window_cursor (w, 1);  
         }  
     }  
   
   return mouse_face_overwritten_p;  
 }  
   
   
 /* Determine the intersection of two rectangles R1 and R2.  Return  
    the intersection in *RESULT.  Value is non-zero if RESULT is not  
    empty.  */  
   
 static int  
 x_intersect_rectangles (r1, r2, result)  
      XRectangle *r1, *r2, *result;  
 {  
   XRectangle *left, *right;  
   XRectangle *upper, *lower;  
   int intersection_p = 0;  
     
   /* Rearrange so that R1 is the left-most rectangle.  */  
   if (r1->x < r2->x)  
     left = r1, right = r2;  
   else  
     left = r2, right = r1;  
   
   /* X0 of the intersection is right.x0, if this is inside R1,  
      otherwise there is no intersection.  */  
   if (right->x <= left->x + left->width)  
     {  
       result->x = right->x;  
         
       /* The right end of the intersection is the minimum of the  
          the right ends of left and right.  */  
       result->width = (min (left->x + left->width, right->x + right->width)  
                        - result->x);  
   
       /* Same game for Y.  */  
       if (r1->y < r2->y)  
         upper = r1, lower = r2;  
       else  
         upper = r2, lower = r1;  
   
       /* The upper end of the intersection is lower.y0, if this is inside  
          of upper.  Otherwise, there is no intersection.  */  
       if (lower->y <= upper->y + upper->height)  
         {  
           result->y = lower->y;  
             
           /* The lower end of the intersection is the minimum of the lower  
              ends of upper and lower.  */  
           result->height = (min (lower->y + lower->height,  
                                  upper->y + upper->height)  
                             - result->y);  
           intersection_p = 1;  
         }  
     }  
   
   return intersection_p;  
 }  
   
   
   
3048    
3049    
3050  static void  static void
# Line 6291  x_new_focus_frame (dpyinfo, frame) Line 3116  x_new_focus_frame (dpyinfo, frame)
3116    x_frame_rehighlight (dpyinfo);    x_frame_rehighlight (dpyinfo);
3117  }  }
3118    
3119    /* Handle FocusIn and FocusOut state changes for FRAME.
3120       If FRAME has focus and there exists more than one frame, puts
3121       a FOCUS_IN_EVENT into BUFP.
3122       Returns number of events inserted into BUFP. */
3123    
3124    static int
3125    x_focus_changed (type, state, dpyinfo, frame, bufp, numchars)
3126         int type;
3127         int state;
3128         struct x_display_info *dpyinfo;
3129         struct frame *frame;
3130         struct input_event *bufp;
3131         int numchars;
3132    {
3133      int nr_events = 0;
3134    
3135      if (type == FocusIn)
3136        {
3137          if (dpyinfo->x_focus_event_frame != frame)
3138            {
3139              x_new_focus_frame (dpyinfo, frame);
3140              dpyinfo->x_focus_event_frame = frame;
3141    
3142              /* Don't stop displaying the initial startup message
3143                 for a switch-frame event we don't need.  */
3144              if (numchars > 0
3145                  && GC_NILP (Vterminal_frame)
3146                  && GC_CONSP (Vframe_list)
3147                  && !GC_NILP (XCDR (Vframe_list)))
3148                {
3149                  bufp->kind = FOCUS_IN_EVENT;
3150                  XSETFRAME (bufp->frame_or_window, frame);
3151                  bufp->arg = Qnil;
3152                  ++bufp;
3153                  numchars--;
3154                  ++nr_events;
3155                }
3156            }
3157    
3158          frame->output_data.x->focus_state |= state;
3159    
3160    #ifdef HAVE_X_I18N
3161          if (FRAME_XIC (frame))
3162            XSetICFocus (FRAME_XIC (frame));
3163    #endif
3164        }
3165      else if (type == FocusOut)
3166        {
3167          frame->output_data.x->focus_state &= ~state;
3168    
3169          if (dpyinfo->x_focus_event_frame == frame)
3170            {
3171              dpyinfo->x_focus_event_frame = 0;
3172              x_new_focus_frame (dpyinfo, 0);
3173            }
3174    
3175    #ifdef HAVE_X_I18N
3176          if (FRAME_XIC (frame))
3177            XUnsetICFocus (FRAME_XIC (frame));
3178    #endif
3179        }
3180    
3181      return nr_events;
3182    }
3183    
3184    /* The focus may have changed.  Figure out if it is a real focus change,
3185       by checking both FocusIn/Out and Enter/LeaveNotify events.
3186    
3187       Returns number of events inserted into BUFP. */
3188    
3189    static int
3190    x_detect_focus_change (dpyinfo, event, bufp, numchars)
3191         struct x_display_info *dpyinfo;
3192         XEvent *event;
3193         struct input_event *bufp;
3194         int numchars;
3195    {
3196      struct frame *frame;
3197      int nr_events = 0;
3198    
3199      frame = x_any_window_to_frame (dpyinfo, event->xany.window);
3200      if (! frame) return nr_events;
3201    
3202      switch (event->type)
3203        {
3204        case EnterNotify:
3205        case LeaveNotify:
3206          if (event->xcrossing.detail != NotifyInferior
3207              && event->xcrossing.focus
3208              && ! (frame->output_data.x->focus_state & FOCUS_EXPLICIT))
3209            nr_events = x_focus_changed ((event->type == EnterNotify
3210                                          ? FocusIn : FocusOut),
3211                                         FOCUS_IMPLICIT,
3212                                         dpyinfo,
3213                                         frame,
3214                                         bufp,
3215                                         numchars);
3216          break;
3217    
3218        case FocusIn:
3219        case FocusOut:
3220          nr_events = x_focus_changed (event->type,
3221                                       (event->xfocus.detail == NotifyPointer
3222                                        ? FOCUS_IMPLICIT : FOCUS_EXPLICIT),
3223                                       dpyinfo,
3224                                       frame,
3225                                       bufp,
3226                                       numchars);
3227          break;
3228        }
3229    
3230      return nr_events;
3231    }
3232    
3233    
3234  /* Handle an event saying the mouse has moved out of an Emacs frame.  */  /* Handle an event saying the mouse has moved out of an Emacs frame.  */
3235    
3236  void  void
# Line 6464  x_x_to_emacs_modifiers (dpyinfo, state) Line 3404  x_x_to_emacs_modifiers (dpyinfo, state)
3404    EMACS_UINT mod_hyper = hyper_modifier;    EMACS_UINT mod_hyper = hyper_modifier;
3405    EMACS_UINT mod_super = super_modifier;    EMACS_UINT mod_super = super_modifier;
3406    Lisp_Object tem;    Lisp_Object tem;
3407      
3408    tem = Fget (Vx_alt_keysym, Qmodifier_value);    tem = Fget (Vx_alt_keysym, Qmodifier_value);
3409    if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);    if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
3410    tem = Fget (Vx_meta_keysym, Qmodifier_value);    tem = Fget (Vx_meta_keysym, Qmodifier_value);
# Line 6473  x_x_to_emacs_modifiers (dpyinfo, state) Line 3413  x_x_to_emacs_modifiers (dpyinfo, state)
3413    if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);    if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
3414    tem = Fget (Vx_super_keysym, Qmodifier_value);    tem = Fget (Vx_super_keysym, Qmodifier_value);
3415    if (! EQ (tem, Qnil)) mod_super = XUINT (tem);    if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
3416      
3417    
3418    return (  ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)    return (  ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
3419              | ((state & ControlMask)                    ? ctrl_modifier : 0)              | ((state & ControlMask)                    ? ctrl_modifier : 0)
# Line 6492  x_emacs_to_x_modifiers (dpyinfo, state) Line 3432  x_emacs_to_x_modifiers (dpyinfo, state)
3432    EMACS_UINT mod_alt  = alt_modifier;    EMACS_UINT mod_alt  = alt_modifier;
3433    EMACS_UINT mod_hyper = hyper_modifier;    EMACS_UINT mod_hyper = hyper_modifier;
3434    EMACS_UINT mod_super = super_modifier;    EMACS_UINT mod_super = super_modifier;
3435      
3436    Lisp_Object tem;    Lisp_Object tem;
3437      
3438    tem = Fget (Vx_alt_keysym, Qmodifier_value);    tem = Fget (Vx_alt_keysym, Qmodifier_value);
3439    if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);    if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
3440    tem = Fget (Vx_meta_keysym, Qmodifier_value);    tem = Fget (Vx_meta_keysym, Qmodifier_value);
# Line 6503  x_emacs_to_x_modifiers (dpyinfo, state) Line 3443  x_emacs_to_x_modifiers (dpyinfo, state)
3443    if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);    if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
3444    tem = Fget (Vx_super_keysym, Qmodifier_value);    tem = Fget (Vx_super_keysym, Qmodifier_value);
3445    if (! EQ (tem, Qnil)) mod_super = XUINT (tem);    if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
3446      
3447      
3448    return (  ((state & mod_alt)          ? dpyinfo->alt_mod_mask   : 0)    return (  ((state & mod_alt)          ? dpyinfo->alt_mod_mask   : 0)
3449              | ((state & mod_super)      ? dpyinfo->super_mod_mask : 0)              | ((state & mod_super)      ? dpyinfo->super_mod_mask : 0)
3450              | ((state & mod_hyper)      ? dpyinfo->hyper_mod_mask : 0)              | ((state & mod_hyper)      ? dpyinfo->hyper_mod_mask : 0)
# Line 6532  x_get_keysym_name (keysym) Line 3472  x_get_keysym_name (keysym)
3472    
3473  /* Mouse clicks and mouse movement.  Rah.  */  /* Mouse clicks and mouse movement.  Rah.  */
3474    
 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph  
    co-ordinates in (*X, *Y).  Set *BOUNDS to the rectangle that the  
    glyph at X, Y occupies, if BOUNDS != 0.  If NOCLIP is non-zero, do  
    not force the value into range.  */  
   
 void  
 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)  
      FRAME_PTR f;  
      register int pix_x, pix_y;  
      register int *x, *y;  
      XRectangle *bounds;  
      int noclip;  
 {  
   /* Arrange for the division in PIXEL_TO_CHAR_COL etc.  to round down  
      even for negative values.  */  
   if (pix_x < 0)  
     pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;  
   if (pix_y < 0)  
     pix_y -= (f)->output_data.x->line_height - 1;  
   
   pix_x = PIXEL_TO_CHAR_COL (f, pix_x);  
   pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);  
   
   if (bounds)  
     {  
       bounds->width  = FONT_WIDTH  (f->output_data.x->font);  
       bounds->height = f->output_data.x->line_height;  
       bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);  
       bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);  
     }  
   
   if (!noclip)  
     {  
       if (pix_x < 0)  
         pix_x = 0;  
       else if (pix_x > FRAME_WINDOW_WIDTH (f))  
         pix_x = FRAME_WINDOW_WIDTH (f);  
   
       if (pix_y < 0)  
         pix_y = 0;  
       else if (pix_y > f->height)  
         pix_y = f->height;  
     }  
   
   *x = pix_x;  
   *y = pix_y;  
 }  
   
   
 /* Given HPOS/VPOS in the current matrix of W, return corresponding  
    frame-relative pixel positions in *FRAME_X and *FRAME_Y.  If we  
    can't tell the positions because W's display is not up to date,  
    return 0.  */  
   
 int  
 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)  
      struct window *w;  
      int hpos, vpos;  
      int *frame_x, *frame_y;  
 {  
   int success_p;  
   
   xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);  
   xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);  
   
   if (display_completed)  
     {  
       struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);  
       struct glyph *glyph = row->glyphs[TEXT_AREA];  
       struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);  
   
       *frame_y = row->y;  
       *frame_x = row->x;  
       while (glyph < end)  
         {  
           *frame_x += glyph->pixel_width;  
           ++glyph;  
         }  
   
       success_p = 1;  
     }  
   else  
     {  
       *frame_y = *frame_x = 0;  
       success_p = 0;  
     }  
   
   *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);  
   *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);  
   return success_p;  
 }  
   
   
3475  /* Prepare a mouse-event in *RESULT for placement in the input queue.  /* Prepare a mouse-event in *RESULT for placement in the input queue.
3476    
3477     If the event is a button press, then note that we have grabbed     If the event is a button press, then note that we have grabbed
# Line 6636  construct_mouse_click (result, event, f) Line 3483  construct_mouse_click (result, event, f)
3483       XButtonEvent *event;       XButtonEvent *event;
3484       struct frame *f;       struct frame *f;
3485  {  {
3486    /* Make the event type no_event; we'll change that when we decide    /* Make the event type NO_EVENT; we'll change that when we decide
3487       otherwise.  */       otherwise.  */
3488    result->kind = mouse_click;    result->kind = MOUSE_CLICK_EVENT;
3489    result->code = event->button - Button1;    result->code = event->button - Button1;
3490    result->timestamp = event->time;    result->timestamp = event->time;
3491    result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),    result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
# Line 6699  note_mouse_movement (frame, event) Line 3546  note_mouse_movement (frame, event)
3546                                Mouse Face                                Mouse Face
3547   ************************************************************************/   ************************************************************************/
3548    
 /* Find the glyph under window-relative coordinates X/Y in window W.  
    Consider only glyphs from buffer text, i.e. no glyphs from overlay  
    strings.  Return in *HPOS and *VPOS the row and column number of  
    the glyph found.  Return in *AREA the glyph area containing X.  
    Value is a pointer to the glyph found or null if X/Y is not on  
    text, or we can't tell because W's current matrix is not up to  
    date.  */  
   
 static struct glyph *  
 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)  
      struct window *w;  
      int x, y;  
      int *hpos, *vpos, *area;  
      int buffer_only_p;  
 {  
   struct glyph *glyph, *end;  
   struct glyph_row *row = NULL;  
   int x0, i, left_area_width;  
   
   /* Find row containing Y.  Give up if some row is not enabled.  */  
   for (i = 0; i < w->current_matrix->nrows; ++i)  
     {  
       row = MATRIX_ROW (w->current_matrix, i);  
       if (!row->enabled_p)  
         return NULL;  
       if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))  
         break;  
     }  
   
   *vpos = i;  
   *hpos = 0;  
   
   /* Give up if Y is not in the window.  */  
   if (i == w->current_matrix->nrows)  
     return NULL;  
   
   /* Get the glyph area containing X.  */  
   if (w->pseudo_window_p)  
     {  
       *area = TEXT_AREA;  
       x0 = 0;  
     }  
   else  
     {  
       left_area_width = window_box_width (w, LEFT_MARGIN_AREA);  
       if (x < left_area_width)  
         {  
           *area = LEFT_MARGIN_AREA;  
           x0 = 0;  
         }  
       else if (x < left_area_width + window_box_width (w, TEXT_AREA))  
         {  
           *area = TEXT_AREA;  
           x0 = row->x + left_area_width;  
         }  
       else  
         {  
           *area = RIGHT_MARGIN_AREA;  
           x0 = left_area_width + window_box_width (w, TEXT_AREA);  
         }  
     }  
   
   /* Find glyph containing X.  */  
   glyph = row->glyphs[*area];  
   end = glyph + row->used[*area];  
   while (glyph < end)  
     {  
       if (x < x0 + glyph->pixel_width)  
         {  
           if (w->pseudo_window_p)  
             break;  
           else if (!buffer_only_p || BUFFERP (glyph->object))  
             break;  
         }  
         
       x0 += glyph->pixel_width;  
       ++glyph;  
     }  
   
   if (glyph == end)  
     return NULL;  
   
   *hpos = glyph - row->glyphs[*area];  
   return glyph;  
 }  
   
   
 /* Convert frame-relative x/y to coordinates relative to window W.  
    Takes pseudo-windows into account.  */  
   
 static void  
 frame_to_window_pixel_xy (w, x, y)  
      struct window *w;  
      int *x, *y;  
 {  
   if (w->pseudo_window_p)  
     {  
       /* A pseudo-window is always full-width, and starts at the  
          left edge of the frame, plus a frame border.  */  
       struct frame *f = XFRAME (w->frame);  
       *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);  
       *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);  
     }  
   else  
     {  
       *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);  
       *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);  
     }  
 }  
   
   
 /* Take proper action when mouse has moved to the mode or header line  
    or marginal area of window W, x-position X and y-position Y.  Area  
    is 1, 3, 6 or 7 for the mode line, header line, left and right  
    marginal area respectively.  X is relative to the start of the text  
    display area of W, so the width of bitmap areas and scroll bars  
    must be subtracted to get a position relative to the start of the  
    mode line.  */  
   
 static void  
 note_mode_line_or_margin_highlight (w, x, y, portion)  
      struct window *w;  
      int x, y, portion;  
 {  
   struct frame *f = XFRAME (w->frame);  
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);  
   Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;  
   int charpos;  
   Lisp_Object string, help, map, pos;  
   
   if (portion == 1 || portion == 3)  
     string = mode_line_string (w, x, y, portion == 1, &charpos);  
    else  
      string = marginal_area_string (w, x, y, portion, &charpos);  
   
   if (STRINGP (string))  
     {  
       pos = make_number (charpos);  
         
       /* If we're on a string with `help-echo' text property, arrange  
          for the help to be displayed.  This is done by setting the  
          global variable help_echo to the help string.  */  
       help = Fget_text_property (pos, Qhelp_echo, string);  
       if (!NILP (help))  
         {  
           help_echo = help;  
           XSETWINDOW (help_echo_window, w);  
           help_echo_object = string;  
           help_echo_pos = charpos;  
         }  
   
      /* Change the mouse pointer according to what is under X/Y.  */  
       map = Fget_text_property (pos, Qlocal_map, string);  
       if (!KEYMAPP (map))  
         map = Fget_text_property (pos, Qkeymap, string);  
       if (KEYMAPP (map))  
         cursor = f->output_data.x->nontext_cursor;  
     }  
     
   XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);  
 }  
   
   
 /* Take proper action when the mouse has moved to position X, Y on  
    frame F as regards highlighting characters that have mouse-face  
    properties.  Also de-highlighting chars where the mouse was before.  
    X and Y can be negative or out of range.  */  
   
 static void  
 note_mouse_highlight (f, x, y)  
      struct frame *f;  
      int x, y;  
 {  
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);  
   int portion;  
   Lisp_Object window;  
   struct window *w;  
   Cursor cursor = None;  
   struct buffer *b;  
   
   /* When a menu is active, don't highlight because this looks odd.  */  
 #ifdef USE_X_TOOLKIT  
   if (popup_activated ())  
     return;  
 #endif  
   
   if (NILP (Vmouse_highlight)  
       || !f->glyphs_initialized_p)  
     return;  
   
   dpyinfo->mouse_face_mouse_x = x;  
   dpyinfo->mouse_face_mouse_y = y;  
   dpyinfo->mouse_face_mouse_frame = f;  
   
   if (dpyinfo->mouse_face_defer)  
     return;  
   
   if (gc_in_progress)  
     {  
       dpyinfo->mouse_face_deferred_gc = 1;  
       return;  
     }  
   
   /* Which window is that in?  */  
   window = window_from_coordinates (f, x, y, &portion, 1);  
   
   /* If we were displaying active text in another window, clear that.  */  
   if (! EQ (window, dpyinfo->mouse_face_window))  
     clear_mouse_face (dpyinfo);  
   
   /* Not on a window -> return.  */  
   if (!WINDOWP (window))  
     return;  
   
   /* Convert to window-relative pixel coordinates.  */  
   w = XWINDOW (window);  
   frame_to_window_pixel_xy (w, &x, &y);  
   
   /* Handle tool-bar window differently since it doesn't display a  
      buffer.  */  
   if (EQ (window, f->tool_bar_window))  
     {  
       note_tool_bar_highlight (f, x, y);  
       return;  
     }  
   
   /* Mouse is on the mode, header line or margin?  */  
   if (portion == 1 || portion == 3 || portion == 6 || portion == 7)  
     {  
       note_mode_line_or_margin_highlight (w, x, y, portion);  
       return;  
     }  
     
   if (portion == 2)  
     cursor = f->output_data.x->horizontal_drag_cursor;  
   else  
     cursor = f->output_data.x->text_cursor;  
   
   /* Are we in a window whose display is up to date?  
      And verify the buffer's text has not changed.  */  
   b = XBUFFER (w->buffer);  
   if (/* Within text portion of the window.  */  
       portion == 0  
       && EQ (w->window_end_valid, w->buffer)  
       && XFASTINT (w->last_modified) == BUF_MODIFF (b)  
       && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))  
     {  
       int hpos, vpos, pos, i, area;  
       struct glyph *glyph;  
       Lisp_Object object;  
       Lisp_Object mouse_face = Qnil, overlay = Qnil, position;  
       Lisp_Object *overlay_vec = NULL;  
       int len, noverlays;  
       struct buffer *obuf;  
       int obegv, ozv, same_region;  
   
       /* Find the glyph under X/Y.  */  
       glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);  
   
       /* Clear mouse face if X/Y not over text.  */  
       if (glyph == NULL  
           || area != TEXT_AREA  
           || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)  
         {  
           if (clear_mouse_face (dpyinfo))  
             cursor = None;  
           goto set_cursor;  
         }  
   
       pos = glyph->charpos;  
       object = glyph->object;  
       if (!STRINGP (object) && !BUFFERP (object))  
         goto set_cursor;  
   
       /* If we get an out-of-range value, return now; avoid an error.  */  
       if (BUFFERP (object) && pos > BUF_Z (b))  
         goto set_cursor;  
   
       /* Make the window's buffer temporarily current for  
          overlays_at and compute_char_face.  */  
       obuf = current_buffer;  
       current_buffer = b;  
       obegv = BEGV;  
       ozv = ZV;  
       BEGV = BEG;  
       ZV = Z;  
   
       /* Is this char mouse-active or does it have help-echo?  */  
       position = make_number (pos);  
   
       if (BUFFERP (object))  
         {  
           /* Put all the overlays we want in a vector in overlay_vec.  
              Store the length in len.  If there are more than 10, make  
              enough space for all, and try again.  */  
           len = 10;  
           overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));  
           noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);  
           if (noverlays > len)  
             {  
               len = noverlays;  
               overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));  
               noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);  
             }  
   
           /* Sort overlays into increasing priority order.  */  
           noverlays = sort_overlays (overlay_vec, noverlays, w);  
         }  
       else  
         noverlays = 0;  
   
       same_region = (EQ (window, dpyinfo->mouse_face_window)  
                      && vpos >= dpyinfo->mouse_face_beg_row  
                      && vpos <= dpyinfo->mouse_face_end_row  
                      && (vpos > dpyinfo->mouse_face_beg_row  
                          || hpos >= dpyinfo->mouse_face_beg_col)  
                      && (vpos < dpyinfo->mouse_face_end_row  
                          || hpos < dpyinfo->mouse_face_end_col  
                          || dpyinfo->mouse_face_past_end));  
   
       if (same_region)  
         cursor = None;  
   
       /* Check mouse-face highlighting.  */  
       if (! same_region  
           /* If there exists an overlay with mouse-face overlapping  
              the one we are currently highlighting, we have to  
              check if we enter the overlapping overlay, and then  
              highlight only that.  */  
           || (OVERLAYP (dpyinfo->mouse_face_overlay)  
               && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))  
         {  
           /* Find the highest priority overlay that has a mouse-face  
              property.  */  
           overlay = Qnil;  
           for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)  
             {  
               mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);  
               if (!NILP (mouse_face))  
                 overlay = overlay_vec[i];  
             }  
             
           /* If we're actually highlighting the same overlay as  
              before, there's no need to do that again.  */  
           if (!NILP (overlay)  
               && EQ (overlay, dpyinfo->mouse_face_overlay))  
             goto check_help_echo;  
               
           dpyinfo->mouse_face_overlay = overlay;  
   
           /* Clear the display of the old active region, if any.  */  
           if (clear_mouse_face (dpyinfo))  
             cursor = None;  
   
           /* If no overlay applies, get a text property.  */  
           if (NILP (overlay))  
             mouse_face = Fget_text_property (position, Qmouse_face, object);  
   
           /* Handle the overlay case.  */  
           if (!NILP (overlay))  
             {  
               /* Find the range of text around this char that  
                  should be active.  */  
               Lisp_Object before, after;  
               int ignore;  
   
               before = Foverlay_start (overlay);  
               after = Foverlay_end (overlay);  
               /* Record this as the current active region.  */  
               fast_find_position (w, XFASTINT (before),  
                                   &dpyinfo->mouse_face_beg_col,  
                                   &dpyinfo->mouse_face_beg_row,  
                                   &dpyinfo->mouse_face_beg_x,  
                                   &dpyinfo->mouse_face_beg_y, Qnil);  
                         
               dpyinfo->mouse_face_past_end  
                 = !fast_find_position (w, XFASTINT (after),  
                                        &dpyinfo->mouse_face_end_col,  
                                        &dpyinfo->mouse_face_end_row,  
                                        &dpyinfo->mouse_face_end_x,  
                                        &dpyinfo->mouse_face_end_y, Qnil);  
               dpyinfo->mouse_face_window = window;  
               dpyinfo->mouse_face_face_id  
                 = face_at_buffer_position (w, pos, 0, 0,  
                                            &ignore, pos + 1, 1);  
   
               /* Display it as active.  */  
               show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);  
               cursor = None;  
             }  
           /* Handle the text property case.  */  
           else if (!NILP (mouse_face) && BUFFERP (object))  
             {  
               /* Find the range of text around this char that  
                  should be active.  */  
               Lisp_Object before, after, beginning, end;  
               int ignore;  
   
               beginning = Fmarker_position (w->start);  
               end = make_number (BUF_Z (XBUFFER (object))  
                                  - XFASTINT (w->window_end_pos));  
               before  
                 = Fprevious_single_property_change (make_number (pos + 1),  
                                                     Qmouse_face,  
                                                     object, beginning);  
               after  
                 = Fnext_single_property_change (position, Qmouse_face,  
                                                 object, end);  
                   
               /* Record this as the current active region.  */  
               fast_find_position (w, XFASTINT (before),  
                                   &dpyinfo->mouse_face_beg_col,  
                                   &dpyinfo->mouse_face_beg_row,  
                                   &dpyinfo->mouse_face_beg_x,  
                                   &dpyinfo->mouse_face_beg_y, Qnil);  
               dpyinfo->mouse_face_past_end  
                 = !fast_find_position (w, XFASTINT (after),  
                                        &dpyinfo->mouse_face_end_col,  
                                        &dpyinfo->mouse_face_end_row,  
                                        &dpyinfo->mouse_face_end_x,  
                                        &dpyinfo->mouse_face_end_y, Qnil);  
               dpyinfo->mouse_face_window = window;  
   
               if (BUFFERP (object))  
                 dpyinfo->mouse_face_face_id  
                   = face_at_buffer_position (w, pos, 0, 0,  
                                              &ignore, pos + 1, 1);  
   
               /* Display it as active.  */  
               show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);  
               cursor = None;  
             }  
           else if (!NILP (mouse_face) && STRINGP (object))  
             {  
               Lisp_Object b, e;  
               int ignore;  
                   
               b = Fprevious_single_property_change (make_number (pos + 1),  
                                                     Qmouse_face,  
                                                     object, Qnil);  
               e = Fnext_single_property_change (position, Qmouse_face,  
                                                 object, Qnil);  
               if (NILP (b))  
                 b = make_number (0);  
               if (NILP (e))  
                 e = make_number (XSTRING (object)->size - 1);  
               fast_find_string_pos (w, XINT (b), object,  
                                     &dpyinfo->mouse_face_beg_col,  
                                     &dpyinfo->mouse_face_beg_row,  
                                     &dpyinfo->mouse_face_beg_x,  
                                     &dpyinfo->mouse_face_beg_y, 0);  
               fast_find_string_pos (w, XINT (e), object,  
                                     &dpyinfo->mouse_face_end_col,  
                                     &dpyinfo->mouse_face_end_row,  
                                     &dpyinfo->mouse_face_end_x,  
                                     &dpyinfo->mouse_face_end_y, 1);  
               dpyinfo->mouse_face_past_end = 0;  
               dpyinfo->mouse_face_window = window;  
               dpyinfo->mouse_face_face_id  
                 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,  
                                            glyph->face_id, 1);  
               show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);  
               cursor = None;  
             }  
           else if (STRINGP (object) && NILP (mouse_face))  
             {  
               /* A string which doesn't have mouse-face, but  
                  the text ``under'' it might have.  */  
               struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);  
               int start = MATRIX_ROW_START_CHARPOS (r);  
                 
               pos = string_buffer_position (w, object, start);  
               if (pos > 0)  
                 mouse_face = get_char_property_and_overlay (make_number (pos),  
                                                             Qmouse_face,  
                                                             w->buffer,  
                                                             &overlay);  
               if (!NILP (mouse_face) && !NILP (overlay))  
                 {  
                   Lisp_Object before = Foverlay_start (overlay);  
                   Lisp_Object after = Foverlay_end (overlay);  
                   int ignore;  
   
                   /* Note that we might not be able to find position  
                      BEFORE in the glyph matrix if the overlay is  
                      entirely covered by a `display' property.  In  
                      this case, we overshoot.  So let's stop in  
                      the glyph matrix before glyphs for OBJECT.  */  
                   fast_find_position (w, XFASTINT (before),  
                                       &dpyinfo->mouse_face_beg_col,  
                                       &dpyinfo->mouse_face_beg_row,  
                                       &dpyinfo->mouse_face_beg_x,  
                                       &dpyinfo->mouse_face_beg_y,  
                                       object);  
                         
                   dpyinfo->mouse_face_past_end  
                     = !fast_find_position (w, XFASTINT (after),  
                                            &dpyinfo->mouse_face_end_col,  
                                            &dpyinfo->mouse_face_end_row,  
                                            &dpyinfo->mouse_face_end_x,  
                                            &dpyinfo->mouse_face_end_y,  
                                            Qnil);  
                   dpyinfo->mouse_face_window = window;  
                   dpyinfo->mouse_face_face_id  
                     = face_at_buffer_position (w, pos, 0, 0,  
                                                &ignore, pos + 1, 1);  
   
                   /* Display it as active.  */  
                   show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);  
                   cursor = None;  
                 }  
             }  
         }  
   
     check_help_echo:  
   
       /* Look for a `help-echo' property.  */  
       {  
         Lisp_Object help, overlay;  
   
         /* Check overlays first.  */  
         help = overlay = Qnil;  
         for (i = noverlays - 1; i >= 0 && NILP (help); --i)  
           {  
             overlay = overlay_vec[i];  
             help = Foverlay_get (overlay, Qhelp_echo);  
           }  
   
         if (!NILP (help))  
           {  
             help_echo = help;  
             help_echo_window = window;  
             help_echo_object = overlay;  
             help_echo_pos = pos;  
           }  
         else  
           {  
             Lisp_Object object = glyph->object;  
             int charpos = glyph->charpos;  
                 
             /* Try text properties.  */  
             if (STRINGP (object)  
                 && charpos >= 0  
                 && charpos < XSTRING (object)->size)  
               {  
                 help = Fget_text_property (make_number (charpos),  
                                            Qhelp_echo, object);  
                 if (NILP (help))  
                   {  
                     /* If the string itself doesn't specify a help-echo,  
                        see if the buffer text ``under'' it does.  */  
                     struct glyph_row *r  
                       = MATRIX_ROW (w->current_matrix, vpos);  
                     int start = MATRIX_ROW_START_CHARPOS (r);  
                     int pos = string_buffer_position (w, object, start);  
                     if (pos > 0)  
                       {  
                         help = Fget_char_property (make_number (pos),  
                                                    Qhelp_echo, w->buffer);  
                         if (!NILP (help))  
                           {  
                             charpos = pos;  
                             object = w->buffer;  
                           }  
                       }  
                   }  
               }  
             else if (BUFFERP (object)  
                      && charpos >= BEGV  
                      && charpos < ZV)  
               help = Fget_text_property (make_number (charpos), Qhelp_echo,  
                                          object);  
               
             if (!NILP (help))  
               {  
                 help_echo = help;  
                 help_echo_window = window;  
                 help_echo_object = object;  
                 help_echo_pos = charpos;  
               }  
           }  
       }  
             
       BEGV = obegv;  
       ZV = ozv;  
       current_buffer = obuf;  
     }  
   
  set_cursor:  
     
   if (cursor != None)  
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);  
 }  
   
3549  static void  static void
3550  redo_mouse_highlight ()  redo_mouse_highlight ()
3551  {  {
# Line 7304  redo_mouse_highlight () Line 3557  redo_mouse_highlight ()
3557  }  }
3558    
3559    
   
 /***********************************************************************  
                                Tool-bars  
  ***********************************************************************/  
   
 static int x_tool_bar_item P_ ((struct frame *, int, int,  
                                 struct glyph **, int *, int *, int *));  
   
 /* Tool-bar item index of the item on which a mouse button was pressed  
    or -1.  */  
   
 static int last_tool_bar_item;  
   
   
 /* Get information about the tool-bar item at position X/Y on frame F.  
    Return in *GLYPH a pointer to the glyph of the tool-bar item in  
    the current matrix of the tool-bar window of F, or NULL if not  
    on a tool-bar item.  Return in *PROP_IDX the index of the tool-bar  
    item in F->tool_bar_items.  Value is  
   
    -1   if X/Y is not on a tool-bar item  
    0    if X/Y is on the same item that was highlighted before.  
    1    otherwise.  */  
   
 static int  
 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)  
      struct frame *f;  
      int x, y;  
      struct glyph **glyph;  
      int *hpos, *vpos, *prop_idx;  
 {  
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);  
   struct window *w = XWINDOW (f->tool_bar_window);  
   int area;  
   
   /* Find the glyph under X/Y.  */  
   *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);  
   if (*glyph == NULL)  
     return -1;  
   
   /* Get the start of this tool-bar item's properties in  
      f->tool_bar_items.  */  
   if (!tool_bar_item_info (f, *glyph, prop_idx))  
     return -1;  
   
   /* Is mouse on the highlighted item?  */  
   if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)  
       && *vpos >= dpyinfo->mouse_face_beg_row  
       && *vpos <= dpyinfo->mouse_face_end_row  
       && (*vpos > dpyinfo->mouse_face_beg_row  
           || *hpos >= dpyinfo->mouse_face_beg_col)  
       && (*vpos < dpyinfo->mouse_face_end_row  
           || *hpos < dpyinfo->mouse_face_end_col  
           || dpyinfo->mouse_face_past_end))  
     return 0;  
     
   return 1;  
 }  
   
   
 /* Handle mouse button event on the tool-bar of frame F, at  
    frame-relative coordinates X/Y.  EVENT_TYPE is either ButtonPress  
    or ButtonRelase.  */  
   
 static void  
 x_handle_tool_bar_click (f, button_event)  
      struct frame *f;  
      XButtonEvent *button_event;  
 {  
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);  
   struct window *w = XWINDOW (f->tool_bar_window);  
   int hpos, vpos, prop_idx;  
   struct glyph *glyph;  
   Lisp_Object enabled_p;  
   int x = button_event->x;  
   int y = button_event->y;  
     
   /* If not on the highlighted tool-bar item, return.  */  
   frame_to_window_pixel_xy (w, &x, &y);  
   if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)  
     return;  
   
   /* If item is disabled, do nothing.  */  
   enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);  
   if (NILP (enabled_p))  
     return;  
     
   if (button_event->type == ButtonPress)  
     {  
       /* Show item in pressed state.  */  
       show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);  
       dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;  
       last_tool_bar_item = prop_idx;  
     }  
   else  
     {  
       Lisp_Object key, frame;  
       struct input_event event;  
   
       /* Show item in released state.  */  
       show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);  
       dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;  
   
       key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);  
   
       XSETFRAME (frame, f);  
       event.kind = TOOL_BAR_EVENT;  
       event.frame_or_window = frame;  
       event.arg = frame;  
       kbd_buffer_store_event (&event);  
   
       event.kind = TOOL_BAR_EVENT;  
       event.frame_or_window = frame;  
       event.arg = key;  
       event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),  
                                                 button_event->state);  
       kbd_buffer_store_event (&event);  
       last_tool_bar_item = -1;  
     }  
 }  
   
   
 /* Possibly highlight a tool-bar item on frame F when mouse moves to  
    tool-bar window-relative coordinates X/Y.  Called from  
    note_mouse_highlight.  */  
   
 static void  
 note_tool_bar_highlight (f, x, y)  
      struct frame *f;  
      int x, y;  
 {  
   Lisp_Object window = f->tool_bar_window;  
   struct window *w = XWINDOW (window);  
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);  
   int hpos, vpos;  
   struct glyph *glyph;  
   struct glyph_row *row;  
   int i;  
   Lisp_Object enabled_p;  
   int prop_idx;  
   enum draw_glyphs_face draw;  
   int mouse_down_p, rc;  
   
   /* Function note_mouse_highlight is called with negative x(y  
      values when mouse moves outside of the frame.  */  
   if (x <= 0 || y <= 0)  
     {  
       clear_mouse_face (dpyinfo);  
       return;  
     }  
   
   rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);  
   if (rc < 0)  
     {  
       /* Not on tool-bar item.  */  
       clear_mouse_face (dpyinfo);  
       return;  
     }  
   else if (rc == 0)  
     goto set_help_echo;  
   
   clear_mouse_face (dpyinfo);  
     
   /* Mouse is down, but on different tool-bar item?  */  
   mouse_down_p = (dpyinfo->grabbed  
                   && f == last_mouse_frame  
                   && FRAME_LIVE_P (f));  
   if (mouse_down_p  
       && last_tool_bar_item != prop_idx)  
     return;  
   
   dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;  
   draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;  
     
   /* If tool-bar item is not enabled, don't highlight it.  */  
   enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);  
   if (!NILP (enabled_p))  
     {  
       /* Compute the x-position of the glyph.  In front and past the  
          image is a space.  We include this is the highlighted area.  */  
       row = MATRIX_ROW (w->current_matrix, vpos);  
       for (i = x = 0; i < hpos; ++i)  
         x += row->glyphs[TEXT_AREA][i].pixel_width;  
         
       /* Record this as the current active region.  */  
       dpyinfo->mouse_face_beg_col = hpos;  
       dpyinfo->mouse_face_beg_row = vpos;  
       dpyinfo->mouse_face_beg_x = x;  
       dpyinfo->mouse_face_beg_y = row->y;  
       dpyinfo->mouse_face_past_end = 0;  
         
       dpyinfo->mouse_face_end_col = hpos + 1;  
       dpyinfo->mouse_face_end_row = vpos;  
       dpyinfo->mouse_face_end_x = x + glyph->pixel_width;  
       dpyinfo->mouse_face_end_y = row->y;  
       dpyinfo->mouse_face_window = window;  
       dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;  
         
       /* Display it as active.  */  
       show_mouse_face (dpyinfo, draw);  
       dpyinfo->mouse_face_image_state = draw;  
     }  
         
  set_help_echo:  
     
   /* Set help_echo to a help string to display for this tool-bar item.  
      XTread_socket does the rest.  */  
   help_echo_object = help_echo_window = Qnil;  
   help_echo_pos = -1;  
   help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);  
   if (NILP (help_echo))  
     help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);  
 }  
   
   
   
 /* Find the glyph matrix position of buffer position CHARPOS in window  
    *W.  HPOS, *VPOS, *X, and *Y are set to the positions found.  W's  
    current glyphs must be up to date.  If CHARPOS is above window  
    start return (0, 0, 0, 0).  If CHARPOS is after end of W, return end  
    of last line in W.  In the row containing CHARPOS, stop before glyphs  
    having STOP as object.  */  
   
 #if 0 /* This is a version of fast_find_position that's more correct  
          in the presence of hscrolling, for example.  I didn't install  
          it right away because the problem fixed is minor, it failed  
          in 20.x as well, and I think it's too risky to install  
          so near the release of 21.1.  2001-09-25 gerd.  */  
   
 static int  
 fast_find_position (w, charpos, hpos, vpos, x, y, stop)  
      struct window *w;  
      int charpos;  
      int *hpos, *vpos, *x, *y;  
      Lisp_Object stop;  
 {  
   struct glyph_row *row, *first;  
   struct glyph *glyph, *end;  
   int i, past_end = 0;  
   
   first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);  
   row = row_containing_pos (w, charpos, first, NULL, 0);  
   if (row == NULL)  
     {  
       if (charpos < MATRIX_ROW_START_CHARPOS (first))  
         {  
           *x = *y = *hpos = *vpos = 0;  
           return 0;  
         }  
       else  
         {  
           row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));  
           past_end = 1;  
         }  
     }  
   
   *x = row->x;  
   *y = row->y;  
   *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);  
     
   glyph = row->glyphs[TEXT_AREA];  
   end = glyph + row->used[TEXT_AREA];  
     
   /* Skip over glyphs not having an object at the start of the row.  
      These are special glyphs like truncation marks on terminal  
      frames.  */  
   if (row->displays_text_p)  
     while (glyph < end  
            && INTEGERP (glyph->object)  
            && !EQ (stop, glyph->object)  
            && glyph->charpos < 0)  
       {  
         *x += glyph->pixel_width;  
         ++glyph;  
       }  
   
   while (glyph < end  
          && !INTEGERP (glyph->object)  
          && !EQ (stop, glyph->object)  
          && (!BUFFERP (glyph->object)  
              || glyph->charpos < charpos))  
     {  
       *x += glyph->pixel_width;  
       ++glyph;  
     }  
   
   *hpos = glyph - row->glyphs[TEXT_AREA];  
   return past_end;  
 }  
   
 #else /* not 0 */  
   
 static int  
 fast_find_position (w, pos, hpos, vpos, x, y, stop)  
      struct window *w;  
      int pos;  
      int *hpos, *vpos, *x, *y;  
      Lisp_Object stop;  
 {  
   int i;  
   int lastcol;  
   int maybe_next_line_p = 0;  
   int line_start_position;  
   int yb = window_text_bottom_y (w);  
   struct glyph_row *row, *best_row;  
   int row_vpos, best_row_vpos;  
   int current_x;  
   
   row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);  
   row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);  
   
   while (row->y < yb)  
     {  
       if (row->used[TEXT_AREA])  
         line_start_position = row->glyphs[TEXT_AREA]->charpos;  
       else  
         line_start_position = 0;  
   
       if (line_start_position > pos)  
         break;  
       /* If the position sought is the end of the buffer,  
          don't include the blank lines at the bottom of the window.  */  
       else if (line_start_position == pos  
                && pos == BUF_ZV (XBUFFER (w->buffer)))  
         {  
           maybe_next_line_p = 1;  
           break;  
         }  
       else if (line_start_position > 0)  
         {  
           best_row = row;  
           best_row_vpos = row_vpos;  
         }  
   
       if (row->y + row->height >= yb)  
         break;  
         
       ++row;  
       ++row_vpos;  
     }  
     
   /* Find the right column within BEST_ROW.  */  
   lastcol = 0;  
   current_x = best_row->x;  
   for (i = 0; i < best_row->used[TEXT_AREA]; i++)  
     {  
       struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;  
       int charpos = glyph->charpos;  
   
       if (BUFFERP (glyph->object))  
         {  
           if (charpos == pos)  
             {  
               *hpos = i;  
               *vpos = best_row_vpos;  
               *x = current_x;  
               *y = best_row->y;  
               return 1;  
             }  
           else if (charpos > pos)  
             break;  
         }  
       else if (EQ (glyph->object, stop))  
         break;  
   
       if (charpos > 0)  
         lastcol = i;  
       current_x += glyph->pixel_width;  
     }  
   
   /* If we're looking for the end of the buffer,  
      and we didn't find it in the line we scanned,  
      use the start of the following line.  */  
   if (maybe_next_line_p)  
     {  
       ++best_row;  
       ++best_row_vpos;  
       lastcol = 0;  
       current_x = best_row->x;  
     }  
   
   *vpos = best_row_vpos;  
   *hpos = lastcol + 1;  
   *x = current_x;  
   *y = best_row->y;  
   return 0;  
 }  
   
 #endif /* not 0 */  
   
   
 /* Find the position of the glyph for position POS in OBJECT in  
    window W's current matrix, and return in *X, *Y the pixel  
    coordinates, and return in *HPOS, *VPOS the column/row of the glyph.  
   
    RIGHT_P non-zero means return the position of the right edge of the  
    glyph, RIGHT_P zero means return the left edge position.  
   
    If no glyph for POS exists in the matrix, return the position of  
    the glyph with the next smaller position that is in the matrix, if  
    RIGHT_P is zero.  If RIGHT_P is non-zero, and no glyph for POS  
    exists in the matrix, return the position of the glyph with the  
    next larger position in OBJECT.  
   
    Value is non-zero if a glyph was found.  */  
   
 static int  
 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)  
      struct window *w;  
      int pos;  
      Lisp_Object object;  
      int *hpos, *vpos, *x, *y;  
      int right_p;  
 {  
   int yb = window_text_bottom_y (w);  
   struct glyph_row *r;  
   struct glyph *best_glyph = NULL;  
   struct glyph_row *best_row = NULL;  
   int best_x = 0;  
   
   for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);  
        r->enabled_p && r->y < yb;  
        ++r)  
     {  
       struct glyph *g = r->glyphs[TEXT_AREA];  
       struct glyph *e = g + r->used[TEXT_AREA];  
       int gx;  
   
       for (gx = r->x; g < e; gx += g->pixel_width, ++g)  
         if (EQ (g->object, object))  
           {  
             if (g->charpos == pos)  
               {  
                 best_glyph = g;  
                 best_x = gx;  
                 best_row = r;  
                 goto found;  
               }  
             else if (best_glyph == NULL  
                      || ((abs (g->charpos - pos)  
                          < abs (best_glyph->charpos - pos))  
                          && (right_p  
                              ? g->charpos < pos  
                              : g->charpos > pos)))  
               {  
                 best_glyph = g;  
                 best_x = gx;  
                 best_row = r;  
               }  
           }  
     }  
   
  found:  
   
   if (best_glyph)  
     {  
       *x = best_x;  
       *hpos = best_glyph - best_row->glyphs[TEXT_AREA];  
   
       if (right_p)  
         {  
           *x += best_glyph->pixel_width;  
           ++*hpos;  
         }  
         
       *y = best_row->y;  
       *vpos = best_row - w->current_matrix->rows;  
     }  
   
   return best_glyph != NULL;  
 }  
   
   
 /* Display the active region described by mouse_face_*  
    in its mouse-face if HL > 0, in its normal face if HL = 0.  */  
   
 static void  
 show_mouse_face (dpyinfo, draw)  
      struct x_display_info *dpyinfo;  
      enum draw_glyphs_face draw;  
 {  
   struct window *w = XWINDOW (dpyinfo->mouse_face_window);  
   struct frame *f = XFRAME (WINDOW_FRAME (w));  
   
   if (/* If window is in the process of being destroyed, don't bother  
          to do anything.  */  
       w->current_matrix != NULL  
       /* Don't update mouse highlight if hidden */  
       && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)  
       /* Recognize when we are called to operate on rows that don't exist  
          anymore.  This can happen when a window is split.  */  
       && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)  
     {  
       int phys_cursor_on_p = w->phys_cursor_on_p;  
       struct glyph_row *row, *first, *last;  
   
       first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);  
       last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);  
         
       for (row = first; row <= last && row->enabled_p; ++row)  
         {  
           int start_hpos, end_hpos, start_x;  
   
           /* For all but the first row, the highlight starts at column 0.  */  
           if (row == first)  
             {  
               start_hpos = dpyinfo->mouse_face_beg_col;  
               start_x = dpyinfo->mouse_face_beg_x;  
             }  
           else  
             {  
               start_hpos = 0;  
               start_x = 0;  
             }  
   
           if (row == last)  
             end_hpos = dpyinfo->mouse_face_end_col;  
           else  
             end_hpos = row->used[TEXT_AREA];  
   
           if (end_hpos > start_hpos)  
             {  
               x_draw_glyphs (w, start_x, row, TEXT_AREA,  
                              start_hpos, end_hpos, draw, 0);  
   
               row->mouse_face_p  
                 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;  
             }  
         }  
   
       /* When we've written over the cursor, arrange for it to  
          be displayed again.  */  
       if (phys_cursor_on_p && !w->phys_cursor_on_p)  
         x_display_cursor (w, 1,  
                           w->phys_cursor.hpos, w->phys_cursor.vpos,  
                           w->phys_cursor.x, w->phys_cursor.y);  
     }  
   
   /* Change the mouse cursor.  */  
   if (draw == DRAW_NORMAL_TEXT)  
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),  
                    f->output_data.x->text_cursor);  
   else if (draw == DRAW_MOUSE_FACE)  
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),  
                    f->output_data.x->cross_cursor);  
   else  
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),  
                    f->output_data.x->nontext_cursor);  
 }  
   
 /* Clear out the mouse-highlighted active region.  
    Redraw it un-highlighted first.  Value is non-zero if mouse  
    face was actually drawn unhighlighted.  */  
   
 static int  
 clear_mouse_face (dpyinfo)  
      struct x_display_info *dpyinfo;  
 {  
   int cleared = 0;  
     
   if (!NILP (dpyinfo->mouse_face_window))  
     {  
       show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);  
       cleared = 1;  
     }  
   
   dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;  
   dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;  
   dpyinfo->mouse_face_window = Qnil;  
   dpyinfo->mouse_face_overlay = Qnil;  
   return cleared;  
 }  
   
   
 /* Clear any mouse-face on window W.  This function is part of the  
    redisplay interface, and is called from try_window_id and similar  
    functions to ensure the mouse-highlight is off.  */  
   
 static void  
 x_clear_mouse_face (w)  
      struct window *w;  
 {  
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));  
   Lisp_Object window;  
   
   BLOCK_INPUT;  
   XSETWINDOW (window, w);  
   if (EQ (window, dpyinfo->mouse_face_window))  
     clear_mouse_face (dpyinfo);  
   UNBLOCK_INPUT;  
 }  
   
   
 /* Just discard the mouse face information for frame F, if any.  
    This is used when the size of F is changed.  */  
   
 void  
 cancel_mouse_face (f)  
      FRAME_PTR f;  
 {  
   Lisp_Object window;  
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);  
   
   window = dpyinfo->mouse_face_window;  
   if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)  
     {  
       dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;  
       dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;  
       dpyinfo->mouse_face_window = Qnil;  
     }  
 }  
   
   
3560  static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));  static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
3561    
3562    
# Line 7932  glyph_rect (f, x, y, rect) Line 3572  glyph_rect (f, x, y, rect)
3572       XRectangle *rect;       XRectangle *rect;
3573  {  {
3574    Lisp_Object window;    Lisp_Object window;
3575    int part, found = 0;    int found = 0;
3576    
3577    window = window_from_coordinates (f, x, y, &part, 0);    window = window_from_coordinates (f, x, y, 0, 0);
3578    if (!NILP (window))    if (!NILP (window))
3579      {      {
3580        struct window *w = XWINDOW (window);        struct window *w = XWINDOW (window);
# Line 7942  glyph_rect (f, x, y, rect) Line 3582  glyph_rect (f, x, y, rect)
3582        struct glyph_row *end = r + w->current_matrix->nrows - 1;        struct glyph_row *end = r + w->current_matrix->nrows - 1;
3583    
3584        frame_to_window_pixel_xy (w, &x, &y);        frame_to_window_pixel_xy (w, &x, &y);
3585          
3586        for (; !found && r < end && r->enabled_p; ++r)        for (; !found && r < end && r->enabled_p; ++r)
3587          if (r->y >= y)          if (r->y >= y)
3588            {            {
3589              struct glyph *g = r->glyphs[TEXT_AREA];              struct glyph *g = r->glyphs[TEXT_AREA];
3590              struct glyph *end = g + r->used[TEXT_AREA];              struct glyph *end = g + r->used[TEXT_AREA];
3591              int gx;              int gx;
3592                  
3593              for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)              for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
3594                if (gx >= x)                if (gx >= x)
3595                  {                  {
# Line 8152  XTmouse_position (fp, insist, bar_window Line 3792  XTmouse_position (fp, insist, bar_window
3792    
3793              int width, height, gx, gy;              int width, height, gx, gy;
3794              XRectangle rect;              XRectangle rect;
3795                
3796              if (glyph_rect (f1, win_x, win_y, &rect))              if (glyph_rect (f1, win_x, win_y, &rect))
3797                last_mouse_glyph = rect;                last_mouse_glyph = rect;
3798              else              else
# Line 8161  XTmouse_position (fp, insist, bar_window Line 3801  XTmouse_position (fp, insist, bar_window
3801                  height = FRAME_SMALLEST_FONT_HEIGHT (f1);                  height = FRAME_SMALLEST_FONT_HEIGHT (f1);
3802                  gx = win_x;                  gx = win_x;
3803                  gy = win_y;                  gy = win_y;
3804                  
3805                  /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to                  /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
3806                     round down even for negative values.  */                     round down even for negative values.  */
3807                  if (gx < 0)                  if (gx < 0)
# Line 8170  XTmouse_position (fp, insist, bar_window Line 3810  XTmouse_position (fp, insist, bar_window
3810                    gy -= height - 1;                    gy -= height - 1;
3811                  gx = (gx + width - 1) / width * width;                  gx = (gx + width - 1) / width * width;
3812                  gy = (gy + height - 1) / height * height;                  gy = (gy + height - 1) / height * height;
3813                
3814                  last_mouse_glyph.width  = width;                  last_mouse_glyph.width  = width;
3815                  last_mouse_glyph.height = height;                  last_mouse_glyph.height = height;
3816                  last_mouse_glyph.x = gx;                  last_mouse_glyph.x = gx;
# Line 8191  XTmouse_position (fp, insist, bar_window Line 3831  XTmouse_position (fp, insist, bar_window
3831  }  }
3832    
3833    
 #ifdef USE_X_TOOLKIT  
   
 /* Atimer callback function for TIMER.  Called every 0.1s to process  
    Xt timeouts, if needed.  We must avoid calling XtAppPending as  
    much as possible because that function does an implicit XFlush  
    that slows us down.  */  
   
 static void  
 x_process_timeouts (timer)  
      struct atimer *timer;  
 {  
   if (toolkit_scroll_bar_interaction || popup_activated_flag)  
     {  
       BLOCK_INPUT;  
       while (XtAppPending (Xt_app_con) & XtIMTimer)  
         XtAppProcessEvent (Xt_app_con, XtIMTimer);  
       UNBLOCK_INPUT;  
     }  
 }  
   
 #endif /* USE_X_TOOLKIT */  
   
3834    
3835    /***********************************************************************
3836                                   Scroll bars
3837     ***********************************************************************/
3838    
3839  /* Scroll bar support.  */  /* Scroll bar support.  */
3840    
3841  /* Given an X window ID, find the struct scroll_bar which manages it.  /* Given an X window ID, find the struct scroll_bar which manages it.
# Line 8226  x_window_to_scroll_bar (window_id) Line 3848  x_window_to_scroll_bar (window_id)
3848  {  {
3849    Lisp_Object tail;    Lisp_Object tail;
3850    
3851    #ifdef USE_GTK
3852      window_id = (Window) xg_get_scroll_id_for_window (window_id);
3853    #endif /* USE_GTK */
3854    
3855    for (tail = Vframe_list;    for (tail = Vframe_list;
3856         XGCTYPE (tail) == Lisp_Cons;         XGCTYPE (tail) == Lisp_Cons;
3857         tail = XCDR (tail))         tail = XCDR (tail))
# Line 8265  x_window_to_menu_bar (window) Line 3891  x_window_to_menu_bar (window)
3891       Window window;       Window window;
3892  {  {
3893    Lisp_Object tail;    Lisp_Object tail;
3894      
3895    for (tail = Vframe_list;    for (tail = Vframe_list;
3896         XGCTYPE (tail) == Lisp_Cons;         XGCTYPE (tail) == Lisp_Cons;
3897         tail = XCDR (tail))         tail = XCDR (tail))
3898      {      {
3899        Lisp_Object frame = XCAR (tail);        Lisp_Object frame = XCAR (tail);
3900        Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;        Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
3901          
3902        if (menu_bar && xlwmenu_window_p (menu_bar, window))        if (menu_bar && xlwmenu_window_p (menu_bar, window))
3903          return menu_bar;          return menu_bar;
3904      }      }
# Line 8297  static void x_set_toolkit_scroll_bar_thu Line 3923  static void x_set_toolkit_scroll_bar_thu
3923                                                  int, int, int));                                                  int, int, int));
3924    
3925    
 /* Id of action hook installed for scroll bars.  */  
   
 static XtActionHookId action_hook_id;  
   
3926  /* Lisp window being scrolled.  Set when starting to interact with  /* Lisp window being scrolled.  Set when starting to interact with
3927     a toolkit scroll bar, reset to nil when ending the interaction.  */     a toolkit scroll bar, reset to nil when ending the interaction.  */
3928    
# Line 8313  static int last_scroll_bar_part; Line 3935  static int last_scroll_bar_part;
3935  /* Whether this is an Xaw with arrow-scrollbars.  This should imply  /* Whether this is an Xaw with arrow-scrollbars.  This should imply
3936     that movements of 1/20 of the screen size are mapped to up/down.  */     that movements of 1/20 of the screen size are mapped to up/down.  */
3937    
3938    #ifndef USE_GTK
3939    /* Id of action hook installed for scroll bars.  */
3940    
3941    static XtActionHookId action_hook_id;
3942    
3943  static Boolean xaw3d_arrow_scroll;  static Boolean xaw3d_arrow_scroll;
3944    
3945  /* Whether the drag scrolling maintains the mouse at the top of the  /* Whether the drag scrolling maintains the mouse at the top of the
# Line 8321  static Boolean xaw3d_arrow_scroll; Line 3948  static Boolean xaw3d_arrow_scroll;
3948    
3949  static Boolean xaw3d_pick_top;  static Boolean xaw3d_pick_top;
3950    
3951    extern void set_vertical_scroll_bar P_ ((struct window *));
3952    
3953  /* Action hook installed via XtAppAddActionHook when toolkit scroll  /* Action hook installed via XtAppAddActionHook when toolkit scroll
3954     bars are used..  The hook is responsible for detecting when     bars are used..  The hook is responsible for detecting when
3955     the user ends an interaction with the scroll bar, and generates     the user ends an interaction with the scroll bar, and generates
3956     a `end-scroll' scroll_bar_click' event if so.  */     a `end-scroll' SCROLL_BAR_CLICK_EVENT' event if so.  */
3957    
3958  static void  static void
3959  xt_action_hook (widget, client_data, action_name, event, params,  xt_action_hook (widget, client_data, action_name, event, params,
# Line 8339  xt_action_hook (widget, client_data, act Line 3967  xt_action_hook (widget, client_data, act
3967  {  {
3968    int scroll_bar_p;    int scroll_bar_p;
3969    char *end_action;    char *end_action;
3970      
3971  #ifdef USE_MOTIF  #ifdef USE_MOTIF
3972    scroll_bar_p = XmIsScrollBar (widget);    scroll_bar_p = XmIsScrollBar (widget);
3973    end_action = "Release";    end_action = "Release";
# Line 8353  xt_action_hook (widget, client_data, act Line 3981  xt_action_hook (widget, client_data, act
3981        && WINDOWP (window_being_scrolled))        && WINDOWP (window_being_scrolled))
3982      {      {
3983        struct window *w;        struct window *w;
3984          
3985        x_send_scroll_bar_event (window_being_scrolled,        x_send_scroll_bar_event (window_being_scrolled,
3986                                 scroll_bar_end_scroll, 0, 0);                                 scroll_bar_end_scroll, 0, 0);
3987        w = XWINDOW (window_being_scrolled);        w = XWINDOW (window_being_scrolled);
3988        XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;        
3989          if (!NILP (XSCROLL_BAR (w->vertical_scroll_bar)->dragging))
3990            {
3991              XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
3992              /* The thumb size is incorrect while dragging: fix it.  */
3993              set_vertical_scroll_bar (w);
3994            }
3995        window_being_scrolled = Qnil;        window_being_scrolled = Qnil;
3996        last_scroll_bar_part = -1;        last_scroll_bar_part = -1;
3997    
# Line 8365  xt_action_hook (widget, client_data, act Line 3999  xt_action_hook (widget, client_data, act
3999        toolkit_scroll_bar_interaction = 0;        toolkit_scroll_bar_interaction = 0;
4000      }      }
4001  }  }
4002    #endif /* not USE_GTK */
4003    
4004  /* A vector of windows used for communication between  /* A vector of windows used for communication between
4005     x_send_scroll_bar_event and x_scroll_bar_to_input_event.  */     x_send_scroll_bar_event and x_scroll_bar_to_input_event.  */
# Line 8390  x_send_scroll_bar_event (window, part, p Line 4025  x_send_scroll_bar_event (window, part, p
4025    int i;    int i;
4026    
4027    BLOCK_INPUT;    BLOCK_INPUT;
4028      
4029    /* Construct a ClientMessage event to send to the frame.  */    /* Construct a ClientMessage event to send to the frame.  */
4030    ev->type = ClientMessage;    ev->type = ClientMessage;
4031    ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;    ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
# Line 8411  x_send_scroll_bar_event (window, part, p Line 4046  x_send_scroll_bar_event (window, part, p
4046        int new_size = max (10, 2 * scroll_bar_windows_size);        int new_size = max (10, 2 * scroll_bar_windows_size);
4047        size_t nbytes = new_size * sizeof *scroll_bar_windows;        size_t nbytes = new_size * sizeof *scroll_bar_windows;
4048        size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;        size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
4049          
4050        scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,        scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
4051                                                          nbytes);                                                          nbytes);
4052        bzero (&scroll_bar_windows[i], nbytes - old_nbytes);        bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
# Line 8448  x_scroll_bar_to_input_event (event, ieve Line 4083  x_scroll_bar_to_input_event (event, ieve
4083    Lisp_Object window;    Lisp_Object window;
4084    struct frame *f;    struct frame *f;
4085    struct window *w;    struct window *w;
4086      
4087    w = scroll_bar_windows[ev->data.l[0]];    w = scroll_bar_windows[ev->data.l[0]];
4088    scroll_bar_windows[ev->data.l[0]] = NULL;    scroll_bar_windows[ev->data.l[0]] = NULL;
4089    
4090    XSETWINDOW (window, w);    XSETWINDOW (window, w);
4091    f = XFRAME (w->frame);    f = XFRAME (w->frame);
4092      
4093    ievent->kind = scroll_bar_click;    ievent->kind = SCROLL_BAR_CLICK_EVENT;
4094    ievent->frame_or_window = window;    ievent->frame_or_window = window;
4095    ievent->arg = Qnil;    ievent->arg = Qnil;
4096    #ifdef USE_GTK
4097      ievent->timestamp = CurrentTime;
4098    #else
4099    ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));    ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
4100    #endif
4101    ievent->part = ev->data.l[1];    ievent->part = ev->data.l[1];
4102    ievent->code = ev->data.l[2];    ievent->code = ev->data.l[2];
4103    ievent->x = make_number ((int) ev->data.l[3]);    ievent->x = make_number ((int) ev->data.l[3]);
# Line 8471  x_scroll_bar_to_input_event (event, ieve Line 4110  x_scroll_bar_to_input_event (event, ieve
4110    
4111  /* Minimum and maximum values used for Motif scroll bars.  */  /* Minimum and maximum values used for Motif scroll bars.  */
4112    
 #define XM_SB_MIN 1  
4113  #define XM_SB_MAX 10000000  #define XM_SB_MAX 10000000
 #define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)  
4114    
4115    
4116  /* Scroll bar callback for Motif scroll bars.  WIDGET is the scroll  /* Scroll bar callback for Motif scroll bars.  WIDGET is the scroll
4117     bar widget.  CLIENT_DATA is a pointer to the scroll_bar structure.     bar widget.  CLIENT_DATA is a pointer to the scroll_bar structure.
4118     CALL_DATA is a pointer a a XmScrollBarCallbackStruct.  */     CALL_DATA is a pointer to a XmScrollBarCallbackStruct.  */
4119    
4120  static void  static void
4121  xm_scroll_callback (widget, client_data, call_data)  xm_scroll_callback (widget, client_data, call_data)
# Line 8515  xm_scroll_callback (widget, client_data, Line 4152  xm_scroll_callback (widget, client_data,
4152        bar->dragging = Qnil;        bar->dragging = Qnil;
4153        part = scroll_bar_to_top;        part = scroll_bar_to_top;
4154        break;        break;
4155          
4156      case XmCR_TO_BOTTOM:      case XmCR_TO_BOTTOM:
4157        bar->dragging = Qnil;        bar->dragging = Qnil;
4158        part = scroll_bar_to_bottom;        part = scroll_bar_to_bottom;
# Line 8524  xm_scroll_callback (widget, client_data, Line 4161  xm_scroll_callback (widget, client_data,
4161      case XmCR_DRAG:      case XmCR_DRAG:
4162        {        {
4163          int slider_size;          int slider_size;
         int dragging_down_p = (INTEGERP (bar->dragging)  
                                && XINT (bar->dragging) <= cs->value);  
4164    
4165          /* Get the slider size.  */          /* Get the slider size.  */
4166          BLOCK_INPUT;          BLOCK_INPUT;
4167          XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);          XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
4168          UNBLOCK_INPUT;          UNBLOCK_INPUT;
4169    
4170          whole = XM_SB_RANGE - slider_size;          whole = XM_SB_MAX - slider_size;
4171          portion = min (cs->value - XM_SB_MIN, whole);          portion = min (cs->value, whole);
4172          part = scroll_bar_handle;          part = scroll_bar_handle;
4173          bar->dragging = make_number (cs->value);          bar->dragging = make_number (cs->value);
4174        }        }
4175        break;        break;
4176          
4177      case XmCR_VALUE_CHANGED:      case XmCR_VALUE_CHANGED:
4178        break;        break;
4179      };      };
# Line 8552  xm_scroll_callback (widget, client_data, Line 4187  xm_scroll_callback (widget, client_data,
4187  }  }
4188    
4189    
4190  #else /* !USE_MOTIF, i.e. Xaw.  */  #else /* !USE_MOTIF, i.e. Xaw or GTK */
4191    #ifdef USE_GTK
4192    /* Scroll bar callback for GTK scroll bars.  WIDGET is the scroll
4193       bar adjustment widget.  DATA is a pointer to the scroll_bar structure. */
4194    
4195    static void
4196    xg_scroll_callback (widget, data)
4197         GtkWidget *widget;
4198         gpointer data;
4199    {
4200      struct scroll_bar *bar = (struct scroll_bar *) data;
4201      gdouble previous;
4202      gdouble position;
4203      gdouble *p;
4204      int diff;
4205    
4206      int part = -1, whole = 0, portion = 0;
4207      GtkAdjustment *adj = GTK_ADJUSTMENT (widget);
4208    
4209      if (xg_ignore_gtk_scrollbar) return;
4210    
4211      position = gtk_adjustment_get_value (adj);
4212    
4213      p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
4214      if (! p)
4215        {
4216          p = (gdouble*) xmalloc (sizeof (gdouble));
4217          *p = XG_SB_MIN;
4218          g_object_set_data (G_OBJECT (widget), XG_LAST_SB_DATA, p);
4219        }
4220    
4221      previous = *p;
4222      *p = position;
4223    
4224      diff = (int) (position - previous);
4225    
4226      if (diff == (int) adj->step_increment)
4227        {
4228          part = scroll_bar_down_arrow;
4229          bar->dragging = Qnil;
4230        }
4231      else if (-diff == (int) adj->step_increment)
4232        {
4233          part = scroll_bar_up_arrow;
4234          bar->dragging = Qnil;
4235        }
4236      else if (diff == (int) adj->page_increment)
4237        {
4238          part = scroll_bar_below_handle;
4239          bar->dragging = Qnil;
4240        }
4241      else if (-diff == (int) adj->page_increment)
4242        {
4243          part = scroll_bar_above_handle;
4244          bar->dragging = Qnil;
4245        }
4246      else
4247        {
4248          part = scroll_bar_handle;
4249          whole = adj->upper - adj->page_size;
4250          portion = min ((int)position, whole);
4251          bar->dragging = make_number ((int)portion);
4252        }
4253    
4254      if (part >= 0)
4255        {
4256          window_being_scrolled = bar->window;
4257          last_scroll_bar_part = part;
4258          x_send_scroll_bar_event (bar->window, part, portion, whole);
4259        }
4260    }
4261    
4262    #else /* not USE_GTK */
4263    
4264  /* Xaw scroll bar callback.  Invoked when the thumb is dragged.  /* Xaw scroll bar callback.  Invoked when the thumb is dragged.
4265     WIDGET is the scroll bar widget.  CLIENT_DATA is a pointer to the     WIDGET is the scroll bar widget.  CLIENT_DATA is a pointer to the
# Line 8600  xaw_jump_callback (widget, client_data, Line 4306  xaw_jump_callback (widget, client_data,
4306     i.e. line or page up or down.  WIDGET is the Xaw scroll bar     i.e. line or page up or down.  WIDGET is the Xaw scroll bar
4307     widget.  CLIENT_DATA is a pointer to the scroll_bar structure for     widget.  CLIENT_DATA is a pointer to the scroll_bar structure for
4308     the scroll bar.  CALL_DATA is an integer specifying the action that     the scroll bar.  CALL_DATA is an integer specifying the action that
4309     has taken place.  It's magnitude is in the range 0..height of the     has taken place.  Its magnitude is in the range 0..height of the
4310     scroll bar.  Negative values mean scroll towards buffer start.     scroll bar.  Negative values mean scroll towards buffer start.
4311     Values < height of scroll bar mean line-wise movement.  */     Values < height of scroll bar mean line-wise movement.  */
4312    
# Line 8610  xaw_scroll_callback (widget, client_data Line 4316  xaw_scroll_callback (widget, client_data
4316       XtPointer client_data, call_data;       XtPointer client_data, call_data;
4317  {  {
4318    struct scroll_bar *bar = (struct scroll_bar *) client_data;    struct scroll_bar *bar = (struct scroll_bar *) client_data;
4319    int position = (int) call_data;    /* The position really is stored cast to a pointer.  */
4320      int position = (long) call_data;
4321    Dimension height;    Dimension height;
4322    int part;    int part;
4323    
# Line 8635  xaw_scroll_callback (widget, client_data Line 4342  xaw_scroll_callback (widget, client_data
4342    x_send_scroll_bar_event (bar->window, part, position, height);    x_send_scroll_bar_event (bar->window, part, position, height);
4343  }  }
4344    
4345    #endif /* not USE_GTK */
4346  #endif /* not USE_MOTIF */  #endif /* not USE_MOTIF */
4347    
4348    #define SCROLL_BAR_NAME "verticalScrollBar"
4349    
4350  /* Create the widget for scroll bar BAR on frame F.  Record the widget  /* Create the widget for scroll bar BAR on frame F.  Record the widget
4351     and X window of the scroll bar in BAR.  */     and X window of the scroll bar in BAR.  */
4352    
4353    #ifdef USE_GTK
4354    static void
4355    x_create_toolkit_scroll_bar (f, bar)
4356         struct frame *f;
4357         struct scroll_bar *bar;
4358    {
4359      char *scroll_bar_name = SCROLL_BAR_NAME;
4360    
4361      BLOCK_INPUT;
4362      xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
4363                            scroll_bar_name);
4364      UNBLOCK_INPUT;
4365    }
4366    
4367    #else /* not USE_GTK */
4368    
4369  static void  static void
4370  x_create_toolkit_scroll_bar (f, bar)  x_create_toolkit_scroll_bar (f, bar)
4371       struct frame *f;       struct frame *f;
# Line 8651  x_create_toolkit_scroll_bar (f, bar) Line 4375  x_create_toolkit_scroll_bar (f, bar)
4375    Widget widget;    Widget widget;
4376    Arg av[20];    Arg av[20];
4377    int ac = 0;    int ac = 0;
4378    char *scroll_bar_name = "verticalScrollBar";    char *scroll_bar_name = SCROLL_BAR_NAME;
4379    unsigned long pixel;    unsigned long pixel;
4380    
4381    BLOCK_INPUT;    BLOCK_INPUT;
# Line 8659  x_create_toolkit_scroll_bar (f, bar) Line 4383  x_create_toolkit_scroll_bar (f, bar)
4383  #ifdef USE_MOTIF  #ifdef USE_MOTIF
4384    /* Set resources.  Create the widget.  */    /* Set resources.  Create the widget.  */
4385    XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;    XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
4386    XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;    XtSetArg (av[ac], XmNminimum, 0); ++ac;
4387    XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;    XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
4388    XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;    XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
4389    XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;    XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
# Line 8672  x_create_toolkit_scroll_bar (f, bar) Line 4396  x_create_toolkit_scroll_bar (f, bar)
4396        XtSetArg (av[ac], XmNforeground, pixel);        XtSetArg (av[ac], XmNforeground, pixel);
4397        ++ac;        ++ac;
4398      }      }
4399      
4400    pixel = f->output_data.x->scroll_bar_background_pixel;    pixel = f->output_data.x->scroll_bar_background_pixel;
4401    if (pixel != -1)    if (pixel != -1)
4402      {      {
4403        XtSetArg (av[ac], XmNbackground, pixel);        XtSetArg (av[ac], XmNbackground, pixel);
4404        ++ac;        ++ac;
4405      }      }
4406      
4407    widget = XmCreateScrollBar (f->output_data.x->edit_widget,    widget = XmCreateScrollBar (f->output_data.x->edit_widget,
4408                                scroll_bar_name, av, ac);                                scroll_bar_name, av, ac);
4409    
# Line 8698  x_create_toolkit_scroll_bar (f, bar) Line 4422  x_create_toolkit_scroll_bar (f, bar)
4422                   (XtPointer) bar);                   (XtPointer) bar);
4423    XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,    XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
4424                   (XtPointer) bar);                   (XtPointer) bar);
4425      
4426    /* Realize the widget.  Only after that is the X window created.  */    /* Realize the widget.  Only after that is the X window created.  */
4427    XtRealizeWidget (widget);    XtRealizeWidget (widget);
4428    
# Line 8706  x_create_toolkit_scroll_bar (f, bar) Line 4430  x_create_toolkit_scroll_bar (f, bar)
4430       And I'm wondering why it hasn't an arrow cursor by default.  */       And I'm wondering why it hasn't an arrow cursor by default.  */
4431    XDefineCursor (XtDisplay (widget), XtWindow (widget),    XDefineCursor (XtDisplay (widget), XtWindow (widget),
4432                   f->output_data.x->nontext_cursor);                   f->output_data.x->nontext_cursor);
4433      
4434  #else /* !USE_MOTIF i.e. use Xaw */  #else /* !USE_MOTIF i.e. use Xaw */
4435      
4436    /* Set resources.  Create the widget.  The background of the    /* Set resources.  Create the widget.  The background of the
4437       Xaw3d scroll bar widget is a little bit light for my taste.       Xaw3d scroll bar widget is a little bit light for my taste.
4438       We don't alter it here to let users change it according       We don't alter it here to let users change it according
# Line 8717  x_create_toolkit_scroll_bar (f, bar) Line 4441  x_create_toolkit_scroll_bar (f, bar)
4441    XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;    XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
4442    /* For smoother scrolling with Xaw3d   -sm */    /* For smoother scrolling with Xaw3d   -sm */
4443    /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */    /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
4444      
4445    pixel = f->output_data.x->scroll_bar_foreground_pixel;    pixel = f->output_data.x->scroll_bar_foreground_pixel;
4446    if (pixel != -1)    if (pixel != -1)
4447      {      {
4448        XtSetArg (av[ac], XtNforeground, pixel);        XtSetArg (av[ac], XtNforeground, pixel);
4449        ++ac;        ++ac;
4450      }      }
4451      
4452    pixel = f->output_data.x->scroll_bar_background_pixel;    pixel = f->output_data.x->scroll_bar_background_pixel;
4453    if (pixel != -1)    if (pixel != -1)
4454      {      {
# Line 8801  x_create_toolkit_scroll_bar (f, bar) Line 4525  x_create_toolkit_scroll_bar (f, bar)
4525          XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);          XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
4526        }        }
4527    }    }
4528      
4529    /* Define callbacks.  */    /* Define callbacks.  */
4530    XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);    XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
4531    XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,    XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
4532                   (XtPointer) bar);                   (XtPointer) bar);
4533      
4534    /* Realize the widget.  Only after that is the X window created.  */    /* Realize the widget.  Only after that is the X window created.  */
4535    XtRealizeWidget (widget);    XtRealizeWidget (widget);
4536      
4537  #endif /* !USE_MOTIF */  #endif /* !USE_MOTIF */
4538    
4539    /* Install an action hook that let's us detect when the user    /* Install an action hook that lets us detect when the user
4540       finishes interacting with a scroll bar.  */       finishes interacting with a scroll bar.  */
4541    if (action_hook_id == 0)    if (action_hook_id == 0)
4542      action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);      action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
4543      
4544    /* Remember X window and widget in the scroll bar vector.  */    /* Remember X window and widget in the scroll bar vector.  */
4545    SET_SCROLL_BAR_X_WIDGET (bar, widget);    SET_SCROLL_BAR_X_WIDGET (bar, widget);
4546    xwindow = XtWindow (widget);    xwindow = XtWindow (widget);
# Line 8824  x_create_toolkit_scroll_bar (f, bar) Line 4548  x_create_toolkit_scroll_bar (f, bar)
4548    
4549    UNBLOCK_INPUT;    UNBLOCK_INPUT;
4550  }  }
4551    #endif /* not USE_GTK */
4552    
4553    
4554  /* Set the thumb size and position of scroll bar BAR.  We are currently  /* Set the thumb size and position of scroll bar BAR.  We are currently
4555     displaying PORTION out of a whole WHOLE, and our position POSITION.  */     displaying PORTION out of a whole WHOLE, and our position POSITION.  */
4556    
4557    #ifdef USE_GTK
4558    static void
4559    x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
4560         struct scroll_bar *bar;
4561         int portion, position, whole;
4562    {
4563      xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
4564    }
4565    
4566    #else /* not USE_GTK */
4567  static void  static void
4568  x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)  x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
4569       struct scroll_bar *bar;       struct scroll_bar *bar;
# Line 8873  x_set_toolkit_scroll_bar_thumb (bar, por Line 4608  x_set_toolkit_scroll_bar_thumb (bar, por
4608        /* Slider size.  Must be in the range [1 .. MAX - MIN] where MAX        /* Slider size.  Must be in the range [1 .. MAX - MIN] where MAX
4609           is the scroll bar's maximum and MIN is the scroll bar's minimum           is the scroll bar's maximum and MIN is the scroll bar's minimum
4610           value.  */           value.  */
4611        size = shown * XM_SB_RANGE;        size = shown * XM_SB_MAX;
4612        size = min (size, XM_SB_RANGE);        size = min (size, XM_SB_MAX);
4613        size = max (size, 1);        size = max (size, 1);
4614    
4615        /* Position.  Must be in the range [MIN .. MAX - SLIDER_SIZE].  */        /* Position.  Must be in the range [MIN .. MAX - SLIDER_SIZE].  */
4616        value = top * XM_SB_RANGE;        value = top * XM_SB_MAX;
4617        value = min (value, XM_SB_MAX - size);        value = min (value, XM_SB_MAX - size);
4618        value = max (value, XM_SB_MIN);  
         
4619        XmScrollBarSetValues (widget, value, size, 0, 0, False);        XmScrollBarSetValues (widget, value, size, 0, 0, False);
4620      }      }
4621  #else /* !USE_MOTIF i.e. use Xaw */  #else /* !USE_MOTIF i.e. use Xaw */
# Line 8923  x_set_toolkit_scroll_bar_thumb (bar, por Line 4657  x_set_toolkit_scroll_bar_thumb (bar, por
4657  #ifdef HAVE_XAW3D  #ifdef HAVE_XAW3D
4658              ScrollbarWidget sb = (ScrollbarWidget) widget;              ScrollbarWidget sb = (ScrollbarWidget) widget;
4659              int scroll_mode = 0;              int scroll_mode = 0;
4660                
4661              /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR.  */              /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR.  */
4662              if (xaw3d_arrow_scroll)              if (xaw3d_arrow_scroll)
4663                {                {
# Line 8937  x_set_toolkit_scroll_bar_thumb (bar, por Line 4671  x_set_toolkit_scroll_bar_thumb (bar, por
4671              /* Try to make the scrolling a tad smoother.  */              /* Try to make the scrolling a tad smoother.  */
4672              if (!xaw3d_pick_top)              if (!xaw3d_pick_top)
4673                shown = min (shown, old_shown);                shown = min (shown, old_shown);
4674                
4675              XawScrollbarSetThumb (widget, top, shown);              XawScrollbarSetThumb (widget, top, shown);
4676                
4677  #ifdef HAVE_XAW3D  #ifdef HAVE_XAW3D
4678              if (xaw3d_arrow_scroll && scroll_mode == 2)              if (xaw3d_arrow_scroll && scroll_mode == 2)
4679                sb->scrollbar.scroll_mode = scroll_mode;                sb->scrollbar.scroll_mode = scroll_mode;
# Line 8951  x_set_toolkit_scroll_bar_thumb (bar, por Line 4685  x_set_toolkit_scroll_bar_thumb (bar, por
4685    
4686    UNBLOCK_INPUT;    UNBLOCK_INPUT;
4687  }  }
4688    #endif /* not USE_GTK */
4689    
4690  #endif /* USE_TOOLKIT_SCROLL_BARS */  #endif /* USE_TOOLKIT_SCROLL_BARS */
4691    
# Line 8959  x_set_toolkit_scroll_bar_thumb (bar, por Line 4694  x_set_toolkit_scroll_bar_thumb (bar, por
4694  /************************************************************************  /************************************************************************
4695                           Scroll bars, general                           Scroll bars, general
4696   ************************************************************************/   ************************************************************************/
4697                                                                            
4698  /* Create a scroll bar and return the scroll bar vector for it.  W is  /* Create a scroll bar and return the scroll bar vector for it.  W is
4699     the Emacs window on which to create the scroll bar. TOP, LEFT,     the Emacs window on which to create the scroll bar. TOP, LEFT,
4700     WIDTH and HEIGHT are the pixel coordinates and dimensions of the     WIDTH and HEIGHT are the pixel coordinates and dimensions of the
# Line 8987  x_scroll_bar_create (w, top, left, width Line 4722  x_scroll_bar_create (w, top, left, width
4722      a.background_pixel = f->output_data.x->scroll_bar_background_pixel;      a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
4723      if (a.background_pixel == -1)      if (a.background_pixel == -1)
4724        a.background_pixel = f->output_data.x->background_pixel;        a.background_pixel = f->output_data.x->background_pixel;
4725        
4726      a.event_mask = (ButtonPressMask | ButtonReleaseMask      a.event_mask = (ButtonPressMask | ButtonReleaseMask
4727                      | ButtonMotionMask | PointerMotionHintMask                      | ButtonMotionMask | PointerMotionHintMask
4728                      | ExposureMask);                      | ExposureMask);
# Line 9039  x_scroll_bar_create (w, top, left, width Line 4774  x_scroll_bar_create (w, top, left, width
4774    /* Map the window/widget.  */    /* Map the window/widget.  */
4775  #ifdef USE_TOOLKIT_SCROLL_BARS  #ifdef USE_TOOLKIT_SCROLL_BARS
4776    {    {
4777    #ifdef USE_GTK
4778        xg_update_scrollbar_pos (f,
4779                                 SCROLL_BAR_X_WINDOW (bar),
4780                                 top,
4781                                 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4782                                 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4783                                 max (height, 1),
4784                                 left,
4785                                 width);
4786        xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar));
4787    #else /* not USE_GTK */
4788      Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);      Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
4789      XtConfigureWidget (scroll_bar,      XtConfigureWidget (scroll_bar,
4790                         left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,                         left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
# Line 9046  x_scroll_bar_create (w, top, left, width Line 4792  x_scroll_bar_create (w, top, left, width
4792                         width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,                         width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4793                         max (height, 1), 0);                         max (height, 1), 0);
4794      XtMapWidget (scroll_bar);      XtMapWidget (scroll_bar);
4795    #endif /* not USE_GTK */
4796      }      }
4797  #else /* not USE_TOOLKIT_SCROLL_BARS */  #else /* not USE_TOOLKIT_SCROLL_BARS */
4798    XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));    XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
# Line 9057  x_scroll_bar_create (w, top, left, width Line 4804  x_scroll_bar_create (w, top, left, width
4804    
4805    
4806  /* Draw BAR's handle in the proper position.  /* Draw BAR's handle in the proper position.
4807      
4808     If the handle is already drawn from START to END, don't bother     If the handle is already drawn from START to END, don't bother
4809     redrawing it, unless REBUILD is non-zero; in that case, always     redrawing it, unless REBUILD is non-zero; in that case, always
4810     redraw it.  (REBUILD is handy for drawing the handle after expose     redraw it.  (REBUILD is handy for drawing the handle after expose
# Line 9180  x_scroll_bar_remove (bar) Line 4927  x_scroll_bar_remove (bar)
4927    BLOCK_INPUT;    BLOCK_INPUT;
4928    
4929  #ifdef USE_TOOLKIT_SCROLL_BARS  #ifdef USE_TOOLKIT_SCROLL_BARS
4930    #ifdef USE_GTK
4931      xg_remove_scroll_bar (f, SCROLL_BAR_X_WINDOW (bar));
4932    #else /* not USE_GTK */
4933    XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));    XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
4934    #endif /* not USE_GTK */
4935  #else  #else
4936    XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));    XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
4937  #endif  #endif
4938      
4939    /* Disassociate this scroll bar from its window.  */    /* Disassociate this scroll bar from its window.  */
4940    XWINDOW (bar->window)->vertical_scroll_bar = Qnil;    XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4941    
# Line 9231  XTset_vertical_scroll_bar (w, portion, w Line 4982  XTset_vertical_scroll_bar (w, portion, w
4982    /* Compute the left edge of the scroll bar.  */    /* Compute the left edge of the scroll bar.  */
4983  #ifdef USE_TOOLKIT_SCROLL_BARS  #ifdef USE_TOOLKIT_SCROLL_BARS
4984    if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))    if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4985      sb_left = left + width - sb_width - (width - sb_width) / 2;      sb_left = left + width - sb_width - (width - sb_width) / 2;
4986    else    else
4987      sb_left = left + (width - sb_width) / 2;      sb_left = left + (width - sb_width) / 2;
4988  #else  #else
4989    if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))    if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4990      sb_left = left + width - sb_width;      sb_left = left + width - sb_width;
4991    else    else
4992      sb_left = left;      sb_left = left;
4993  #endif  #endif
4994      
4995    /* Does the scroll bar exist yet?  */    /* Does the scroll bar exist yet?  */
4996    if (NILP (w->vertical_scroll_bar))    if (NILP (w->vertical_scroll_bar))
4997      {      {
# Line 9251  XTset_vertical_scroll_bar (w, portion, w Line 5002  XTset_vertical_scroll_bar (w, portion, w
5002                          left, top, width, height, False);                          left, top, width, height, False);
5003            UNBLOCK_INPUT;            UNBLOCK_INPUT;
5004          }          }
5005          
5006        bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);        bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
5007      }      }
5008    else    else
5009      {      {
5010        /* It may just need to be moved and resized.  */        /* It may just need to be moved and resized.  */
5011        unsigned int mask = 0;        unsigned int mask = 0;
5012          
5013        bar = XSCROLL_BAR (w->vertical_scroll_bar);        bar = XSCROLL_BAR (w->vertical_scroll_bar);
5014    
5015        BLOCK_INPUT;        BLOCK_INPUT;
# Line 9269  XTset_vertical_scroll_bar (w, portion, w Line 5020  XTset_vertical_scroll_bar (w, portion, w
5020          mask |= CWY;          mask |= CWY;
5021        if (sb_width != XINT (bar->width))        if (sb_width != XINT (bar->width))
5022          mask |= CWWidth;          mask |= CWWidth;
5023        if (height != XINT (bar->height))        if (height != XINT (bar->height))
5024          mask |= CWHeight;          mask |= CWHeight;
5025          
5026  #ifdef USE_TOOLKIT_SCROLL_BARS  #ifdef USE_TOOLKIT_SCROLL_BARS
5027    
5028    #ifdef USE_GTK
5029          if (mask)
5030            xg_update_scrollbar_pos (f,
5031                                     SCROLL_BAR_X_WINDOW (bar),
5032                                     top,
5033                                     sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5034                                     sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5035                                     max (height, 1),
5036                                     left,
5037                                     width);
5038    #else /* not USE_GTK */
5039    
5040        /* Since toolkit scroll bars are smaller than the space reserved        /* Since toolkit scroll bars are smaller than the space reserved
5041           for them on the frame, we have to clear "under" them.  */           for them on the frame, we have to clear "under" them.  */
5042        if (width > 0 && height > 0)        if (width > 0 && height > 0)
5043          x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),          x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5044                        left, top, width, height, False);                            left, top, width, height, False);
   
5045        /* Move/size the scroll bar widget.  */        /* Move/size the scroll bar widget.  */
5046        if (mask)        if (mask)
5047          XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),            XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
5048                             sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,                               sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
5049                             top,                               top,
5050                             sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,                               sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
5051                             max (height, 1), 0);                               max (height, 1), 0);
5052    
5053    #endif /* not USE_GTK */
5054  #else /* not USE_TOOLKIT_SCROLL_BARS */  #else /* not USE_TOOLKIT_SCROLL_BARS */
5055      
5056        /* Clear areas not covered by the scroll bar because of        /* Clear areas not covered by the scroll bar because of
5057           VERTICAL_SCROLL_BAR_WIDTH_TRIM.  */           VERTICAL_SCROLL_BAR_WIDTH_TRIM.  */
5058        if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)        if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
# Line 9321  XTset_vertical_scroll_bar (w, portion, w Line 5084  XTset_vertical_scroll_bar (w, portion, w
5084                              left, top, rest, height, False);                              left, top, rest, height, False);
5085            }            }
5086        }        }
5087          
5088        /* Move/size the scroll bar window.  */        /* Move/size the scroll bar window.  */
5089        if (mask)        if (mask)
5090          {          {
5091            XWindowChanges wc;            XWindowChanges wc;
5092              
5093            wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;            wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5094            wc.y = top;            wc.y = top;
5095            wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;            wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
# Line 9334  XTset_vertical_scroll_bar (w, portion, w Line 5097  XTset_vertical_scroll_bar (w, portion, w
5097            XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),            XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
5098                              mask, &wc);                              mask, &wc);
5099          }          }
5100      
5101  #endif /* not USE_TOOLKIT_SCROLL_BARS */  #endif /* not USE_TOOLKIT_SCROLL_BARS */
5102    
5103        /* Remember new settings.  */        /* Remember new settings.  */
# Line 9342  XTset_vertical_scroll_bar (w, portion, w Line 5105  XTset_vertical_scroll_bar (w, portion, w
5105        XSETINT (bar->top, top);        XSETINT (bar->top, top);
5106        XSETINT (bar->width, sb_width);        XSETINT (bar->width, sb_width);
5107        XSETINT (bar->height, height);        XSETINT (bar->height, height);
5108          
5109        UNBLOCK_INPUT;        UNBLOCK_INPUT;
5110      }      }
5111    
# Line 9477  XTjudge_scroll_bars (f) Line 5240  XTjudge_scroll_bars (f)
5240  }  }
5241    
5242    
5243    #ifndef USE_TOOLKIT_SCROLL_BARS
5244  /* Handle an Expose or GraphicsExpose event on a scroll bar.  This  /* Handle an Expose or GraphicsExpose event on a scroll bar.  This
5245     is a no-op when using toolkit scroll bars.     is a no-op when using toolkit scroll bars.
5246    
# Line 9488  x_scroll_bar_expose (bar, event) Line 5252  x_scroll_bar_expose (bar, event)
5252       struct scroll_bar *bar;       struct scroll_bar *bar;
5253       XEvent *event;       XEvent *event;
5254  {  {
 #ifndef USE_TOOLKIT_SCROLL_BARS  
   
5255    Window w = SCROLL_BAR_X_WINDOW (bar);    Window w = SCROLL_BAR_X_WINDOW (bar);
5256    FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));    FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
5257    GC gc = f->output_data.x->normal_gc;    GC gc = f->output_data.x->normal_gc;
# Line 9506  x_scroll_bar_expose (bar, event) Line 5268  x_scroll_bar_expose (bar, event)
5268                    0, 0,                    0, 0,
5269                    XINT (bar->width) - 1 - width_trim - width_trim,                    XINT (bar->width) - 1 - width_trim - width_trim,
5270                    XINT (bar->height) - 1);                    XINT (bar->height) - 1);
5271        
5272    UNBLOCK_INPUT;    UNBLOCK_INPUT;
5273    
 #endif /* not USE_TOOLKIT_SCROLL_BARS */  
5274  }  }
5275    #endif /* not USE_TOOLKIT_SCROLL_BARS */
5276    
5277  /* Handle a mouse click on the scroll bar BAR.  If *EMACS_EVENT's kind  /* Handle a mouse click on the scroll bar BAR.  If *EMACS_EVENT's kind
5278     is set to something other than no_event, it is enqueued.     is set to something other than NO_EVENT, it is enqueued.
5279    
5280     This may be called from a signal handler, so we have to ignore GC     This may be called from a signal handler, so we have to ignore GC
5281     mark bits.  */     mark bits.  */
5282    
 #ifndef USE_TOOLKIT_SCROLL_BARS  
5283    
5284  static void  static void
5285  x_scroll_bar_handle_click (bar, event, emacs_event)  x_scroll_bar_handle_click (bar, event, emacs_event)
# Line 9529  x_scroll_bar_handle_click (bar, event, e Line 5290  x_scroll_bar_handle_click (bar, event, e
5290    if (! GC_WINDOWP (bar->window))    if (! GC_WINDOWP (bar->window))
5291      abort ();      abort ();
5292    
5293    emacs_event->kind = scroll_bar_click;    emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
5294    emacs_event->code = event->xbutton.button - Button1;    emacs_event->code = event->xbutton.button - Button1;
5295    emacs_event->modifiers    emacs_event->modifiers
5296      = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO      = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
5297                                 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),                                 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
5298                                 event->xbutton.state)                                 event->xbutton.state)
5299         | (event->type == ButtonRelease         | (event->type == ButtonRelease
# Line 9572  x_scroll_bar_handle_click (bar, event, e Line 5333  x_scroll_bar_handle_click (bar, event, e
5333        XSETINT (bar->dragging, y - XINT (bar->start));        XSETINT (bar->dragging, y - XINT (bar->start));
5334  #endif  #endif
5335    
5336    #ifndef USE_TOOLKIT_SCROLL_BARS
5337      /* If the user has released the handle, set it to its final position.  */      /* If the user has released the handle, set it to its final position.  */
5338      if (event->type == ButtonRelease      if (event->type == ButtonRelease
5339          && ! NILP (bar->dragging))          && ! NILP (bar->dragging))
# Line 9582  x_scroll_bar_handle_click (bar, event, e Line 5344  x_scroll_bar_handle_click (bar, event, e
5344          x_scroll_bar_set_handle (bar, new_start, new_end, 0);          x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5345          bar->dragging = Qnil;          bar->dragging = Qnil;
5346        }        }
5347    #endif
5348    
5349      /* Same deal here as the other #if 0.  */      /* Same deal here as the other #if 0.  */
5350  #if 0  #if 0
# Line 9599  x_scroll_bar_handle_click (bar, event, e Line 5362  x_scroll_bar_handle_click (bar, event, e
5362    }    }
5363  }  }
5364    
5365    #ifndef USE_TOOLKIT_SCROLL_BARS
5366    
5367  /* Handle some mouse motion while someone is dragging the scroll bar.  /* Handle some mouse motion while someone is dragging the scroll bar.
5368    
5369     This may be called from a signal handler, so we have to ignore GC     This may be called from a signal handler, so we have to ignore GC
# Line 9736  x_scroll_bar_clear (f) Line 5501  x_scroll_bar_clear (f)
5501  #endif /* not USE_TOOLKIT_SCROLL_BARS */  #endif /* not USE_TOOLKIT_SCROLL_BARS */
5502  }  }
5503    
 /* This processes Expose events from the menu-bar specific X event  
    loop in xmenu.c.  This allows to redisplay the frame if necessary  
    when handling menu-bar or pop-up items.  */  
   
 int  
 process_expose_from_menu (event)  
      XEvent event;  
 {  
   FRAME_PTR f;  
   struct x_display_info *dpyinfo;  
   int frame_exposed_p = 0;  
   
   BLOCK_INPUT;  
   
   dpyinfo = x_display_info_for_display (event.xexpose.display);  
   f = x_window_to_frame (dpyinfo, event.xexpose.window);  
   if (f)  
     {  
       if (f->async_visible == 0)  
         {  
           f->async_visible = 1;  
           f->async_iconified = 0;  
           f->output_data.x->has_been_visible = 1;  
           SET_FRAME_GARBAGED (f);  
         }  
       else  
         {  
           expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),  
                         event.xexpose.x, event.xexpose.y,  
                         event.xexpose.width, event.xexpose.height);  
           frame_exposed_p = 1;  
         }  
     }  
   else  
     {  
       struct scroll_bar *bar  
         = x_window_to_scroll_bar (event.xexpose.window);  
   
       if (bar)  
         x_scroll_bar_expose (bar, &event);  
     }  
   
   UNBLOCK_INPUT;  
   return frame_exposed_p;  
 }  
5504    
5505  /* Define a queue to save up SelectionRequest events for later handling.  */  /* Define a queue to save up SelectionRequest events for later handling.  */
5506    
# Line 9896  static struct x_display_info *next_noop_ Line 5616  static struct x_display_info *next_noop_
5616           bcopy (&event, f->output_data.x->saved_menu_event, size);      \           bcopy (&event, f->output_data.x->saved_menu_event, size);      \
5617           if (numchars >= 1)                                             \           if (numchars >= 1)                                             \
5618             {                                                            \             {                                                            \
5619               bufp->kind = menu_bar_activate_event;                      \               bufp->kind = MENU_BAR_ACTIVATE_EVENT;                      \
5620               XSETFRAME (bufp->frame_or_window, f);                      \               XSETFRAME (bufp->frame_or_window, f);                      \
5621               bufp->arg = Qnil;                                          \               bufp->arg = Qnil;                                          \
5622               bufp++;                                                    \               bufp++;                                                    \
# Line 9909  static struct x_display_info *next_noop_ Line 5629  static struct x_display_info *next_noop_
5629  #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))  #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
5630  #define SET_SAVED_KEY_EVENT    SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))  #define SET_SAVED_KEY_EVENT    SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
5631    
 /* Read events coming from the X server.  
    This routine is called by the SIGIO handler.  
    We return as soon as there are no more events to be read.  
5632    
5633     Events representing keys are stored in buffer BUFP,  enum
5634     which can hold up to NUMCHARS characters.  {
5635     We return the number of characters stored into the buffer,    X_EVENT_NORMAL,
5636     thus pretending to be `read'.    X_EVENT_GOTO_OUT,
5637      X_EVENT_DROP
5638    };
5639    
5640     EXPECTED is nonzero if the caller knows input is available.  */  /* Filter events for the current X input method.
5641       DPYINFO is the display this event is for.
5642       EVENT is the X event to filter.
5643    
5644       Returns non-zero if the event was filtered, caller shall not process
5645       this event further.
5646       Returns zero if event is wasn't filtered.  */
5647    
5648    #ifdef HAVE_X_I18N
5649  static int  static int
5650  XTread_socket (sd, bufp, numchars, expected)  x_filter_event (dpyinfo, event)
5651       register int sd;       struct x_display_info *dpyinfo;
5652       /* register */ struct input_event *bufp;       XEvent *event;
      /* register */ int numchars;  
      int expected;  
5653  {  {
5654    int count = 0;    /* XFilterEvent returns non-zero if the input method has
5655    int nbytes = 0;     consumed the event.  We pass the frame's X window to
5656    XEvent event;     XFilterEvent because that's the one for which the IC
5657    struct frame *f;     was created.  */
   int event_found = 0;  
   struct x_display_info *dpyinfo;  
   struct coding_system coding;  
5658    
5659    if (interrupt_input_blocked)    struct frame *f1 = x_any_window_to_frame (dpyinfo,
5660      {                                              event->xclient.window);
       interrupt_input_pending = 1;  
       return -1;  
     }  
5661    
5662    interrupt_input_pending = 0;    return XFilterEvent (event, f1 ? FRAME_X_WINDOW (f1) : None);
5663    BLOCK_INPUT;  }
5664    #endif
5665    
5666    /* So people can tell when we have read the available input.  */  #ifdef USE_GTK
5667    input_signal_count++;  static struct x_display_info *current_dpyinfo;
5668    static struct input_event **current_bufp;
5669    static int *current_numcharsp;
5670    static int current_count;
5671    static int current_finish;
5672    
5673    if (numchars <= 0)  /* This is the filter function invoked by the GTK event loop.
5674      abort ();                   /* Don't think this happens.  */     It is invoked before the XEvent is translated to a GdkEvent,
5675       so we have a chanse to act on the event before GTK. */
5676    static GdkFilterReturn
5677    event_handler_gdk (gxev, ev, data)
5678         GdkXEvent *gxev;
5679         GdkEvent *ev;
5680         gpointer data;
5681    {
5682      XEvent *xev = (XEvent*)gxev;
5683    
5684    ++handling_signal;    if (current_numcharsp)
     
   /* Find the display we are supposed to read input for.  
      It's the one communicating on descriptor SD.  */  
   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)  
5685      {      {
5686  #if 0 /* This ought to be unnecessary; let's verify it.  */  #ifdef HAVE_X_I18N
5687  #ifdef FIOSNBIO        /* Filter events for the current X input method.
5688        /* If available, Xlib uses FIOSNBIO to make the socket           GTK calls XFilterEvent but not for key press and release,
5689           non-blocking, and then looks for EWOULDBLOCK.  If O_NDELAY is set,           so we do it here.  */
5690           FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,        if (xev->type == KeyPress || xev->type == KeyRelease)
5691           a read returns 0, which Xlib interprets as equivalent to EPIPE.  */          if (x_filter_event (current_dpyinfo, xev))
5692        fcntl (dpyinfo->connection, F_SETFL, 0);            return GDK_FILTER_REMOVE;
 #endif /* ! defined (FIOSNBIO) */  
5693  #endif  #endif
5694          current_count += handle_one_xevent (current_dpyinfo,
5695                                              xev,
5696                                              current_bufp,
5697                                              current_numcharsp,
5698                                              &current_finish);
5699        }
5700      else
5701        current_finish = x_dispatch_event (xev, GDK_DISPLAY ());
5702    
5703  #if 0 /* This code can't be made to work, with multiple displays,    if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
5704           and appears not to be used on any system any more.      return GDK_FILTER_REMOVE;
          Also keyboard.c doesn't turn O_NDELAY on and off  
          for X connections.  */  
 #ifndef SIGIO  
 #ifndef HAVE_SELECT  
       if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))  
         {  
           extern int read_alarm_should_throw;  
           read_alarm_should_throw = 1;  
           XPeekEvent (dpyinfo->display, &event);  
           read_alarm_should_throw = 0;  
         }  
 #endif /* HAVE_SELECT */  
 #endif /* SIGIO */  
 #endif  
5705    
5706        /* For debugging, this gives a way to fake an I/O error.  */    return GDK_FILTER_CONTINUE;
5707        if (dpyinfo == XTread_socket_fake_io_error)  }
5708          {  #endif /* USE_GTK */
           XTread_socket_fake_io_error = 0;  
           x_io_error_quitter (dpyinfo->display);  
         }  
5709    
 #ifdef HAVE_X_SM  
       BLOCK_INPUT;  
       count += x_session_check_input (bufp, &numchars);  
       UNBLOCK_INPUT;  
 #endif  
5710    
5711        while (XPending (dpyinfo->display))  /* Handles the XEvent EVENT on display DPYINFO.
         {  
           XNextEvent (dpyinfo->display, &event);  
5712    
5713  #ifdef HAVE_X_I18N     *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
5714            {     *FINISH is zero if caller should continue reading events.
5715              /* Filter events for the current X input method.     *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
                XFilterEvent returns non-zero if the input method has  
                consumed the event.  We pass the frame's X window to  
                XFilterEvent because that's the one for which the IC  
                was created.  */  
             struct frame *f1 = x_any_window_to_frame (dpyinfo,  
                                                       event.xclient.window);  
             if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))  
               break;  
           }  
 #endif  
           event_found = 1;  
5716    
5717            switch (event.type)     Events representing keys are stored in buffer *BUFP_R,
5718              {     which can hold up to *NUMCHARSP characters.
5719              case ClientMessage:     We return the number of characters stored into the buffer. */
5720                {  
5721                  if (event.xclient.message_type  static int
5722                      == dpyinfo->Xatom_wm_protocols  handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
5723                      && event.xclient.format == 32)       struct x_display_info *dpyinfo;
5724                    {       XEvent *eventp;
5725                      if (event.xclient.data.l[0]       /* register */ struct input_event **bufp_r;
5726                          == dpyinfo->Xatom_wm_take_focus)       /* register */ int *numcharsp;
5727                        {       int *finish;
5728                          /* Use x_any_window_to_frame because this  {
5729                             could be the shell widget window    int count = 0;
5730                             if the frame has no title bar.  */    int nbytes = 0;
5731                          f = x_any_window_to_frame (dpyinfo, event.xclient.window);    struct frame *f;
5732      struct coding_system coding;
5733      struct input_event *bufp = *bufp_r;
5734      int numchars = *numcharsp;
5735      XEvent event = *eventp;
5736    
5737      *finish = X_EVENT_NORMAL;
5738    
5739      switch (event.type)
5740        {
5741        case ClientMessage:
5742          {
5743            if (event.xclient.message_type
5744                == dpyinfo->Xatom_wm_protocols
5745                && event.xclient.format == 32)
5746              {
5747                if (event.xclient.data.l[0]
5748                    == dpyinfo->Xatom_wm_take_focus)
5749                  {
5750                    /* Use x_any_window_to_frame because this
5751                       could be the shell widget window
5752                       if the frame has no title bar.  */
5753                    f = x_any_window_to_frame (dpyinfo, event.xclient.window);
5754  #ifdef HAVE_X_I18N  #ifdef HAVE_X_I18N
5755                          /* Not quite sure this is needed -pd */                  /* Not quite sure this is needed -pd */
5756                          if (f && FRAME_XIC (f))                  if (f && FRAME_XIC (f))
5757                            XSetICFocus (FRAME_XIC (f));                    XSetICFocus (FRAME_XIC (f));
5758  #endif  #endif
5759  #if 0 /* Emacs sets WM hints whose `input' field is `true'.  This  #if 0 /* Emacs sets WM hints whose `input' field is `true'.  This
5760           instructs the WM to set the input focus automatically for           instructs the WM to set the input focus automatically for
# Line 10047  XTread_socket (sd, bufp, numchars, expec Line 5768  XTread_socket (sd, bufp, numchars, expec
5768           below are temporally close (on a fast machine), the call           below are temporally close (on a fast machine), the call
5769           below can generate additional FocusIn events which confuse           below can generate additional FocusIn events which confuse
5770           Emacs.  */           Emacs.  */
5771                            
5772                          /* Since we set WM_TAKE_FOCUS, we must call                  /* Since we set WM_TAKE_FOCUS, we must call
5773                             XSetInputFocus explicitly.  But not if f is null,                     XSetInputFocus explicitly.  But not if f is null,
5774                             since that might be an event for a deleted frame.  */                     since that might be an event for a deleted frame.  */
5775                          if (f)                  if (f)
5776                            {                    {
5777                              Display *d = event.xclient.display;                      Display *d = event.xclient.display;
5778                              /* Catch and ignore errors, in case window has been                      /* Catch and ignore errors, in case window has been
5779                                 iconified by a window manager such as GWM.  */                         iconified by a window manager such as GWM.  */
5780                              int count = x_catch_errors (d);                      int count = x_catch_errors (d);
5781                              XSetInputFocus (d, event.xclient.window,                      XSetInputFocus (d, event.xclient.window,
5782                                              /* The ICCCM says this is                                      /* The ICCCM says this is
5783                                                 the only valid choice.  */                                         the only valid choice.  */
5784                                              RevertToParent,                                      RevertToParent,
5785                                              event.xclient.data.l[1]);                                      event.xclient.data.l[1]);
5786                              /* This is needed to detect the error                      /* This is needed to detect the error
5787                                 if there is an error.  */                         if there is an error.  */
5788                              XSync (d, False);                      XSync (d, False);
5789                              x_uncatch_errors (d, count);                      x_uncatch_errors (d, count);
5790                            }                      }
5791                          /* Not certain about handling scroll bars here */                  /* Not certain about handling scroll bars here */
5792  #endif /* 0 */  #endif /* 0 */
5793                        }                }
5794                      else if (event.xclient.data.l[0]              else if (event.xclient.data.l[0]
5795                               == dpyinfo->Xatom_wm_save_yourself)                       == dpyinfo->Xatom_wm_save_yourself)
5796                        {                {
5797                          /* Save state modify the WM_COMMAND property to                  /* Save state modify the WM_COMMAND property to
5798                             something which can reinstate us.  This notifies                     something which can reinstate us.  This notifies
5799                             the session manager, who's looking for such a                     the session manager, who's looking for such a
5800                             PropertyNotify.  Can restart processing when                     PropertyNotify.  Can restart processing when
5801                             a keyboard or mouse event arrives.  */                     a keyboard or mouse event arrives.  */
5802                          /* If we have a session manager, don't set this.                  /* If we have a session manager, don't set this.
5803                             KDE will then start two Emacsen, one for the                     KDE will then start two Emacsen, one for the
5804                             session manager and one for this. */                     session manager and one for this. */
5805                          if (numchars > 0                  if (numchars > 0
5806  #ifdef HAVE_X_SM  #ifdef HAVE_X_SM
5807                              && ! x_session_have_connection ()                      && ! x_session_have_connection ()
5808  #endif  #endif
5809                              )                      )
5810                            {                    {
5811                              f = x_top_window_to_frame (dpyinfo,                      f = x_top_window_to_frame (dpyinfo,
5812                                                         event.xclient.window);                                                 event.xclient.window);
5813                              /* This is just so we only give real data once                      /* This is just so we only give real data once
5814                                 for a single Emacs process.  */                         for a single Emacs process.  */
5815                              if (f == SELECTED_FRAME ())                      if (f == SELECTED_FRAME ())
5816                                XSetCommand (FRAME_X_DISPLAY (f),                        XSetCommand (FRAME_X_DISPLAY (f),
5817                                             event.xclient.window,                                     event.xclient.window,
5818                                             initial_argv, initial_argc);                                     initial_argv, initial_argc);
5819                              else if (f)                      else if (f)
5820                                XSetCommand (FRAME_X_DISPLAY (f),                        XSetCommand (FRAME_X_DISPLAY (f),
5821                                             event.xclient.window,                                     event.xclient.window,
5822                                             0, 0);                                     0, 0);
5823                            }                    }
5824                        }                }
5825                      else if (event.xclient.data.l[0]              else if (event.xclient.data.l[0]
5826                               == dpyinfo->Xatom_wm_delete_window)                       == dpyinfo->Xatom_wm_delete_window)
5827                        {                {
5828                          struct frame *f                  struct frame *f
5829                            = x_any_window_to_frame (dpyinfo,                    = x_any_window_to_frame (dpyinfo,
5830                                                     event.xclient.window);                                             event.xclient.window);
5831    
5832                          if (f)                  if (f)
5833                            {                    {
5834                              if (numchars == 0)                      if (numchars == 0)
5835                                abort ();                        abort ();
5836    
5837                              bufp->kind = delete_window_event;                      bufp->kind = DELETE_WINDOW_EVENT;
5838                              XSETFRAME (bufp->frame_or_window, f);                      XSETFRAME (bufp->frame_or_window, f);
5839                              bufp->arg = Qnil;                      bufp->arg = Qnil;
5840                              bufp++;                      bufp++;
5841    
5842                              count += 1;                      count += 1;
5843                              numchars -= 1;                      numchars -= 1;
5844                            }                    }
5845                        }                  else
5846                    }                    goto OTHER; /* May be a dialog that is to be removed  */
5847                  else if (event.xclient.message_type                }
5848                           == dpyinfo->Xatom_wm_configure_denied)            }
5849                    {          else if (event.xclient.message_type
5850                    }                   == dpyinfo->Xatom_wm_configure_denied)
5851                  else if (event.xclient.message_type            {
5852                           == dpyinfo->Xatom_wm_window_moved)            }
5853                    {          else if (event.xclient.message_type
5854                      int new_x, new_y;                   == dpyinfo->Xatom_wm_window_moved)
5855                      struct frame *f            {
5856                        = x_window_to_frame (dpyinfo, event.xclient.window);              int new_x, new_y;
5857                struct frame *f
5858                      new_x = event.xclient.data.s[0];                = x_window_to_frame (dpyinfo, event.xclient.window);
5859                      new_y = event.xclient.data.s[1];  
5860                new_x = event.xclient.data.s[0];
5861                      if (f)              new_y = event.xclient.data.s[1];
5862                        {  
5863                          f->output_data.x->left_pos = new_x;              if (f)
5864                          f->output_data.x->top_pos = new_y;                {
5865                        }                  f->output_data.x->left_pos = new_x;
5866                    }                  f->output_data.x->top_pos = new_y;
5867                  }
5868              }
5869  #ifdef HACK_EDITRES  #ifdef HACK_EDITRES
5870                  else if (event.xclient.message_type          else if (event.xclient.message_type
5871                           == dpyinfo->Xatom_editres)                   == dpyinfo->Xatom_editres)
5872                    {            {
5873                      struct frame *f              struct frame *f
5874                        = x_any_window_to_frame (dpyinfo, event.xclient.window);                = x_any_window_to_frame (dpyinfo, event.xclient.window);
5875                      _XEditResCheckMessages (f->output_data.x->widget, NULL,              _XEditResCheckMessages (f->output_data.x->widget, NULL,
5876                                              &event, NULL);                                      &event, NULL);
5877                    }            }
5878  #endif /* HACK_EDITRES */  #endif /* HACK_EDITRES */
5879                  else if ((event.xclient.message_type          else if ((event.xclient.message_type
5880                            == dpyinfo->Xatom_DONE)                    == dpyinfo->Xatom_DONE)
5881                           || (event.xclient.message_type                   || (event.xclient.message_type
5882                               == dpyinfo->Xatom_PAGE))                       == dpyinfo->Xatom_PAGE))
5883                    {            {
5884                      /* Ghostview job completed.  Kill it.  We could              /* Ghostview job completed.  Kill it.  We could
5885                         reply with "Next" if we received "Page", but we                 reply with "Next" if we received "Page", but we
5886                         currently never do because we are interested in                 currently never do because we are interested in
5887                         images, only, which should have 1 page.  */                 images, only, which should have 1 page.  */
5888                      Pixmap pixmap = (Pixmap) event.xclient.data.l[1];              Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
5889                      struct frame *f              struct frame *f
5890                        = x_window_to_frame (dpyinfo, event.xclient.window);                = x_window_to_frame (dpyinfo, event.xclient.window);
5891                      x_kill_gs_process (pixmap, f);              x_kill_gs_process (pixmap, f);
5892                      expose_frame (f, 0, 0, 0, 0);              expose_frame (f, 0, 0, 0, 0);
5893                    }            }
5894  #ifdef USE_TOOLKIT_SCROLL_BARS  #ifdef USE_TOOLKIT_SCROLL_BARS
5895                  /* Scroll bar callbacks send a ClientMessage from which          /* Scroll bar callbacks send a ClientMessage from which
5896                     we construct an input_event.  */             we construct an input_event.  */
5897                  else if (event.xclient.message_type          else if (event.xclient.message_type
5898                           == dpyinfo->Xatom_Scrollbar)                   == dpyinfo->Xatom_Scrollbar)
5899                    {            {
5900                      x_scroll_bar_to_input_event (&event, bufp);              x_scroll_bar_to_input_event (&event, bufp);
5901                      ++bufp, ++count, --numchars;              ++bufp, ++count, --numchars;
5902                      goto out;              goto out;
5903                    }            }
5904  #endif /* USE_TOOLKIT_SCROLL_BARS */  #endif /* USE_TOOLKIT_SCROLL_BARS */
5905                  else          else
5906                    goto OTHER;            goto OTHER;
5907                }        }
5908                break;        break;
5909    
5910              case SelectionNotify:      case SelectionNotify:
5911  #ifdef USE_X_TOOLKIT  #ifdef USE_X_TOOLKIT
5912                if (! x_window_to_frame (dpyinfo, event.xselection.requestor))        if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
5913                  goto OTHER;          goto OTHER;
5914  #endif /* not USE_X_TOOLKIT */  #endif /* not USE_X_TOOLKIT */
5915                x_handle_selection_notify (&event.xselection);        x_handle_selection_notify (&event.xselection);
5916                break;        break;
5917    
5918              case SelectionClear:        /* Someone has grabbed ownership.  */      case SelectionClear:        /* Someone has grabbed ownership.  */
5919  #ifdef USE_X_TOOLKIT  #ifdef USE_X_TOOLKIT
5920                if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))        if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
5921                  goto OTHER;          goto OTHER;
5922  #endif /* USE_X_TOOLKIT */  #endif /* USE_X_TOOLKIT */
5923                {        {
5924                  XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;          XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
5925    
5926                  if (numchars == 0)          if (numchars == 0)
5927                    abort ();            abort ();
5928    
5929                  bufp->kind = selection_clear_event;          bufp->kind = SELECTION_CLEAR_EVENT;
5930                  SELECTION_EVENT_DISPLAY (bufp) = eventp->display;          SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
5931                  SELECTION_EVENT_SELECTION (bufp) = eventp->selection;          SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
5932                  SELECTION_EVENT_TIME (bufp) = eventp->time;          SELECTION_EVENT_TIME (bufp) = eventp->time;
5933                  bufp->frame_or_window = Qnil;          bufp->frame_or_window = Qnil;
5934                  bufp->arg = Qnil;          bufp->arg = Qnil;
5935                  bufp++;          bufp++;
5936    
5937                  count += 1;          count += 1;
5938                  numchars -= 1;          numchars -= 1;
5939                }        }
5940                break;        break;
5941    
5942              case SelectionRequest:      /* Someone wants our selection.  */      case SelectionRequest:      /* Someone wants our selection.  */
5943  #ifdef USE_X_TOOLKIT  #ifdef USE_X_TOOLKIT
5944                if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))        if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
5945                  goto OTHER;          goto OTHER;
5946  #endif /* USE_X_TOOLKIT */  #endif /* USE_X_TOOLKIT */
5947                if (x_queue_selection_requests)        if (x_queue_selection_requests)
5948                  x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),          x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
5949                                 &event);                         &event);
5950                else        else
5951                  {          {
5952                    XSelectionRequestEvent *eventp            XSelectionRequestEvent *eventp
5953                      = (XSelectionRequestEvent *) &event;              = (XSelectionRequestEvent *) &event;
5954    
5955                    if (numchars == 0)            if (numchars == 0)
5956                      abort ();              abort ();
5957    
5958                    bufp->kind = selection_request_event;            bufp->kind = SELECTION_REQUEST_EVENT;
5959                    SELECTION_EVENT_DISPLAY (bufp) = eventp->display;            SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
5960                    SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;            SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
5961                    SELECTION_EVENT_SELECTION (bufp) = eventp->selection;            SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
5962                    SELECTION_EVENT_TARGET (bufp) = eventp->target;            SELECTION_EVENT_TARGET (bufp) = eventp->target;
5963                    SELECTION_EVENT_PROPERTY (bufp) = eventp->property;            SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
5964                    SELECTION_EVENT_TIME (bufp) = eventp->time;            SELECTION_EVENT_TIME (bufp) = eventp->time;
5965                    bufp->frame_or_window = Qnil;            bufp->frame_or_window = Qnil;
5966                    bufp->arg = Qnil;            bufp->arg = Qnil;
5967                    bufp++;            bufp++;
5968    
5969                    count += 1;            count += 1;
5970                    numchars -= 1;            numchars -= 1;
5971                  }          }
5972                break;        break;
5973    
5974              case PropertyNotify:      case PropertyNotify:
5975  #if 0 /* This is plain wrong.  In the case that we are waiting for a  #if 0 /* This is plain wrong.  In the case that we are waiting for a
5976           PropertyNotify used as an ACK in incremental selection           PropertyNotify used as an ACK in incremental selection
5977           transfer, the property will be on the receiver's window.  */           transfer, the property will be on the receiver's window.  */
5978  #if defined USE_X_TOOLKIT  #if defined USE_X_TOOLKIT
5979                if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))        if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
5980                  goto OTHER;          goto OTHER;
5981  #endif  #endif
5982  #endif  #endif
5983                x_handle_property_notify (&event.xproperty);        x_handle_property_notify (&event.xproperty);
5984                goto OTHER;        goto OTHER;
5985    
5986              case ReparentNotify:      case ReparentNotify:
5987                f = x_top_window_to_frame (dpyinfo, event.xreparent.window);        f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
5988                if (f)        if (f)
5989                  {          {
5990                    int x, y;            int x, y;
5991                    f->output_data.x->parent_desc = event.xreparent.parent;            f->output_data.x->parent_desc = event.xreparent.parent;
5992                    x_real_positions (f, &x, &y);            x_real_positions (f, &x, &y);
5993                    f->output_data.x->left_pos = x;            f->output_data.x->left_pos = x;
5994                    f->output_data.x->top_pos = y;            f->output_data.x->top_pos = y;
5995                  }          }
5996                break;        goto OTHER;
5997          break;
5998    
5999              case Expose:      case Expose:
6000                f = x_window_to_frame (dpyinfo, event.xexpose.window);        f = x_window_to_frame (dpyinfo, event.xexpose.window);
6001                if (f)        if (f)
6002                  {          {
6003                    x_check_fullscreen (f);            x_check_fullscreen (f);
6004    
6005                    if (f->async_visible == 0)            if (f->async_visible == 0)
6006                      {              {
6007                        f->async_visible = 1;                f->async_visible = 1;
6008                        f->async_iconified = 0;                f->async_iconified = 0;
6009                        f->output_data.x->has_been_visible = 1;                f->output_data.x->has_been_visible = 1;
6010                        SET_FRAME_GARBAGED (f);                SET_FRAME_GARBAGED (f);
6011                      }              }
6012                    else            else
6013                      expose_frame (x_window_to_frame (dpyinfo,              expose_frame (x_window_to_frame (dpyinfo,
6014                                                       event.xexpose.window),                                               event.xexpose.window),
6015                                    event.xexpose.x, event.xexpose.y,                            event.xexpose.x, event.xexpose.y,
6016                                    event.xexpose.width, event.xexpose.height);                            event.xexpose.width, event.xexpose.height);
6017                  }          }
6018                else        else
6019                  {          {
6020  #ifndef USE_TOOLKIT_SCROLL_BARS  #ifndef USE_TOOLKIT_SCROLL_BARS
6021                    struct scroll_bar *bar;            struct scroll_bar *bar;
6022  #endif  #endif
6023  #if defined USE_LUCID  #if defined USE_LUCID
6024                    /* Submenus of the Lucid menu bar aren't widgets            /* Submenus of the Lucid menu bar aren't widgets
6025                       themselves, so there's no way to dispatch events               themselves, so there's no way to dispatch events
6026                       to them.  Recognize this case separately.  */               to them.  Recognize this case separately.  */
6027                    {            {
6028                      Widget widget              Widget widget
6029                        = x_window_to_menu_bar (event.xexpose.window);                = x_window_to_menu_bar (event.xexpose.window);
6030                      if (widget)              if (widget)
6031                        xlwmenu_redisplay (widget);                xlwmenu_redisplay (widget);
6032                    }            }
6033  #endif /* USE_LUCID */  #endif /* USE_LUCID */
6034    
6035  #ifdef USE_TOOLKIT_SCROLL_BARS  #ifdef USE_TOOLKIT_SCROLL_BARS
6036                    /* Dispatch event to the widget.  */            /* Dispatch event to the widget.  */
6037                    goto OTHER;            goto OTHER;
6038  #else /* not USE_TOOLKIT_SCROLL_BARS */  #else /* not USE_TOOLKIT_SCROLL_BARS */
6039                    bar = x_window_to_scroll_bar (event.xexpose.window);            bar = x_window_to_scroll_bar (event.xexpose.window);
6040    
6041                    if (bar)            if (bar)
6042                      x_scroll_bar_expose (bar, &event);              x_scroll_bar_expose (bar, &event);
6043  #ifdef USE_X_TOOLKIT  #ifdef USE_X_TOOLKIT
6044                    else            else
6045                      goto OTHER;              goto OTHER;
6046  #endif /* USE_X_TOOLKIT */  #endif /* USE_X_TOOLKIT */
6047  #endif /* not USE_TOOLKIT_SCROLL_BARS */  #endif /* not USE_TOOLKIT_SCROLL_BARS */
6048                  }          }
6049                break;        break;
6050    
6051              case GraphicsExpose:        /* This occurs when an XCopyArea's      case GraphicsExpose:        /* This occurs when an XCopyArea's
6052                                             source area was obscured or not                                     source area was obscured or not
6053                                             available.  */                                     available.  */
6054                f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);        f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
6055                if (f)        if (f)
6056                  {          {
6057                    expose_frame (f,            expose_frame (f,
6058                                  event.xgraphicsexpose.x, event.xgraphicsexpose.y,                          event.xgraphicsexpose.x, event.xgraphicsexpose.y,
6059                                  event.xgraphicsexpose.width,                          event.xgraphicsexpose.width,
6060                                  event.xgraphicsexpose.height);                          event.xgraphicsexpose.height);
6061                  }          }
6062  #ifdef USE_X_TOOLKIT  #ifdef USE_X_TOOLKIT
6063                else        else
6064                  goto OTHER;          goto OTHER;
6065  #endif /* USE_X_TOOLKIT */  #endif /* USE_X_TOOLKIT */
6066                break;        break;
   
             case NoExpose:              /* This occurs when an XCopyArea's  
                                            source area was completely  
                                            available.  */  
               break;  
6067    
6068              case UnmapNotify:      case NoExpose:              /* This occurs when an XCopyArea's
6069                /* Redo the mouse-highlight after the tooltip has gone.  */                                     source area was completely
6070                if (event.xmap.window == tip_window)                                     available.  */
6071                  {        break;
                   tip_window = 0;  
                   redo_mouse_highlight ();  
                 }  
                 
               f = x_top_window_to_frame (dpyinfo, event.xunmap.window);  
               if (f)            /* F may no longer exist if  
                                    the frame was deleted.  */  
                 {  
                   /* While a frame is unmapped, display generation is  
                      disabled; you don't want to spend time updating a  
                      display that won't ever be seen.  */  
                   f->async_visible = 0;  
                   /* We can't distinguish, from the event, whether the window  
                      has become iconified or invisible.  So assume, if it  
                      was previously visible, than now it is iconified.  
                      But x_make_frame_invisible clears both  
                      the visible flag and the iconified flag;  
                      and that way, we know the window is not iconified now.  */  
                   if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))  
                     {  
                       f->async_iconified = 1;  
6072    
6073                        bufp->kind = iconify_event;      case UnmapNotify:
6074                        XSETFRAME (bufp->frame_or_window, f);        /* Redo the mouse-highlight after the tooltip has gone.  */
6075                        bufp->arg = Qnil;        if (event.xmap.window == tip_window)
6076                        bufp++;          {
6077                        count++;            tip_window = 0;
6078                        numchars--;            redo_mouse_highlight ();
6079                      }          }
                 }  
               goto OTHER;  
6080    
6081              case MapNotify:        f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
6082                if (event.xmap.window == tip_window)        if (f)            /* F may no longer exist if
6083                  /* The tooltip has been drawn already.  Avoid                             the frame was deleted.  */
6084                     the SET_FRAME_GARBAGED below.  */          {
6085                  goto OTHER;            /* While a frame is unmapped, display generation is
6086                               disabled; you don't want to spend time updating a
6087                /* We use x_top_window_to_frame because map events can               display that won't ever be seen.  */
6088                   come for sub-windows and they don't mean that the            f->async_visible = 0;
6089                   frame is visible.  */            /* We can't distinguish, from the event, whether the window
6090                f = x_top_window_to_frame (dpyinfo, event.xmap.window);               has become iconified or invisible.  So assume, if it
6091                if (f)               was previously visible, than now it is iconified.
6092                  {               But x_make_frame_invisible clears both
6093                    f->async_visible = 1;               the visible flag and the iconified flag;
6094                    f->async_iconified = 0;               and that way, we know the window is not iconified now.  */
6095                    f->output_data.x->has_been_visible = 1;            if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
6096                {
6097                    /* wait_reading_process_input will notice this and update                f->async_iconified = 1;
6098                       the frame's display structures.  */  
6099                    SET_FRAME_GARBAGED (f);                bufp->kind = ICONIFY_EVENT;
6100                  XSETFRAME (bufp->frame_or_window, f);
6101                  bufp->arg = Qnil;
6102                  bufp++;
6103                  count++;
6104                  numchars--;
6105                }
6106            }
6107          goto OTHER;
6108    
6109                    if (f->iconified)      case MapNotify:
6110                      {        if (event.xmap.window == tip_window)
6111                        bufp->kind = deiconify_event;          /* The tooltip has been drawn already.  Avoid
6112                        XSETFRAME (bufp->frame_or_window, f);             the SET_FRAME_GARBAGED below.  */
6113                        bufp->arg = Qnil;          goto OTHER;
6114                        bufp++;  
6115                        count++;        /* We use x_top_window_to_frame because map events can
6116                        numchars--;           come for sub-windows and they don't mean that the
6117                      }           frame is visible.  */
6118                    else if (! NILP (Vframe_list)        f = x_top_window_to_frame (dpyinfo, event.xmap.window);
6119                             && ! NILP (XCDR (Vframe_list)))        if (f)
6120                      /* Force a redisplay sooner or later          {
6121                         to update the frame titles            /* wait_reading_process_input will notice this and update
6122                         in case this is the second frame.  */               the frame's display structures.
6123                      record_asynch_buffer_change ();               If we where iconified, we should not set garbaged,
6124                  }               because that stops redrawing on Expose events.  This looks
6125                goto OTHER;               bad if we are called from a recursive event loop
6126                 (x_dispatch_event), for example when a dialog is up.  */
6127              if (! f->async_iconified)
6128                SET_FRAME_GARBAGED (f);
6129    
6130              f->async_visible = 1;
6131              f->async_iconified = 0;
6132              f->output_data.x->has_been_visible = 1;
6133    
6134              if (f->iconified)
6135                {
6136                  bufp->kind = DEICONIFY_EVENT;
6137                  XSETFRAME (bufp->frame_or_window, f);
6138                  bufp->arg = Qnil;
6139                  bufp++;
6140                  count++;
6141                  numchars--;
6142                }
6143              else if (! NILP (Vframe_list)
6144                       && ! NILP (XCDR (Vframe_list)))
6145                /* Force a redisplay sooner or later
6146                   to update the frame titles
6147                   in case this is the second frame.  */
6148                record_asynch_buffer_change ();
6149            }
6150          goto OTHER;
6151    
6152              case KeyPress:      case KeyPress:
6153    
6154                /* Dispatch KeyPress events when in menu.  */  #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6155                if (popup_activated_flag)        /* Dispatch KeyPress events when in menu.  */
6156                 goto OTHER;        if (popup_activated ())
6157            goto OTHER;
6158    #endif
6159    
6160                f = x_any_window_to_frame (dpyinfo, event.xkey.window);        f = x_any_window_to_frame (dpyinfo, event.xkey.window);
6161    
6162                if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))        if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
6163                  {          {
6164                    dpyinfo->mouse_face_hidden = 1;            dpyinfo->mouse_face_hidden = 1;
6165                    clear_mouse_face (dpyinfo);            clear_mouse_face (dpyinfo);
6166                  }          }
6167    
6168  #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS  #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
6169                if (f == 0)        if (f == 0)
6170                  {          {
6171                    /* Scroll bars consume key events, but we want            /* Scroll bars consume key events, but we want
6172                       the keys to go to the scroll bar's frame.  */               the keys to go to the scroll bar's frame.  */
6173                    Widget widget = XtWindowToWidget (dpyinfo->display,            Widget widget = XtWindowToWidget (dpyinfo->display,
6174                                                      event.xkey.window);                                              event.xkey.window);
6175                    if (widget && XmIsScrollBar (widget))            if (widget && XmIsScrollBar (widget))
6176                      {              {
6177                        widget = XtParent (widget);                widget = XtParent (widget);
6178                        f = x_any_window_to_frame (dpyinfo, XtWindow (widget));                f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
6179                      }              }
6180                  }          }
6181  #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */  #endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
6182    
6183                if (f != 0)        if (f != 0)
6184                  {          {
6185                    KeySym keysym, orig_keysym;            KeySym keysym, orig_keysym;
6186                    /* al%imercury@uunet.uu.net says that making this 81            /* al%imercury@uunet.uu.net says that making this 81
6187                       instead of 80 fixed a bug whereby meta chars made               instead of 80 fixed a bug whereby meta chars made
6188                       his Emacs hang.               his Emacs hang.
6189    
6190                       It seems that some version of XmbLookupString has               It seems that some version of XmbLookupString has
6191                       a bug of not returning XBufferOverflow in               a bug of not returning XBufferOverflow in
6192                       status_return even if the input is too long to               status_return even if the input is too long to
6193                       fit in 81 bytes.  So, we must prepare sufficient               fit in 81 bytes.  So, we must prepare sufficient
6194                       bytes for copy_buffer.  513 bytes (256 chars for               bytes for copy_buffer.  513 bytes (256 chars for
6195                       two-byte character set) seems to be a fairly good               two-byte character set) seems to be a fairly good
6196                       approximation.  -- 2000.8.10 handa@etl.go.jp  */               approximation.  -- 2000.8.10 handa@etl.go.jp  */
6197                    unsigned char copy_buffer[513];            unsigned char copy_buffer[513];
6198                    unsigned char *copy_bufptr = copy_buffer;            unsigned char *copy_bufptr = copy_buffer;
6199                    int copy_bufsiz = sizeof (copy_buffer);            int copy_bufsiz = sizeof (copy_buffer);
6200                    int modifiers;            int modifiers;
6201                    Lisp_Object coding_system = Qlatin_1;            Lisp_Object coding_system = Qlatin_1;
6202    
6203                    event.xkey.state            event.xkey.state
6204                      |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),              |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
6205                                                 extra_keyboard_modifiers);                                         extra_keyboard_modifiers);
6206                    modifiers = event.xkey.state;            modifiers = event.xkey.state;
6207    
6208                    /* This will have to go some day...  */            /* This will have to go some day...  */
6209    
6210                    /* make_lispy_event turns chars into control chars.            /* make_lispy_event turns chars into control chars.
6211                       Don't do it here because XLookupString is too eager.  */               Don't do it here because XLookupString is too eager.  */
6212                    event.xkey.state &= ~ControlMask;            event.xkey.state &= ~ControlMask;
6213                    event.xkey.state &= ~(dpyinfo->meta_mod_mask            event.xkey.state &= ~(dpyinfo->meta_mod_mask
6214                                          | dpyinfo->super_mod_mask                                  | dpyinfo->super_mod_mask
6215                                          | dpyinfo->hyper_mod_mask                                  | dpyinfo->hyper_mod_mask
6216                                          | dpyinfo->alt_mod_mask);                                  | dpyinfo->alt_mod_mask);
6217    
6218                    /* In case Meta is ComposeCharacter,            /* In case Meta is ComposeCharacter,
6219                       clear its status.  According to Markus Ehrnsperger               clear its status.  According to Markus Ehrnsperger
6220                       Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de               Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
6221                       this enables ComposeCharacter to work whether or               this enables ComposeCharacter to work whether or
6222                       not it is combined with Meta.  */               not it is combined with Meta.  */
6223                    if (modifiers & dpyinfo->meta_mod_mask)            if (modifiers & dpyinfo->meta_mod_mask)
6224                      bzero (&compose_status, sizeof (compose_status));              bzero (&compose_status, sizeof (compose_status));
6225    
6226  #ifdef HAVE_X_I18N  #ifdef HAVE_X_I18N
6227                    if (FRAME_XIC (f))            if (FRAME_XIC (f))
6228                      {              {
6229                        Status status_return;                Status status_return;
6230    
6231                        coding_system = Vlocale_coding_system;                coding_system = Vlocale_coding_system;
6232                        nbytes = XmbLookupString (FRAME_XIC (f),                nbytes = XmbLookupString (FRAME_XIC (f),
6233                                                  &event.xkey, copy_bufptr,                                          &event.xkey, copy_bufptr,
6234                                                  copy_bufsiz, &keysym,                                          copy_bufsiz, &keysym,
6235                                                  &status_return);                                          &status_return);
6236                        if (status_return == XBufferOverflow)                if (status_return == XBufferOverflow)
6237                          {                  {
6238                            copy_bufsiz = nbytes + 1;                    copy_bufsiz = nbytes + 1;
6239                            copy_bufptr = (char *) alloca (copy_bufsiz);                    copy_bufptr = (char *) alloca (copy_bufsiz);
6240                            nbytes = XmbLookupString (FRAME_XIC (f),                    nbytes = XmbLookupString (FRAME_XIC (f),
6241                                                      &event.xkey, copy_bufptr,                                              &event.xkey, copy_bufptr,
6242                                                      copy_bufsiz, &keysym,                                              copy_bufsiz, &keysym,
6243                                                      &status_return);                                              &status_return);
6244                          }                  }
6245  /* Xutf8LookupString is a new but already deprecated interface.  -stef  */                /* Xutf8LookupString is a new but already deprecated interface.  -stef  */
6246  #if 0 && defined X_HAVE_UTF8_STRING  #if 0 && defined X_HAVE_UTF8_STRING
6247                        else if (status_return == XLookupKeySym)                else if (status_return == XLookupKeySym)
6248                          {  /* Try again but with utf-8.  */                  {  /* Try again but with utf-8.  */
6249                            coding_system = Qutf_8;                    coding_system = Qutf_8;
6250                            nbytes = Xutf8LookupString (FRAME_XIC (f),                    nbytes = Xutf8LookupString (FRAME_XIC (f),
6251                                                        &event.xkey, copy_bufptr,                                                &event.xkey, copy_bufptr,
6252                                                        copy_bufsiz, &keysym,                                                copy_bufsiz, &keysym,
6253                                                        &status_return);                                                &status_return);
6254                            if (status_return == XBufferOverflow)                    if (status_return == XBufferOverflow)
6255                              {                      {
6256                                copy_bufsiz = nbytes + 1;                        copy_bufsiz = nbytes + 1;
6257                                copy_bufptr = (char *) alloca (copy_bufsiz);                        copy_bufptr = (char *) alloca (copy_bufsiz);
6258                                nbytes = Xutf8LookupString (FRAME_XIC (f),                        nbytes = Xutf8LookupString (FRAME_XIC (f),
6259                                                            &event.xkey,                                                    &event.xkey,
6260                                                            copy_bufptr,                                                    copy_bufptr,
6261                                                            copy_bufsiz, &keysym,                                                    copy_bufsiz, &keysym,
6262                                                            &status_return);                                                    &status_return);
6263                              }                      }
6264                          }                  }
6265  #endif  #endif
6266    
6267                        if (status_return == XLookupNone)                if (status_return == XLookupNone)
6268                          break;                  break;
6269                        else if (status_return == XLookupChars)                else if (status_return == XLookupChars)
6270                          {                  {
6271                            keysym = NoSymbol;                    keysym = NoSymbol;
6272                            modifiers = 0;                    modifiers = 0;
6273                          }                  }
6274                        else if (status_return != XLookupKeySym                else if (status_return != XLookupKeySym
6275                                 && status_return != XLookupBoth)                         && status_return != XLookupBoth)
6276                          abort ();                  abort ();
6277                      }              }
6278                    else            else
6279                      nbytes = XLookupString (&event.xkey, copy_bufptr,              nbytes = XLookupString (&event.xkey, copy_bufptr,
6280                                              copy_bufsiz, &keysym,                                      copy_bufsiz, &keysym,
6281                                              &compose_status);                                      &compose_status);
6282  #else  #else
6283                    nbytes = XLookupString (&event.xkey, copy_bufptr,            nbytes = XLookupString (&event.xkey, copy_bufptr,
6284                                            copy_bufsiz, &keysym,                                    copy_bufsiz, &keysym,
6285                                            &compose_status);                                    &compose_status);
6286  #endif  #endif
6287    
6288                    orig_keysym = keysym;            orig_keysym = keysym;
6289    
6290                    if (numchars > 1)            if (numchars > 1)
6291                      {              {
6292                        if (((keysym >= XK_BackSpace && keysym <= XK_Escape)                Lisp_Object c;
6293                             || keysym == XK_Delete  
6294                  /* First deal with keysyms which have defined
6295                     translations to characters.  */
6296                  if (keysym >= 32 && keysym < 128)
6297                    /* Avoid explicitly decoding each ASCII character.  */
6298                    {
6299                      bufp->kind = ASCII_KEYSTROKE_EVENT;
6300                      bufp->code = keysym;
6301                      XSETFRAME (bufp->frame_or_window, f);
6302                      bufp->arg = Qnil;
6303                      bufp->modifiers
6304                        = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6305                                                  modifiers);
6306                      bufp->timestamp = event.xkey.time;
6307                      bufp++;
6308                      count++;
6309                      numchars--;
6310                    }
6311                  /* Now non-ASCII.  */
6312                  else if (HASH_TABLE_P (Vx_keysym_table)
6313                           && (NATNUMP (c = Fgethash (make_number (keysym),
6314                                                      Vx_keysym_table,
6315                                                      Qnil))))
6316                    {
6317                      bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
6318                                    ? ASCII_KEYSTROKE_EVENT
6319                                    : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
6320                      bufp->code = XFASTINT (c);
6321                      XSETFRAME (bufp->frame_or_window, f);
6322                      bufp->arg = Qnil;
6323                      bufp->modifiers
6324                        = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6325                                                  modifiers);
6326                      bufp->timestamp = event.xkey.time;
6327                      bufp++;
6328                      count++;
6329                      numchars--;
6330                    }
6331                  /* Random non-modifier sorts of keysyms.  */
6332                  else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
6333                            || keysym == XK_Delete
6334  #ifdef XK_ISO_Left_Tab  #ifdef XK_ISO_Left_Tab
6335                             || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)                          || (keysym >= XK_ISO_Left_Tab
6336                                && keysym <= XK_ISO_Enter)
6337  #endif  #endif
6338                             || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)                          || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
6339                             || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */                          || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
                            || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */  
6340  #ifdef HPUX  #ifdef HPUX
6341                             /* This recognizes the "extended function keys".                          /* This recognizes the "extended function
6342                                It seems there's no cleaner way.                             keys".  It seems there's no cleaner way.
6343                                Test IsModifierKey to avoid handling mode_switch                             Test IsModifierKey to avoid handling
6344                                incorrectly.  */                             mode_switch incorrectly.  */
6345                             || ((unsigned) (keysym) >= XK_Select                          || ((unsigned) (keysym) >= XK_Select
6346                                 && (unsigned)(keysym) < XK_KP_Space)                              && (unsigned)(keysym) < XK_KP_Space)
6347  #endif  #endif
6348  #ifdef XK_dead_circumflex  #ifdef XK_dead_circumflex
6349                             || orig_keysym == XK_dead_circumflex                          || orig_keysym == XK_dead_circumflex
6350  #endif  #endif
6351  #ifdef XK_dead_grave  #ifdef XK_dead_grave
6352                             || orig_keysym == XK_dead_grave                          || orig_keysym == XK_dead_grave
6353  #endif  #endif
6354  #ifdef XK_dead_tilde  #ifdef XK_dead_tilde
6355                             || orig_keysym == XK_dead_tilde                          || orig_keysym == XK_dead_tilde
6356  #endif  #endif
6357  #ifdef XK_dead_diaeresis  #ifdef XK_dead_diaeresis
6358                             || orig_keysym == XK_dead_diaeresis                          || orig_keysym == XK_dead_diaeresis
6359  #endif  #endif
6360  #ifdef XK_dead_macron  #ifdef XK_dead_macron
6361                             || orig_keysym == XK_dead_macron                          || orig_keysym == XK_dead_macron
6362  #endif  #endif
6363  #ifdef XK_dead_degree  #ifdef XK_dead_degree
6364                             || orig_keysym == XK_dead_degree                          || orig_keysym == XK_dead_degree
6365  #endif  #endif
6366  #ifdef XK_dead_acute  #ifdef XK_dead_acute
6367                             || orig_keysym == XK_dead_acute                          || orig_keysym == XK_dead_acute
6368  #endif  #endif
6369  #ifdef XK_dead_cedilla  #ifdef XK_dead_cedilla
6370                             || orig_keysym == XK_dead_cedilla                          || orig_keysym == XK_dead_cedilla
6371  #endif  #endif
6372  #ifdef XK_dead_breve  #ifdef XK_dead_breve
6373                             || orig_keysym == XK_dead_breve                          || orig_keysym == XK_dead_breve
6374  #endif  #endif
6375  #ifdef XK_dead_ogonek  #ifdef XK_dead_ogonek
6376                             || orig_keysym == XK_dead_ogonek                          || orig_keysym == XK_dead_ogonek
6377  #endif  #endif
6378  #ifdef XK_dead_caron  #ifdef XK_dead_caron
6379                             || orig_keysym == XK_dead_caron                          || orig_keysym == XK_dead_caron
6380  #endif  #endif
6381  #ifdef XK_dead_doubleacute  #ifdef XK_dead_doubleacute
6382                             || orig_keysym == XK_dead_doubleacute                          || orig_keysym == XK_dead_doubleacute
6383  #endif  #endif
6384  #ifdef XK_dead_abovedot  #ifdef XK_dead_abovedot
6385                             || orig_keysym == XK_dead_abovedot                          || orig_keysym == XK_dead_abovedot
6386  #endif  #endif
6387                             || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */                          || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
6388                             || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */                          || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
6389                             /* Any "vendor-specific" key is ok.  */                          /* Any "vendor-specific" key is ok.  */
6390                             || (orig_keysym & (1 << 28))                          || (orig_keysym & (1 << 28))
6391                             || (keysym != NoSymbol && nbytes == 0))                          || (keysym != NoSymbol && nbytes == 0))
6392                            && ! (IsModifierKey (orig_keysym)                         && ! (IsModifierKey (orig_keysym)
6393  #ifndef HAVE_X11R5  #ifndef HAVE_X11R5
6394  #ifdef XK_Mode_switch  #ifdef XK_Mode_switch
6395                                  || ((unsigned)(orig_keysym) == XK_Mode_switch)                               || ((unsigned)(orig_keysym) == XK_Mode_switch)
6396  #endif  #endif
6397  #ifdef XK_Num_Lock  #ifdef XK_Num_Lock
6398                                  || ((unsigned)(orig_keysym) == XK_Num_Lock)                               || ((unsigned)(orig_keysym) == XK_Num_Lock)
6399  #endif  #endif
6400  #endif /* not HAVE_X11R5 */  #endif /* not HAVE_X11R5 */
6401                                  /* The symbols from XK_ISO_Lock to                               /* The symbols from XK_ISO_Lock
6402                                     XK_ISO_Last_Group_Lock doesn't have real                                  to XK_ISO_Last_Group_Lock
6403                                     modifiers but should be treated similarly                                  don't have real modifiers but
6404                                     to Mode_switch by Emacs. */                                  should be treated similarly to
6405                                    Mode_switch by Emacs. */
6406  #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock  #if defined XK_ISO_Lock && defined XK_ISO_Last_Group_Lock
6407                                  || ((unsigned)(orig_keysym) >=  XK_ISO_Lock                               || ((unsigned)(orig_keysym)
6408                                      && (unsigned)(orig_keysym) <= XK_ISO_Last_Group_Lock)                                   >=  XK_ISO_Lock
6409  #endif                                   && (unsigned)(orig_keysym)
6410                                  ))                                   <= XK_ISO_Last_Group_Lock)
6411                          {  #endif
6412                            if (temp_index == sizeof temp_buffer / sizeof (short))                               ))
6413                              temp_index = 0;                  {
6414                            temp_buffer[temp_index++] = keysym;                    if (temp_index == sizeof temp_buffer / sizeof (short))
6415                            bufp->kind = non_ascii_keystroke;                      temp_index = 0;
6416                            bufp->code = keysym;                    temp_buffer[temp_index++] = keysym;
6417                            XSETFRAME (bufp->frame_or_window, f);                    /* make_lispy_event will convert this to a symbolic
6418                            bufp->arg = Qnil;                       key.  */
6419                            bufp->modifiers                    bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
6420                              = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),                    bufp->code = keysym;
6421                                                        modifiers);                    XSETFRAME (bufp->frame_or_window, f);
6422                            bufp->timestamp = event.xkey.time;                    bufp->arg = Qnil;
6423                            bufp++;                    bufp->modifiers
6424                            count++;                      = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6425                            numchars--;                                                modifiers);
6426                          }                    bufp->timestamp = event.xkey.time;
6427                        else if (numchars > nbytes)                    bufp++;
6428                          {                    count++;
6429                            register int i;                    numchars--;
6430                            register int c;                  }
6431                            int nchars, len;                else if (numchars > nbytes)
6432                    {       /* Raw bytes, not keysym.  */
6433                            /* The input should be decoded with `coding_system'                    register int i;
6434                               which depends on which X*LookupString function                    register int c;
6435                               we used just above and the locale.  */                    int nchars, len;
6436                            setup_coding_system (coding_system, &coding);  
6437                            coding.src_multibyte = 0;                    /* The input should be decoded with `coding_system'
6438                            coding.dst_multibyte = 1;                       which depends on which X*LookupString function
6439                            /* The input is converted to events, thus we can't                       we used just above and the locale.  */
6440                               handle composition.  Anyway, there's no XIM that                    setup_coding_system (coding_system, &coding);
6441                               gives us composition information.  */                    coding.src_multibyte = 0;
6442                            coding.composing = COMPOSITION_DISABLED;                    coding.dst_multibyte = 1;
6443                      /* The input is converted to events, thus we can't
6444                            for (i = 0; i < nbytes; i++)                       handle composition.  Anyway, there's no XIM that
6445                              {                       gives us composition information.  */
6446                                if (temp_index == (sizeof temp_buffer                    coding.composing = COMPOSITION_DISABLED;
6447                                                   / sizeof (short)))  
6448                                  temp_index = 0;                    for (i = 0; i < nbytes; i++)
6449                                temp_buffer[temp_index++] = copy_bufptr[i];                      {
6450                              }                        if (temp_index == (sizeof temp_buffer
6451                                             / sizeof (short)))
6452                            {                          temp_index = 0;
6453                              /* Decode the input data.  */                        temp_buffer[temp_index++] = copy_bufptr[i];
6454                              int require;                      }
6455                              unsigned char *p;  
6456                      {
6457                              require = decoding_buffer_size (&coding, nbytes);                      /* Decode the input data.  */
6458                              p = (unsigned char *) alloca (require);                      int require;
6459                              coding.mode |= CODING_MODE_LAST_BLOCK;                      unsigned char *p;
6460                              decode_coding (&coding, copy_bufptr, p,  
6461                                             nbytes, require);                      require = decoding_buffer_size (&coding, nbytes);
6462                              nbytes = coding.produced;                      p = (unsigned char *) alloca (require);
6463                              nchars = coding.produced_char;                      coding.mode |= CODING_MODE_LAST_BLOCK;
6464                              copy_bufptr = p;                      /* We explicitely disable composition
6465                            }                         handling because key data should
6466                           not contain any composition
6467                            /* Convert the input data to a sequence of                         sequence.  */
6468                               character events.  */                      coding.composing = COMPOSITION_DISABLED;
6469                            for (i = 0; i < nbytes; i += len)                      decode_coding (&coding, copy_bufptr, p,
6470                              {                                     nbytes, require);
6471                                if (nchars == nbytes)                      nbytes = coding.produced;
6472                                  c = copy_bufptr[i], len = 1;                      nchars = coding.produced_char;
6473                                else                      copy_bufptr = p;
6474                                  c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,                    }
6475                                                              nbytes - i, len);  
6476                                                    /* Convert the input data to a sequence of
6477                                bufp->kind = (SINGLE_BYTE_CHAR_P (c)                       character events.  */
6478                                              ? ascii_keystroke                    for (i = 0; i < nbytes; i += len)
6479                                              : multibyte_char_keystroke);                      {
6480                                bufp->code = c;                        if (nchars == nbytes)
6481                                XSETFRAME (bufp->frame_or_window, f);                          c = copy_bufptr[i], len = 1;
6482                                bufp->arg = Qnil;                        else
6483                                bufp->modifiers                          c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
6484                                  = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),                                                      nbytes - i, len);
6485                                                            modifiers);  
6486                                bufp->timestamp = event.xkey.time;                        bufp->kind = (SINGLE_BYTE_CHAR_P (c)
6487                                bufp++;                                      ? ASCII_KEYSTROKE_EVENT
6488                              }                                      : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
6489                          bufp->code = c;
6490                            count += nchars;                        XSETFRAME (bufp->frame_or_window, f);
6491                            numchars -= nchars;                        bufp->arg = Qnil;
6492                          bufp->modifiers
6493                            if (keysym == NoSymbol)                          = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6494                              break;                                                    modifiers);
6495                          }                        bufp->timestamp = event.xkey.time;
6496                        else                        bufp++;
6497                          abort ();                      }
6498                      }  
6499                    else                    count += nchars;
6500                      abort ();                    numchars -= nchars;
6501                  }  
6502                      if (keysym == NoSymbol)
6503                        break;
6504                    }
6505                  else
6506                    abort ();
6507                }
6508              else
6509                abort ();
6510            }
6511  #ifdef HAVE_X_I18N  #ifdef HAVE_X_I18N
6512                /* Don't dispatch this event since XtDispatchEvent calls        /* Don't dispatch this event since XtDispatchEvent calls
6513                   XFilterEvent, and two calls in a row may freeze the           XFilterEvent, and two calls in a row may freeze the
6514                   client.  */           client.  */
6515                break;        break;
6516  #else  #else
6517                goto OTHER;        goto OTHER;
6518  #endif  #endif
6519    
6520              case KeyRelease:      case KeyRelease:
6521  #ifdef HAVE_X_I18N  #ifdef HAVE_X_I18N
6522                /* Don't dispatch this event since XtDispatchEvent calls        /* Don't dispatch this event since XtDispatchEvent calls
6523                   XFilterEvent, and two calls in a row may freeze the           XFilterEvent, and two calls in a row may freeze the
6524                   client.  */           client.  */
6525                break;        break;
6526  #else  #else
6527                goto OTHER;        goto OTHER;
6528  #endif  #endif
6529    
6530                /* Here's a possible interpretation of the whole      case EnterNotify:
6531                   FocusIn-EnterNotify FocusOut-LeaveNotify mess.  If        {
6532                   you get a FocusIn event, you have to get a FocusOut          int n;
                  event before you relinquish the focus.  If you  
                  haven't received a FocusIn event, then a mere  
                  LeaveNotify is enough to free you.  */  
6533    
6534              case EnterNotify:          n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
6535                {          if (n > 0)
6536                  f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);            {
6537                bufp += n, count += n, numchars -= n;
6538              }
6539    
6540            f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
6541    
6542  #if 0  #if 0
6543                  if (event.xcrossing.focus)          if (event.xcrossing.focus)
6544                    {            {
6545                      /* Avoid nasty pop/raise loops.  */              /* Avoid nasty pop/raise loops.  */
6546                      if (f && (!(f->auto_raise)              if (f && (!(f->auto_raise)
6547                                || !(f->auto_lower)                        || !(f->auto_lower)
6548                                || (event.xcrossing.time - enter_timestamp) > 500))                        || (event.xcrossing.time - enter_timestamp) > 500))
6549                        {                {
6550                          x_new_focus_frame (dpyinfo, f);                  x_new_focus_frame (dpyinfo, f);
6551                          enter_timestamp = event.xcrossing.time;                  enter_timestamp = event.xcrossing.time;
6552                        }                }
6553                    }            }
6554                  else if (f == dpyinfo->x_focus_frame)          else if (f == dpyinfo->x_focus_frame)
6555                    x_new_focus_frame (dpyinfo, 0);            x_new_focus_frame (dpyinfo, 0);
6556  #endif  #endif
6557    
6558            /* EnterNotify counts as mouse movement,
6559               so update things that depend on mouse position.  */
6560            if (f && !f->output_data.x->hourglass_p)
6561              note_mouse_movement (f, &event.xmotion);
6562            goto OTHER;
6563          }
6564    
6565                  /* EnterNotify counts as mouse movement,      case FocusIn:
6566                     so update things that depend on mouse position.  */        {
6567                  if (f && !f->output_data.x->hourglass_p)          int n;
                   note_mouse_movement (f, &event.xmotion);  
                 goto OTHER;  
               }  
6568    
6569              case FocusIn:          n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
6570                f = x_any_window_to_frame (dpyinfo, event.xfocus.window);          if (n > 0)
6571                if (event.xfocus.detail != NotifyPointer)            {
6572                  dpyinfo->x_focus_event_frame = f;              bufp += n, count += n, numchars -= n;
6573                if (f)            }
6574                  {        }
                   x_new_focus_frame (dpyinfo, f);  
6575    
6576                    /* Don't stop displaying the initial startup message        goto OTHER;
                      for a switch-frame event we don't need.  */  
                   if (GC_NILP (Vterminal_frame)  
                       && GC_CONSP (Vframe_list)  
                       && !GC_NILP (XCDR (Vframe_list)))  
                     {  
                       bufp->kind = FOCUS_IN_EVENT;  
                       XSETFRAME (bufp->frame_or_window, f);  
                       bufp->arg = Qnil;  
                       ++bufp, ++count, --numchars;  
                     }  
                 }  
6577    
6578  #ifdef HAVE_X_I18N      case LeaveNotify:
6579                if (f && FRAME_XIC (f))        {
6580                  XSetICFocus (FRAME_XIC (f));          int n;
 #endif  
6581    
6582                goto OTHER;          n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
6583            if (n > 0)
6584              {
6585                bufp += n, count += n, numchars -= n;
6586              }
6587          }
6588    
6589              case LeaveNotify:        f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
6590                f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);        if (f)
6591                if (f)          {
6592                  {            if (f == dpyinfo->mouse_face_mouse_frame)
6593                    if (f == dpyinfo->mouse_face_mouse_frame)              {
6594                      {                /* If we move outside the frame, then we're
6595                        /* If we move outside the frame, then we're                   certainly no longer on any text in the frame.  */
6596                           certainly no longer on any text in the frame.  */                clear_mouse_face (dpyinfo);
6597                        clear_mouse_face (dpyinfo);                dpyinfo->mouse_face_mouse_frame = 0;
6598                        dpyinfo->mouse_face_mouse_frame = 0;              }
6599                      }  
6600              /* Generate a nil HELP_EVENT to cancel a help-echo.
6601                 Do it only if there's something to cancel.
6602                 Otherwise, the startup message is cleared when
6603                 the mouse leaves the frame.  */
6604              if (any_help_event_p)
6605                {
6606                  Lisp_Object frame;
6607                  int n;
6608    
6609                  XSETFRAME (frame, f);
6610                  help_echo_string = Qnil;
6611                  n = gen_help_event (bufp, numchars,
6612                                      Qnil, frame, Qnil, Qnil, 0);
6613                  bufp += n, count += n, numchars -= n;
6614                }
6615    
6616                    /* Generate a nil HELP_EVENT to cancel a help-echo.          }
6617                       Do it only if there's something to cancel.        goto OTHER;
                      Otherwise, the startup message is cleared when  
                      the mouse leaves the frame.  */  
                   if (any_help_event_p)  
                     {  
                       Lisp_Object frame;  
                       int n;  
6618    
6619                        XSETFRAME (frame, f);      case FocusOut:
6620                        help_echo = Qnil;        {
6621                        n = gen_help_event (bufp, numchars,          int n;
                                           Qnil, frame, Qnil, Qnil, 0);  
                       bufp += n, count += n, numchars -= n;  
                     }  
6622    
6623  #if 0          n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
6624                    if (event.xcrossing.focus)          if (n > 0)
6625                      x_mouse_leave (dpyinfo);            {
6626                    else              bufp += n, count += n, numchars -= n;
6627                      {            }
6628                        if (f == dpyinfo->x_focus_event_frame)        }
6629                          dpyinfo->x_focus_event_frame = 0;  
6630                        if (f == dpyinfo->x_focus_frame)        goto OTHER;
6631                          x_new_focus_frame (dpyinfo, 0);  
6632                      }      case MotionNotify:
6633  #endif        {
6634                  }          previous_help_echo_string = help_echo_string;
6635                goto OTHER;          help_echo_string = help_echo_object = help_echo_window = Qnil;
6636            help_echo_pos = -1;
6637    
6638            if (dpyinfo->grabbed && last_mouse_frame
6639                && FRAME_LIVE_P (last_mouse_frame))
6640              f = last_mouse_frame;
6641            else
6642              f = x_window_to_frame (dpyinfo, event.xmotion.window);
6643    
6644            if (dpyinfo->mouse_face_hidden)
6645              {
6646                dpyinfo->mouse_face_hidden = 0;
6647                clear_mouse_face (dpyinfo);
6648              }
6649    
6650            if (f)
6651              {
6652    
6653                /* Generate SELECT_WINDOW_EVENTs when needed.  */
6654                if (mouse_autoselect_window)
6655                  {
6656                    Lisp_Object window;
6657    
6658                    window = window_from_coordinates (f,
6659                                                      event.xmotion.x, event.xmotion.y,
6660                                                      0, 0);
6661    
6662                    /* Window will be selected only when it is not selected now and
6663                       last mouse movement event was not in it.  Minibuffer window
6664                       will be selected iff it is active.  */
6665                    if (WINDOWP(window)
6666                        && !EQ (window, last_window)
6667                        && !EQ (window, selected_window)
6668                        && numchars > 0)
6669                      {
6670                        bufp->kind = SELECT_WINDOW_EVENT;
6671                        bufp->frame_or_window = window;
6672                        bufp->arg = Qnil;
6673                        ++bufp, ++count, --numchars;
6674                      }
6675    
6676                    last_window=window;
6677                  }
6678                note_mouse_movement (f, &event.xmotion);
6679              }
6680            else
6681              {
6682    #ifndef USE_TOOLKIT_SCROLL_BARS
6683                struct scroll_bar *bar
6684                  = x_window_to_scroll_bar (event.xmotion.window);
6685    
6686              case FocusOut:              if (bar)
6687                f = x_any_window_to_frame (dpyinfo, event.xfocus.window);                x_scroll_bar_note_movement (bar, &event);
6688                if (event.xfocus.detail != NotifyPointer  #endif /* USE_TOOLKIT_SCROLL_BARS */
6689                    && f == dpyinfo->x_focus_event_frame)  
6690                  dpyinfo->x_focus_event_frame = 0;              /* If we move outside the frame, then we're
6691                if (f && f == dpyinfo->x_focus_frame)                 certainly no longer on any text in the frame.  */
6692                  x_new_focus_frame (dpyinfo, 0);              clear_mouse_face (dpyinfo);
6693              }
6694    
6695            /* If the contents of the global variable help_echo_string
6696               has changed, generate a HELP_EVENT.  */
6697            if (!NILP (help_echo_string)
6698                || !NILP (previous_help_echo_string))
6699              {
6700                Lisp_Object frame;
6701                int n;
6702    
6703                if (f)
6704                  XSETFRAME (frame, f);
6705                else
6706                  frame = Qnil;
6707    
6708                any_help_event_p = 1;
6709                n = gen_help_event (bufp, numchars, help_echo_string, frame,
6710                                    help_echo_window, help_echo_object,
6711                                    help_echo_pos);
6712                bufp += n, count += n, numchars -= n;
6713              }
6714    
6715            goto OTHER;
6716          }
6717    
6718        case ConfigureNotify:
6719          f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
6720          if (f)
6721            {
6722    #ifndef USE_X_TOOLKIT
6723    #ifdef USE_GTK
6724              xg_resize_widgets (f, event.xconfigure.width,
6725                                 event.xconfigure.height);
6726    #else /* not USE_GTK */
6727              /* If there is a pending resize for fullscreen, don't
6728                 do this one, the right one will come later.
6729                 The toolkit version doesn't seem to need this, but we
6730                 need to reset it below.  */
6731              int dont_resize =
6732                ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
6733                 && FRAME_NEW_WIDTH (f) != 0);
6734              int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
6735              int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
6736              if (dont_resize)
6737                goto OTHER;
6738    
6739              /* In the toolkit version, change_frame_size
6740                 is called by the code that handles resizing
6741                 of the EmacsFrame widget.  */
6742    
6743              /* Even if the number of character rows and columns has
6744                 not changed, the font size may have changed, so we need
6745                 to check the pixel dimensions as well.  */
6746              if (columns != f->width
6747                  || rows != f->height
6748                  || event.xconfigure.width != f->output_data.x->pixel_width
6749                  || event.xconfigure.height != f->output_data.x->pixel_height)
6750                {
6751                  change_frame_size (f, rows, columns, 0, 1, 0);
6752                  SET_FRAME_GARBAGED (f);
6753                  cancel_mouse_face (f);
6754                }
6755    #endif /* not USE_GTK */
6756    #endif
6757    
6758              f->output_data.x->pixel_width = event.xconfigure.width;
6759              f->output_data.x->pixel_height = event.xconfigure.height;
6760    
6761    #ifdef USE_GTK
6762              /* GTK creates windows but doesn't map them.
6763                 Only get real positions and check fullscreen when mapped. */
6764              if (FRAME_GTK_OUTER_WIDGET (f)
6765                  && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f)))
6766                {
6767    #endif
6768              /* What we have now is the position of Emacs's own window.
6769                 Convert that to the position of the window manager window.  */
6770              x_real_positions (f, &f->output_data.x->left_pos,
6771                                &f->output_data.x->top_pos);
6772    
6773              x_check_fullscreen_move (f);
6774              if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
6775                f->output_data.x->want_fullscreen &=
6776                  ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
6777    #ifdef USE_GTK
6778                }
6779    #endif
6780  #ifdef HAVE_X_I18N  #ifdef HAVE_X_I18N
6781                if (f && FRAME_XIC (f))            if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
6782                  XUnsetICFocus (FRAME_XIC (f));              xic_set_statusarea (f);
6783  #endif  #endif
6784    
6785                goto OTHER;            if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
6786                {
6787                  /* Since the WM decorations come below top_pos now,
6788                     we must put them below top_pos in the future.  */
6789                  f->output_data.x->win_gravity = NorthWestGravity;
6790                  x_wm_set_size_hint (f, (long) 0, 0);
6791                }
6792            }
6793          goto OTHER;
6794    
6795              case MotionNotify:      case ButtonRelease:
6796                {      case ButtonPress:
6797                  previous_help_echo = help_echo;        {
6798                  help_echo = help_echo_object = help_echo_window = Qnil;          /* If we decide we want to generate an event to be seen
6799                  help_echo_pos = -1;             by the rest of Emacs, we put it here.  */
6800                            struct input_event emacs_event;
6801                  if (dpyinfo->grabbed && last_mouse_frame          int tool_bar_p = 0;
6802                      && FRAME_LIVE_P (last_mouse_frame))  
6803                    f = last_mouse_frame;          emacs_event.kind = NO_EVENT;
6804                  else          bzero (&compose_status, sizeof (compose_status));
6805                    f = x_window_to_frame (dpyinfo, event.xmotion.window);  
6806            if (dpyinfo->grabbed
6807                && last_mouse_frame
6808                && FRAME_LIVE_P (last_mouse_frame))
6809              f = last_mouse_frame;
6810            else
6811              f = x_window_to_frame (dpyinfo, event.xbutton.window);
6812    
6813            if (f)
6814              {
6815                /* Is this in the tool-bar?  */
6816                if (WINDOWP (f->tool_bar_window)
6817                    && XFASTINT (XWINDOW (f->tool_bar_window)->height))
6818                  {
6819                    Lisp_Object window;
6820                    int x = event.xbutton.x;
6821                    int y = event.xbutton.y;
6822    
6823                    window = window_from_coordinates (f, x, y, 0, 1);
6824                    if (EQ (window, f->tool_bar_window))
6825                      {
6826                        if (event.xbutton.type == ButtonPress)
6827                          handle_tool_bar_click (f, x, y, 1, 0);
6828                        else
6829                          handle_tool_bar_click (f, x, y, 0,
6830                                                 x_x_to_emacs_modifiers (dpyinfo,
6831                                                                         event.xbutton.state));
6832                        tool_bar_p = 1;
6833                      }
6834                  }
6835    
6836                if (!tool_bar_p)
6837                  if (!dpyinfo->x_focus_frame
6838                      || f == dpyinfo->x_focus_frame)
6839                    {
6840    #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6841                      if (! popup_activated ())
6842    #endif
6843                        construct_mouse_click (&emacs_event, &event, f);
6844                    }
6845              }
6846            else
6847              {
6848                struct scroll_bar *bar
6849                  = x_window_to_scroll_bar (event.xbutton.window);
6850    
6851                  if (dpyinfo->mouse_face_hidden)  #ifdef USE_TOOLKIT_SCROLL_BARS
6852                    {              /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
6853                      dpyinfo->mouse_face_hidden = 0;                 scroll bars.  */
6854                      clear_mouse_face (dpyinfo);              if (bar && event.xbutton.state & ControlMask)
6855                    }                {
6856                    x_scroll_bar_handle_click (bar, &event, &emacs_event);
6857                    *finish = X_EVENT_DROP;
6858                  }
6859    #else /* not USE_TOOLKIT_SCROLL_BARS */
6860                if (bar)
6861                  x_scroll_bar_handle_click (bar, &event, &emacs_event);
6862    #endif /* not USE_TOOLKIT_SCROLL_BARS */
6863              }
6864    
6865                  if (f)          if (event.type == ButtonPress)
6866                    {            {
6867                dpyinfo->grabbed |= (1 << event.xbutton.button);
6868                last_mouse_frame = f;
6869                /* Ignore any mouse motion that happened
6870                   before this event; any subsequent mouse-movement
6871                   Emacs events should reflect only motion after
6872                   the ButtonPress.  */
6873                if (f != 0)
6874                  f->mouse_moved = 0;
6875    
6876                if (!tool_bar_p)
6877                  last_tool_bar_item = -1;
6878              }
6879            else
6880              dpyinfo->grabbed &= ~(1 << event.xbutton.button);
6881    
6882            if (numchars >= 1 && emacs_event.kind != NO_EVENT)
6883              {
6884                bcopy (&emacs_event, bufp, sizeof (struct input_event));
6885                bufp++;
6886                count++;
6887                numchars--;
6888              }
6889    
6890    #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
6891            f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
6892            /* For a down-event in the menu bar,
6893               don't pass it to Xt right now.
6894               Instead, save it away
6895               and we will pass it to Xt from kbd_buffer_get_event.
6896               That way, we can run some Lisp code first.  */
6897            if (
6898    #ifdef USE_GTK
6899                ! popup_activated ()
6900                &&
6901    #endif
6902                f && event.type == ButtonPress
6903                /* Verify the event is really within the menu bar
6904                   and not just sent to it due to grabbing.  */
6905                && event.xbutton.x >= 0
6906                && event.xbutton.x < f->output_data.x->pixel_width
6907                && event.xbutton.y >= 0
6908                && event.xbutton.y < f->output_data.x->menubar_height
6909                && event.xbutton.same_screen)
6910              {
6911                SET_SAVED_BUTTON_EVENT;
6912                XSETFRAME (last_mouse_press_frame, f);
6913    #ifdef USE_GTK
6914                *finish = X_EVENT_DROP;
6915    #endif
6916              }
6917            else if (event.type == ButtonPress)
6918              {
6919                last_mouse_press_frame = Qnil;
6920                goto OTHER;
6921              }
6922    
6923                      /* Generate SELECT_WINDOW_EVENTs when needed.  */  #ifdef USE_MOTIF /* This should do not harm for Lucid,
6924                      if (mouse_autoselect_window)                      but I am trying to be cautious.  */
6925                        {          else if (event.type == ButtonRelease)
6926                          Lisp_Object window;            {
6927                          int area;              if (!NILP (last_mouse_press_frame))
6928                  {
6929                          window = window_from_coordinates (f,                  f = XFRAME (last_mouse_press_frame);
6930                                                            event.xmotion.x, event.xmotion.y,                  if (f->output_data.x)
6931                                                            &area, 0);                    SET_SAVED_BUTTON_EVENT;
6932                  }
6933                          /* Window will be selected only when it is not selected now and              else
6934                             last mouse movement event was not in it.  Minibuffer window                goto OTHER;
6935                             will be selected iff it is active.  */            }
6936                          if (WINDOWP(window)  #endif /* USE_MOTIF */
6937                              && !EQ (window, last_window)          else
6938                              && !EQ (window, selected_window)            goto OTHER;
6939                              && numchars > 0)  #endif /* USE_X_TOOLKIT || USE_GTK */
6940                            {        }
6941                              bufp->kind = SELECT_WINDOW_EVENT;        break;
                             bufp->frame_or_window = window;  
                             bufp->arg = Qnil;  
                             ++bufp, ++count, --numchars;  
                           }  
   
                         last_window=window;  
                       }  
                     note_mouse_movement (f, &event.xmotion);  
                   }  
                 else  
                   {  
 #ifndef USE_TOOLKIT_SCROLL_BARS  
                     struct scroll_bar *bar  
                       = x_window_to_scroll_bar (event.xmotion.window);  
6942    
6943                      if (bar)      case CirculateNotify:
6944                        x_scroll_bar_note_movement (bar, &event);        goto OTHER;
 #endif /* USE_TOOLKIT_SCROLL_BARS */  
6945    
6946                      /* If we move outside the frame, then we're      case CirculateRequest:
6947                         certainly no longer on any text in the frame.  */        goto OTHER;
                     clear_mouse_face (dpyinfo);  
                   }  
6948    
6949                  /* If the contents of the global variable help_echo      case VisibilityNotify:
6950                     has changed, generate a HELP_EVENT.  */        goto OTHER;
                 if (!NILP (help_echo)  
                     || !NILP (previous_help_echo))  
                   {  
                     Lisp_Object frame;  
                     int n;  
6951    
6952                      if (f)      case MappingNotify:
6953                        XSETFRAME (frame, f);        /* Someone has changed the keyboard mapping - update the
6954                      else           local cache.  */
6955                        frame = Qnil;        switch (event.xmapping.request)
6956            {
6957            case MappingModifier:
6958              x_find_modifier_meanings (dpyinfo);
6959              /* This is meant to fall through.  */
6960            case MappingKeyboard:
6961              XRefreshKeyboardMapping (&event.xmapping);
6962            }
6963          goto OTHER;
6964    
6965                      any_help_event_p = 1;      default:
6966                      n = gen_help_event (bufp, numchars, help_echo, frame,      OTHER:
6967                                          help_echo_window, help_echo_object,  #ifdef USE_X_TOOLKIT
6968                                          help_echo_pos);      BLOCK_INPUT;
6969                      bufp += n, count += n, numchars -= n;      if (*finish != X_EVENT_DROP)
6970                    }        XtDispatchEvent (&event);
6971                        UNBLOCK_INPUT;
6972                  goto OTHER;  #endif /* USE_X_TOOLKIT */
6973                }      break;
6974        }
6975    
6976              case ConfigureNotify:    goto ret;
               f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);  
               if (f)  
                 {  
 #ifndef USE_X_TOOLKIT  
                   /* If there is a pending resize for fullscreen, don't  
                      do this one, the right one will come later.  
                      The toolkit version doesn't seem to need this, but we  
                      need to reset it below.  */  
                   int dont_resize =  
                     ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)  
                      && FRAME_NEW_WIDTH (f) != 0);  
                   int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);  
                   int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);  
                   if (dont_resize)  
                     goto OTHER;  
                     
                   /* In the toolkit version, change_frame_size  
                      is called by the code that handles resizing  
                      of the EmacsFrame widget.  */  
   
                   /* Even if the number of character rows and columns has  
                      not changed, the font size may have changed, so we need  
                      to check the pixel dimensions as well.  */  
                   if (columns != f->width  
                       || rows != f->height  
                       || event.xconfigure.width != f->output_data.x->pixel_width  
                       || event.xconfigure.height != f->output_data.x->pixel_height)  
                     {  
                       change_frame_size (f, rows, columns, 0, 1, 0);  
                       SET_FRAME_GARBAGED (f);  
                       cancel_mouse_face (f);  
                     }  
 #endif  
6977    
6978                    f->output_data.x->pixel_width = event.xconfigure.width;   out:
6979                    f->output_data.x->pixel_height = event.xconfigure.height;    *finish = X_EVENT_GOTO_OUT;
6980    
6981                    /* What we have now is the position of Emacs's own window.   ret:
6982                       Convert that to the position of the window manager window.  */    *bufp_r = bufp;
6983                    x_real_positions (f, &f->output_data.x->left_pos,    *numcharsp = numchars;
6984                                      &f->output_data.x->top_pos);    *eventp = event;
   
                   x_check_fullscreen_move(f);  
                   if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)  
                     f->output_data.x->want_fullscreen &=  
                       ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);  
 #ifdef HAVE_X_I18N  
                   if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))  
                     xic_set_statusarea (f);  
 #endif  
6985    
6986                    if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)    return count;
6987                      {  }
                       /* Since the WM decorations come below top_pos now,  
                          we must put them below top_pos in the future.  */  
                       f->output_data.x->win_gravity = NorthWestGravity;  
                       x_wm_set_size_hint (f, (long) 0, 0);  
                     }  
 #ifdef USE_MOTIF  
                   /* Some window managers pass (0,0) as the location of  
                      the window, and the Motif event handler stores it  
                      in the emacs widget, which messes up Motif menus.  */  
                   if (event.xconfigure.x == 0 && event.xconfigure.y == 0)  
                     {  
                       event.xconfigure.x = f->output_data.x->widget->core.x;  
                       event.xconfigure.y = f->output_data.x->widget->core.y;  
                     }  
 #endif /* USE_MOTIF */  
                 }  
               goto OTHER;  
6988    
             case ButtonPress:  
             case ButtonRelease:  
               {  
                 /* If we decide we want to generate an event to be seen  
                    by the rest of Emacs, we put it here.  */  
                 struct input_event emacs_event;  
                 int tool_bar_p = 0;  
                   
                 emacs_event.kind = no_event;  
                 bzero (&compose_status, sizeof (compose_status));  
   
                 if (dpyinfo->grabbed  
                     && last_mouse_frame  
                     && FRAME_LIVE_P (last_mouse_frame))  
                   f = last_mouse_frame;  
                 else  
                   f = x_window_to_frame (dpyinfo, event.xbutton.window);  
6989    
6990                  if (f)  /* Handles the XEvent EVENT on display DISPLAY.
6991                    {     This is used for event loops outside the normal event handling,
6992                      /* Is this in the tool-bar?  */     i.e. looping while a popup menu or a dialog is posted.
                     if (WINDOWP (f->tool_bar_window)  
                         && XFASTINT (XWINDOW (f->tool_bar_window)->height))  
                       {  
                         Lisp_Object window;  
                         int p, x, y;  
   
                         x = event.xbutton.x;  
                         y = event.xbutton.y;  
   
                         /* Set x and y.  */  
                         window = window_from_coordinates (f, x, y, &p, 1);  
                         if (EQ (window, f->tool_bar_window))  
                           {  
                             x_handle_tool_bar_click (f, &event.xbutton);  
                             tool_bar_p = 1;  
                           }  
                       }  
   
                     if (!tool_bar_p)  
                       if (!dpyinfo->x_focus_frame  
                           || f == dpyinfo->x_focus_frame)  
                         construct_mouse_click (&emacs_event, &event, f);  
                   }  
                 else  
                   {  
 #ifndef USE_TOOLKIT_SCROLL_BARS  
                     struct scroll_bar *bar  
                       = x_window_to_scroll_bar (event.xbutton.window);  
6993    
6994                      if (bar)     Returns the value handle_one_xevent sets in the finish argument.  */
6995                        x_scroll_bar_handle_click (bar, &event, &emacs_event);  int
6996  #endif /* not USE_TOOLKIT_SCROLL_BARS */  x_dispatch_event (event, display)
6997                    }       XEvent *event;
6998         Display *display;
6999    {
7000      struct x_display_info *dpyinfo;
7001      struct input_event bufp[10];
7002      struct input_event *bufpp = bufp;
7003      int numchars = 10;
7004      int finish = X_EVENT_NORMAL;
7005    
7006                  if (event.type == ButtonPress)    for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
7007                    {      if (dpyinfo->display == display)
7008                      dpyinfo->grabbed |= (1 << event.xbutton.button);        break;
                     last_mouse_frame = f;  
                     /* Ignore any mouse motion that happened  
                        before this event; any subsequent mouse-movement  
                        Emacs events should reflect only motion after  
                        the ButtonPress.  */  
                     if (f != 0)  
                       f->mouse_moved = 0;  
                       
                     if (!tool_bar_p)  
                       last_tool_bar_item = -1;  
                   }  
                 else  
                   {  
                     dpyinfo->grabbed &= ~(1 << event.xbutton.button);  
                   }  
7009    
7010                  if (numchars >= 1 && emacs_event.kind != no_event)    if (dpyinfo)
7011                    {      {
7012                      bcopy (&emacs_event, bufp, sizeof (struct input_event));        int i, events;
7013                      bufp++;        events = handle_one_xevent (dpyinfo,
7014                      count++;                                    event,
7015                      numchars--;                                    &bufpp,
7016                    }                                    &numchars,
7017                                      &finish);
7018          for (i = 0; i < events; ++i)
7019            kbd_buffer_store_event (&bufp[i]);
7020        }
7021    
7022  #ifdef USE_X_TOOLKIT    return finish;
7023                  f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);  }
                 /* For a down-event in the menu bar,  
                    don't pass it to Xt right now.  
                    Instead, save it away  
                    and we will pass it to Xt from kbd_buffer_get_event.  
                    That way, we can run some Lisp code first.  */  
                 if (f && event.type == ButtonPress  
                     /* Verify the event is really within the menu bar  
                        and not just sent to it due to grabbing.  */  
                     && event.xbutton.x >= 0  
                     && event.xbutton.x < f->output_data.x->pixel_width  
                     && event.xbutton.y >= 0  
                     && event.xbutton.y < f->output_data.x->menubar_height  
                     && event.xbutton.same_screen)  
                   {  
                     SET_SAVED_BUTTON_EVENT;  
                     XSETFRAME (last_mouse_press_frame, f);  
                   }  
                 else if (event.type == ButtonPress)  
                   {  
                     last_mouse_press_frame = Qnil;  
                     goto OTHER;  
                   }  
7024    
 #ifdef USE_MOTIF /* This should do not harm for Lucid,  
                     but I am trying to be cautious.  */  
                 else if (event.type == ButtonRelease)  
                   {  
                     if (!NILP (last_mouse_press_frame))  
                       {  
                         f = XFRAME (last_mouse_press_frame);  
                         if (f->output_data.x)  
                           SET_SAVED_BUTTON_EVENT;  
                       }  
                     else  
                       goto OTHER;  
                   }  
 #endif /* USE_MOTIF */  
                 else  
                   goto OTHER;  
 #endif /* USE_X_TOOLKIT */  
               }  
               break;  
7025    
7026              case CirculateNotify:  /* Read events coming from the X server.
7027                goto OTHER;     This routine is called by the SIGIO handler.
7028                     We return as soon as there are no more events to be read.
             case CirculateRequest:  
               goto OTHER;  
   
             case VisibilityNotify:  
               goto OTHER;  
   
             case MappingNotify:  
               /* Someone has changed the keyboard mapping - update the  
                  local cache.  */  
               switch (event.xmapping.request)  
                 {  
                 case MappingModifier:  
                   x_find_modifier_meanings (dpyinfo);  
                   /* This is meant to fall through.  */  
                 case MappingKeyboard:  
                   XRefreshKeyboardMapping (&event.xmapping);  
                 }  
               goto OTHER;  
7029    
7030              default:     Events representing keys are stored in buffer BUFP,
7031              OTHER:     which can hold up to NUMCHARS characters.
7032  #ifdef USE_X_TOOLKIT     We return the number of characters stored into the buffer,
7033                BLOCK_INPUT;     thus pretending to be `read'.
7034                XtDispatchEvent (&event);  
7035                UNBLOCK_INPUT;     EXPECTED is nonzero if the caller knows input is available.  */
7036  #endif /* USE_X_TOOLKIT */  
7037                break;  static int
7038              }  XTread_socket (sd, bufp, numchars, expected)
7039         register int sd;
7040         /* register */ struct input_event *bufp;
7041         /* register */ int numchars;
7042         int expected;
7043    {
7044      int count = 0;
7045      XEvent event;
7046      int event_found = 0;
7047      struct x_display_info *dpyinfo;
7048    
7049      if (interrupt_input_blocked)
7050        {
7051          interrupt_input_pending = 1;
7052          return -1;
7053        }
7054    
7055      interrupt_input_pending = 0;
7056      BLOCK_INPUT;
7057    
7058      /* So people can tell when we have read the available input.  */
7059      input_signal_count++;
7060    
7061      if (numchars <= 0)
7062        abort ();                   /* Don't think this happens.  */
7063    
7064      ++handling_signal;
7065    
7066      /* Find the display we are supposed to read input for.
7067         It's the one communicating on descriptor SD.  */
7068      for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
7069        {
7070    #if 0 /* This ought to be unnecessary; let's verify it.  */
7071    #ifdef FIOSNBIO
7072          /* If available, Xlib uses FIOSNBIO to make the socket
7073             non-blocking, and then looks for EWOULDBLOCK.  If O_NDELAY is set,
7074             FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
7075             a read returns 0, which Xlib interprets as equivalent to EPIPE.  */
7076          fcntl (dpyinfo->connection, F_SETFL, 0);
7077    #endif /* ! defined (FIOSNBIO) */
7078    #endif
7079    
7080    #if 0 /* This code can't be made to work, with multiple displays,
7081             and appears not to be used on any system any more.
7082             Also keyboard.c doesn't turn O_NDELAY on and off
7083             for X connections.  */
7084    #ifndef SIGIO
7085    #ifndef HAVE_SELECT
7086          if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
7087            {
7088              extern int read_alarm_should_throw;
7089              read_alarm_should_throw = 1;
7090              XPeekEvent (dpyinfo->display, &event);
7091              read_alarm_should_throw = 0;
7092            }
7093    #endif /* HAVE_SELECT */
7094    #endif /* SIGIO */
7095    #endif
7096    
7097          /* For debugging, this gives a way to fake an I/O error.  */
7098          if (dpyinfo == XTread_socket_fake_io_error)
7099            {
7100              XTread_socket_fake_io_error = 0;
7101              x_io_error_quitter (dpyinfo->display);
7102          }          }
7103    
7104    #ifdef HAVE_X_SM
7105          BLOCK_INPUT;
7106          count += x_session_check_input (bufp, &numchars);
7107          UNBLOCK_INPUT;
7108    #endif
7109    
7110    #ifdef USE_GTK
7111          /* For GTK we must use the GTK event loop.  But XEvents gets passed
7112             to our filter function above, and then to the big event switch.
7113             We use a bunch of globals to communicate with our filter function,
7114             that is kind of ugly, but it works. */
7115          current_dpyinfo = dpyinfo;
7116    
7117          while (gtk_events_pending ())
7118            {
7119              static int nr = 0;
7120              current_count = count;
7121              current_numcharsp = &numchars;
7122              current_bufp = &bufp;
7123    
7124              gtk_main_iteration ();
7125    
7126              count = current_count;
7127              current_bufp = 0;
7128              current_numcharsp = 0;
7129    
7130              if (current_finish == X_EVENT_GOTO_OUT)
7131                goto out;
7132            }
7133    
7134    #else /* not USE_GTK */
7135          while (XPending (dpyinfo->display))
7136            {
7137              int finish;
7138    
7139              XNextEvent (dpyinfo->display, &event);
7140    
7141    #ifdef HAVE_X_I18N
7142              /* Filter events for the current X input method.  */
7143              if (x_filter_event (dpyinfo, &event))
7144                break;
7145    #endif
7146              event_found = 1;
7147    
7148              count += handle_one_xevent (dpyinfo,
7149                                          &event,
7150                                          &bufp,
7151                                          &numchars,
7152                                          &finish);
7153    
7154              if (finish == X_EVENT_GOTO_OUT)
7155                goto out;
7156            }
7157    #endif /* USE_GTK */
7158      }      }
7159    
7160   out:;   out:;
# Line 11230  XTread_socket (sd, bufp, numchars, expec Line 7202  XTread_socket (sd, bufp, numchars, expec
7202                               Text Cursor                               Text Cursor
7203   ***********************************************************************/   ***********************************************************************/
7204    
 /* Notice when the text cursor of window W has been completely  
    overwritten by a drawing operation that outputs glyphs in AREA  
    starting at X0 and ending at X1 in the line starting at Y0 and  
    ending at Y1.  X coordinates are area-relative.  X1 < 0 means all  
    the rest of the line after X0 has been written.  Y coordinates  
    are window-relative.  */  
   
 static void  
 notice_overwritten_cursor (w, area, x0, x1, y0, y1)  
      struct window *w;  
      enum glyph_row_area area;  
      int x0, y0, x1, y1;  
 {  
   if (area == TEXT_AREA && w->phys_cursor_on_p)  
     {  
       int cx0 = w->phys_cursor.x;  
       int cx1 = cx0 + w->phys_cursor_width;  
       int cy0 = w->phys_cursor.y;  
       int cy1 = cy0 + w->phys_cursor_height;  
   
       if (x0 <= cx0 && (x1 < 0 || x1 >= cx1))  
         {  
           /* The cursor image will be completely removed from the  
              screen if the output area intersects the cursor area in  
              y-direction.  When we draw in [y0 y1[, and some part of  
              the cursor is at y < y0, that part must have been drawn  
              before.  When scrolling, the cursor is erased before  
              actually scrolling, so we don't come here.  When not  
              scrolling, the rows above the old cursor row must have  
              changed, and in this case these rows must have written  
              over the cursor image.  
   
              Likewise if part of the cursor is below y1, with the  
              exception of the cursor being in the first blank row at  
              the buffer and window end because update_text_area  
              doesn't draw that row.  (Except when it does, but  
              that's handled in update_text_area.)  */  
             
           if (((y0 >= cy0 && y0 < cy1) || (y1 > cy0 && y1 < cy1))  
               && w->current_matrix->rows[w->phys_cursor.vpos].displays_text_p)  
             w->phys_cursor_on_p = 0;  
         }  
     }  
 }  
   
   
7205  /* Set clipping for output in glyph row ROW.  W is the window in which  /* Set clipping for output in glyph row ROW.  W is the window in which
7206     we operate.  GC is the graphics context to set clipping in.     we operate.  GC is the graphics context to set clipping in.
7207     WHOLE_LINE_P non-zero means include the areas used for truncation     WHOLE_LINE_P non-zero means include the areas used for truncation
# Line 11353  x_draw_hollow_cursor (w, row) Line 7279  x_draw_hollow_cursor (w, row)
7279        && !x_stretch_cursor_p)        && !x_stretch_cursor_p)
7280      wd = min (CANON_X_UNIT (f), wd);      wd = min (CANON_X_UNIT (f), wd);
7281    w->phys_cursor_width = wd;    w->phys_cursor_width = wd;
7282      
7283    /* The foreground of cursor_gc is typically the same as the normal    /* The foreground of cursor_gc is typically the same as the normal
7284       background color, which can cause the cursor box to be invisible.  */       background color, which can cause the cursor box to be invisible.  */
7285    xgcv.foreground = f->output_data.x->cursor_pixel;    xgcv.foreground = f->output_data.x->cursor_pixel;
# Line 11387  x_draw_bar_cursor (w, row, width, kind) Line 7313  x_draw_bar_cursor (w, row, width, kind)
7313  {  {
7314    struct frame *f = XFRAME (w->frame);    struct frame *f = XFRAME (w->frame);
7315    struct glyph *cursor_glyph;    struct glyph *cursor_glyph;
7316          
7317    /* If cursor is out of bounds, don't draw garbage.  This can happen    /* If cursor is out of bounds, don't draw garbage.  This can happen
7318       in mini-buffer windows when switching between echo area glyphs       in mini-buffer windows when switching between echo area glyphs
7319       and mini-buffer.  */       and mini-buffer.  */
# Line 11402  x_draw_bar_cursor (w, row, width, kind) Line 7328  x_draw_bar_cursor (w, row, width, kind)
7328      {      {
7329        struct glyph_row *row;        struct glyph_row *row;
7330        row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);        row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
7331        x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);        draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
7332      }      }
7333    else    else
7334      {      {
# Line 11423  x_draw_bar_cursor (w, row, width, kind) Line 7349  x_draw_bar_cursor (w, row, width, kind)
7349        else        else
7350          xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;          xgcv.background = xgcv.foreground = f->output_data.x->cursor_pixel;
7351        xgcv.graphics_exposures = 0;        xgcv.graphics_exposures = 0;
7352      
7353        if (gc)        if (gc)
7354          XChangeGC (dpy, gc, mask, &xgcv);          XChangeGC (dpy, gc, mask, &xgcv);
7355        else        else
# Line 11431  x_draw_bar_cursor (w, row, width, kind) Line 7357  x_draw_bar_cursor (w, row, width, kind)
7357            gc = XCreateGC (dpy, window, mask, &xgcv);            gc = XCreateGC (dpy, window, mask, &xgcv);
7358            FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;            FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
7359          }          }
7360      
7361        if (width < 0)        if (width < 0)
7362          width = f->output_data.x->cursor_width;          width = FRAME_CURSOR_WIDTH (f);
7363        width = min (cursor_glyph->pixel_width, width);        width = min (cursor_glyph->pixel_width, width);
7364      
7365        w->phys_cursor_width = width;        w->phys_cursor_width = width;
7366        x_clip_to_row (w, row, gc, 0);        x_clip_to_row (w, row, gc, 0);
7367          
7368        if (kind == BAR_CURSOR)        if (kind == BAR_CURSOR)
7369            XFillRectangle (dpy, window, gc,            XFillRectangle (dpy, window, gc,
7370                            WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),                            WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
# Line 11457  x_draw_bar_cursor (w, row, width, kind) Line 7383  x_draw_bar_cursor (w, row, width, kind)
7383  }  }
7384    
7385    
7386  /* Clear the cursor of window W to background color, and mark the  /* RIF: Define cursor CURSOR on frame F.  */
    cursor as not shown.  This is used when the text where the cursor  
    is is about to be rewritten.  */  
7387    
7388  static void  static void
7389  x_clear_cursor (w)  x_define_frame_cursor (f, cursor)
7390       struct window *w;       struct frame *f;
7391         Cursor cursor;
7392  {  {
7393    if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
     x_update_window_cursor (w, 0);  
7394  }  }
7395    
7396    
7397  /* Draw the cursor glyph of window W in glyph row ROW.  See the  /* RIF: Clear area on frame F.  */
    comment of x_draw_glyphs for the meaning of HL.  */  
7398    
7399  static void  static void
7400  x_draw_phys_cursor_glyph (w, row, hl)  x_clear_frame_area (f, x, y, width, height)
7401       struct window *w;       struct frame *f;
7402       struct glyph_row *row;       int x, y, width, height;
      enum draw_glyphs_face hl;  
7403  {  {
7404    /* If cursor hpos is out of bounds, don't draw garbage.  This can    x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7405       happen in mini-buffer windows when switching between echo area                  x, y, width, height, False);
      glyphs and mini-buffer.  */  
   if (w->phys_cursor.hpos < row->used[TEXT_AREA])  
     {  
       int on_p = w->phys_cursor_on_p;  
       int x1;  
         
       x1 = x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,  
                           w->phys_cursor.hpos, w->phys_cursor.hpos + 1,  
                           hl, 0);  
       w->phys_cursor_on_p = on_p;  
   
       if (hl == DRAW_CURSOR)  
         w->phys_cursor_width = x1 - w->phys_cursor.x;  
   
       /* When we erase the cursor, and ROW is overlapped by other  
          rows, make sure that these overlapping parts of other rows  
          are redrawn.  */  
       else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)  
         {  
           if (row > w->current_matrix->rows  
               && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))  
             x_fix_overlapping_area (w, row - 1, TEXT_AREA);  
   
           if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)  
               && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))  
             x_fix_overlapping_area (w, row + 1, TEXT_AREA);  
         }  
     }  
7406  }  }
7407    
7408    
7409  /* Erase the image of a cursor of window W from the screen.  */  /* RIF: Draw cursor on window W.  */
7410    
7411  static void  static void
7412  x_erase_phys_cursor (w)  x_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
      struct window *w;  
 {  
   struct frame *f = XFRAME (w->frame);  
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);  
   int hpos = w->phys_cursor.hpos;  
   int vpos = w->phys_cursor.vpos;  
   int mouse_face_here_p = 0;  
   struct glyph_matrix *active_glyphs = w->current_matrix;  
   struct glyph_row *cursor_row;  
   struct glyph *cursor_glyph;  
   enum draw_glyphs_face hl;  
   
   /* No cursor displayed or row invalidated => nothing to do on the  
      screen.  */  
   if (w->phys_cursor_type == NO_CURSOR)  
     goto mark_cursor_off;  
             
   /* VPOS >= active_glyphs->nrows means that window has been resized.  
      Don't bother to erase the cursor.  */  
   if (vpos >= active_glyphs->nrows)  
     goto mark_cursor_off;  
   
   /* If row containing cursor is marked invalid, there is nothing we  
      can do.  */  
   cursor_row = MATRIX_ROW (active_glyphs, vpos);  
   if (!cursor_row->enabled_p)  
     goto mark_cursor_off;  
     
   /* If row is completely invisible, don't attempt to delete a cursor which  
      isn't there.  This can happen if cursor is at top of a window, and  
      we switch to a buffer with a header line in that window.  */  
   if (cursor_row->visible_height <= 0)  
     goto mark_cursor_off;  
     
   /* This can happen when the new row is shorter than the old one.  
      In this case, either x_draw_glyphs or clear_end_of_line  
      should have cleared the cursor.  Note that we wouldn't be  
      able to erase the cursor in this case because we don't have a  
      cursor glyph at hand.  */  
   if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])  
     goto mark_cursor_off;  
           
   /* If the cursor is in the mouse face area, redisplay that when  
      we clear the cursor.  */  
   if (! NILP (dpyinfo->mouse_face_window)  
       && w == XWINDOW (dpyinfo->mouse_face_window)  
       && (vpos > dpyinfo->mouse_face_beg_row  
           || (vpos == dpyinfo->mouse_face_beg_row  
               && hpos >= dpyinfo->mouse_face_beg_col))  
       && (vpos < dpyinfo->mouse_face_end_row  
           || (vpos == dpyinfo->mouse_face_end_row  
               && hpos < dpyinfo->mouse_face_end_col))  
       /* Don't redraw the cursor's spot in mouse face if it is at the  
          end of a line (on a newline).  The cursor appears there, but  
          mouse highlighting does not.  */  
       && cursor_row->used[TEXT_AREA] > hpos)  
     mouse_face_here_p = 1;  
   
   /* Maybe clear the display under the cursor.  */  
   if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)  
     {  
       int x;  
       int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);  
   
       cursor_glyph = get_phys_cursor_glyph (w);  
       if (cursor_glyph == NULL)  
         goto mark_cursor_off;  
   
       x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);  
         
       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),  
                     x,  
                     WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,  
                                                      cursor_row->y)),  
                     cursor_glyph->pixel_width,  
                     cursor_row->visible_height,  
                     False);  
     }  
     
   /* Erase the cursor by redrawing the character underneath it.  */  
   if (mouse_face_here_p)  
     hl = DRAW_MOUSE_FACE;  
   else  
     hl = DRAW_NORMAL_TEXT;  
   x_draw_phys_cursor_glyph (w, cursor_row, hl);  
   
  mark_cursor_off:  
   w->phys_cursor_on_p = 0;  
   w->phys_cursor_type = NO_CURSOR;  
 }  
   
   
 /* Non-zero if physical cursor of window W is within mouse face.  */  
   
 static int  
 cursor_in_mouse_face_p (w)  
7413       struct window *w;       struct window *w;
7414         struct glyph_row *glyph_row;
7415         int x, y;
7416         int cursor_type, cursor_width;
7417         int on_p, active_p;
7418  {  {
7419    struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));    struct frame *f = XFRAME (WINDOW_FRAME (w));
   int in_mouse_face = 0;  
     
   if (WINDOWP (dpyinfo->mouse_face_window)  
       && XWINDOW (dpyinfo->mouse_face_window) == w)  
     {  
       int hpos = w->phys_cursor.hpos;  
       int vpos = w->phys_cursor.vpos;  
   
       if (vpos >= dpyinfo->mouse_face_beg_row  
           && vpos <= dpyinfo->mouse_face_end_row  
           && (vpos > dpyinfo->mouse_face_beg_row  
               || hpos >= dpyinfo->mouse_face_beg_col)  
           && (vpos < dpyinfo->mouse_face_end_row  
               || hpos < dpyinfo->mouse_face_end_col  
               || dpyinfo->mouse_face_past_end))  
         in_mouse_face = 1;  
     }  
   
   return in_mouse_face;  
 }  
   
   
 /* Display or clear cursor of window W.  If ON is zero, clear the  
    cursor.  If it is non-zero, display the cursor.  If ON is nonzero,  
    where to put the cursor is specified by HPOS, VPOS, X and Y.  */  
   
 void  
 x_display_and_set_cursor (w, on, hpos, vpos, x, y)  
      struct window *w;  
      int on, hpos, vpos, x, y;  
 {  
   struct frame *f = XFRAME (w->frame);  
   int new_cursor_type;  
   int new_cursor_width;  
   int cursor_off_state = 0;  
   struct glyph_matrix *current_glyphs;  
   struct glyph_row *glyph_row;  
   struct glyph *glyph;  
   
   /* This is pointless on invisible frames, and dangerous on garbaged  
      windows and frames; in the latter case, the frame or window may  
      be in the midst of changing its size, and x and y may be off the  
      window.  */  
   if (! FRAME_VISIBLE_P (f)  
       || FRAME_GARBAGED_P (f)  
       || vpos >= w->current_matrix->nrows  
       || hpos >= w->current_matrix->matrix_w)  
     return;  
   
   /* If cursor is off and we want it off, return quickly.  */  
   if (!on && !w->phys_cursor_on_p)  
     return;  
   
   current_glyphs = w->current_matrix;  
   glyph_row = MATRIX_ROW (current_glyphs, vpos);  
   glyph = glyph_row->glyphs[TEXT_AREA] + hpos;  
     
   /* If cursor row is not enabled, we don't really know where to  
      display the cursor.  */  
   if (!glyph_row->enabled_p)  
     {  
       w->phys_cursor_on_p = 0;  
       return;  
     }  
   
   xassert (interrupt_input_blocked);  
   
   /* Set new_cursor_type to the cursor we want to be displayed.  In a  
      mini-buffer window, we want the cursor only to appear if we are  
      reading input from this window.  For the selected window, we want  
      the cursor type given by the frame parameter.  If explicitly  
      marked off, draw no cursor.  In all other cases, we want a hollow  
      box cursor.  */  
   new_cursor_width = -1;  
   new_cursor_type = -2;  
   
   /* Echo area */  
   if (cursor_in_echo_area  
       && FRAME_HAS_MINIBUF_P (f)  
       && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))  
     {  
       if (w == XWINDOW (echo_area_window))  
         new_cursor_type = FRAME_DESIRED_CURSOR (f);  
       else if (NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,  
                                           w->buffer)))  
         new_cursor_type = NO_CURSOR;  
       else  
         cursor_off_state = 1;  
     }  
   
   /* Nonselected window or nonselected frame.  */  
   else if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame  
            || w != XWINDOW (f->selected_window))  
     {  
       if ((MINI_WINDOW_P (w) && minibuf_level == 0)  
           || NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,  
                                         w->buffer))  
           || NILP (XBUFFER (w->buffer)->cursor_type))  
         new_cursor_type = NO_CURSOR;  
       else  
         cursor_off_state = 1;  
     }  
   
   /* If new_cursor_type isn't decided yet, decide it now.  */  
   if (new_cursor_type == -2)  
     {  
       struct buffer *b = XBUFFER (w->buffer);  
   
       if (EQ (b->cursor_type, Qt))  
         new_cursor_type = FRAME_DESIRED_CURSOR (f);  
       else  
         new_cursor_type = x_specified_cursor_type (b->cursor_type,  
                                                    &new_cursor_width);  
     }  
   
   /* Dim out or hollow out the cursor,  
      if it has blinked off or for nonselected windows.  */  
   if (w->cursor_off_p || cursor_off_state)  
     {  
       if (new_cursor_type == FILLED_BOX_CURSOR)  
         new_cursor_type = HOLLOW_BOX_CURSOR;  
       else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1)  
         new_cursor_width = 1;  
       else  
         new_cursor_type = NO_CURSOR;  
     }  
   
   /* Now new_cursor_type is correct.  */  
7420    
7421    /* If cursor is currently being shown and we don't want it to be or    if (on_p)
      it is in the wrong place, or the cursor type is not what we want,  
      erase it.  */  
   if (w->phys_cursor_on_p  
       && (!on  
           || w->phys_cursor.x != x  
           || w->phys_cursor.y != y  
           || new_cursor_type != w->phys_cursor_type  
           || (new_cursor_type == BAR_CURSOR  
               && new_cursor_width != w->phys_cursor_width)))  
     x_erase_phys_cursor (w);  
   
   /* Don't check phys_cursor_on_p here because that flag is only set  
      to zero in some cases where we know that the cursor has been  
      completely erased, to avoid the extra work of erasing the cursor  
      twice.  In other words, phys_cursor_on_p can be 1 and the cursor  
      still not be visible, or it has only been partly erased.  */  
   if (on)  
7422      {      {
7423        w->phys_cursor_ascent = glyph_row->ascent;        w->phys_cursor_type = cursor_type;
       w->phys_cursor_height = glyph_row->height;  
         
       /* Set phys_cursor_.* before x_draw_.* is called because some  
          of them may need the information.  */  
       w->phys_cursor.x = x;  
       w->phys_cursor.y = glyph_row->y;  
       w->phys_cursor.hpos = hpos;  
       w->phys_cursor.vpos = vpos;  
       w->phys_cursor_type = new_cursor_type;  
7424        w->phys_cursor_on_p = 1;        w->phys_cursor_on_p = 1;
7425    
7426        switch (new_cursor_type)        switch (cursor_type)
7427          {          {
7428          case HOLLOW_BOX_CURSOR:          case HOLLOW_BOX_CURSOR:
7429            x_draw_hollow_cursor (w, glyph_row);            x_draw_hollow_cursor (w, glyph_row);
7430            break;            break;
7431    
7432          case FILLED_BOX_CURSOR:          case FILLED_BOX_CURSOR:
7433            x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);            draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
7434            break;            break;
7435    
7436          case BAR_CURSOR:          case BAR_CURSOR:
7437            x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR);            x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
7438            break;            break;
7439    
7440          case HBAR_CURSOR:          case HBAR_CURSOR:
7441            x_draw_bar_cursor (w, glyph_row, new_cursor_width, HBAR_CURSOR);            x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
7442            break;            break;
7443    
7444          case NO_CURSOR:          case NO_CURSOR:
# Line 11800  x_display_and_set_cursor (w, on, hpos, v Line 7448  x_display_and_set_cursor (w, on, hpos, v
7448          default:          default:
7449            abort ();            abort ();
7450          }          }
7451          
7452  #ifdef HAVE_X_I18N  #ifdef HAVE_X_I18N
7453        if (w == XWINDOW (f->selected_window))        if (w == XWINDOW (f->selected_window))
7454          if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))          if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
# Line 11814  x_display_and_set_cursor (w, on, hpos, v Line 7462  x_display_and_set_cursor (w, on, hpos, v
7462  #endif  #endif
7463  }  }
7464    
   
 /* Display the cursor on window W, or clear it.  X and Y are window  
    relative pixel coordinates.  HPOS and VPOS are glyph matrix  
    positions.  If W is not the selected window, display a hollow  
    cursor.  ON non-zero means display the cursor at X, Y which  
    correspond to HPOS, VPOS, otherwise it is cleared.  */  
   
 void  
 x_display_cursor (w, on, hpos, vpos, x, y)  
      struct window *w;  
      int on, hpos, vpos, x, y;  
 {  
   BLOCK_INPUT;  
   x_display_and_set_cursor (w, on, hpos, vpos, x, y);  
   UNBLOCK_INPUT;  
 }  
   
   
 /* Display the cursor on window W, or clear it, according to ON_P.  
    Don't change the cursor's position.  */  
   
 void  
 x_update_cursor (f, on_p)  
      struct frame *f;  
 {  
   x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);  
 }  
   
   
 /* Call x_update_window_cursor with parameter ON_P on all leaf windows  
    in the window tree rooted at W.  */  
   
 static void  
 x_update_cursor_in_window_tree (w, on_p)  
      struct window *w;  
      int on_p;  
 {  
   while (w)  
     {  
       if (!NILP (w->hchild))  
         x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);  
       else if (!NILP (w->vchild))  
         x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);  
       else  
         x_update_window_cursor (w, on_p);  
   
       w = NILP (w->next) ? 0 : XWINDOW (w->next);  
     }  
 }  
   
   
 /* Switch the display of W's cursor on or off, according to the value  
    of ON.  */  
   
 static void  
 x_update_window_cursor (w, on)  
      struct window *w;  
      int on;  
 {  
   /* Don't update cursor in windows whose frame is in the process  
      of being deleted.  */  
   if (w->current_matrix)  
     {  
       BLOCK_INPUT;  
       x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,  
                                 w->phys_cursor.x, w->phys_cursor.y);  
       UNBLOCK_INPUT;  
     }  
 }  
   
   
   
7465    
7466  /* Icons.  */  /* Icons.  */
7467    
# Line 11950  x_text_icon (f, icon_name) Line 7526  x_text_icon (f, icon_name)
7526      text.encoding = XA_STRING;      text.encoding = XA_STRING;
7527      text.format = 8;      text.format = 8;
7528      text.nitems = strlen (icon_name);      text.nitems = strlen (icon_name);
7529  #ifdef USE_X_TOOLKIT      XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
     XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),  
                     &text);  
 #else /* not USE_X_TOOLKIT */  
     XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);  
 #endif /* not USE_X_TOOLKIT */  
7530    }    }
7531  #else /* not HAVE_X11R4 */  #else /* not HAVE_X11R4 */
7532    XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);    XSetIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), icon_name);
7533  #endif /* not HAVE_X11R4 */  #endif /* not HAVE_X11R4 */
7534    
7535    if (f->output_data.x->icon_bitmap > 0)    if (f->output_data.x->icon_bitmap > 0)
# Line 11986  x_error_catcher (display, error) Line 7557  x_error_catcher (display, error)
7557       XErrorEvent *error;       XErrorEvent *error;
7558  {  {
7559    XGetErrorText (display, error->error_code,    XGetErrorText (display, error->error_code,
7560                   XSTRING (x_error_message_string)->data,                   SDATA (x_error_message_string),
7561                   X_ERROR_MESSAGE_SIZE);                   X_ERROR_MESSAGE_SIZE);
7562  }  }
7563    
# Line 12010  int Line 7581  int
7581  x_catch_errors (dpy)  x_catch_errors (dpy)
7582       Display *dpy;       Display *dpy;
7583  {  {
7584    int count = specpdl_ptr - specpdl;    int count = SPECPDL_INDEX ();
7585    
7586    /* Make sure any errors from previous requests have been dealt with.  */    /* Make sure any errors from previous requests have been dealt with.  */
7587    XSync (dpy, False);    XSync (dpy, False);
7588    
7589    record_unwind_protect (x_catch_errors_unwind, x_error_message_string);    record_unwind_protect (x_catch_errors_unwind,
7590                             Fcons (make_save_value (dpy, 0),
7591                                    x_error_message_string));
7592    
7593    x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);    x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
7594    XSTRING (x_error_message_string)->data[0] = 0;    SSET (x_error_message_string, 0, 0);
7595    
7596    return count;    return count;
7597  }  }
# Line 12029  static Lisp_Object Line 7602  static Lisp_Object
7602  x_catch_errors_unwind (old_val)  x_catch_errors_unwind (old_val)
7603       Lisp_Object old_val;       Lisp_Object old_val;
7604  {  {
7605    x_error_message_string = old_val;    Lisp_Object first;
7606    
7607      first = XCAR (old_val);
7608    
7609      XSync (XSAVE_VALUE (first)->pointer, False);
7610    
7611      x_error_message_string = XCDR (old_val);
7612    return Qnil;    return Qnil;
7613  }  }
7614    
# Line 12045  x_check_errors (dpy, format) Line 7624  x_check_errors (dpy, format)
7624    /* Make sure to catch any errors incurred so far.  */    /* Make sure to catch any errors incurred so far.  */
7625    XSync (dpy, False);    XSync (dpy, False);
7626    
7627    if (XSTRING (x_error_message_string)->data[0])    if (SREF (x_error_message_string, 0))
7628      error (format, XSTRING (x_error_message_string)->data);      error (format, SDATA (x_error_message_string));
7629  }  }
7630    
7631  /* Nonzero if we had any X protocol errors  /* Nonzero if we had any X protocol errors
# Line 12059  x_had_errors_p (dpy) Line 7638  x_had_errors_p (dpy)
7638    /* Make sure to catch any errors incurred so far.  */    /* Make sure to catch any errors incurred so far.  */
7639    XSync (dpy, False);    XSync (dpy, False);
7640    
7641    return XSTRING (x_error_message_string)->data[0] != 0;    return SREF (x_error_message_string, 0) != 0;
7642  }  }
7643    
7644  /* Forget about any errors we have had, since we did x_catch_errors on DPY.  */  /* Forget about any errors we have had, since we did x_catch_errors on DPY.  */
# Line 12068  void Line 7647  void
7647  x_clear_errors (dpy)  x_clear_errors (dpy)
7648       Display *dpy;       Display *dpy;
7649  {  {
7650    XSTRING (x_error_message_string)->data[0] = 0;    SSET (x_error_message_string, 0, 0);
7651  }  }
7652    
7653  /* Stop catching X protocol errors and let them make Emacs die.  /* Stop catching X protocol errors and let them make Emacs die.
# Line 12095  x_trace_wire () Line 7674  x_trace_wire ()
7674    
7675  /* Handle SIGPIPE, which can happen when the connection to a server  /* Handle SIGPIPE, which can happen when the connection to a server
7676     simply goes away.  SIGPIPE is handled by x_connection_signal.     simply goes away.  SIGPIPE is handled by x_connection_signal.
7677     Don't need to do anything, because the write which caused the     Don't need to do anything, because the write which caused the
7678     SIGPIPE will fail, causing Xlib to invoke the X IO error handler,     SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
7679     which will do the appropriate cleanup for us.  */     which will do the appropriate cleanup for us.  */
7680      
7681  static SIGTYPE  static SIGTYPE
7682  x_connection_signal (signalnum) /* If we don't have an argument, */  x_connection_signal (signalnum) /* If we don't have an argument, */
7683       int signalnum;             /* some compilers complain in signal calls.  */       int signalnum;             /* some compilers complain in signal calls.  */
# Line 12141  x_connection_closed (dpy, error_message) Line 7720  x_connection_closed (dpy, error_message)
7720    struct x_display_info *dpyinfo = x_display_info_for_display (dpy);    struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
7721    Lisp_Object frame, tail;    Lisp_Object frame, tail;
7722    int count;    int count;
7723      
7724    error_msg = (char *) alloca (strlen (error_message) + 1);    error_msg = (char *) alloca (strlen (error_message) + 1);
7725    strcpy (error_msg, error_message);    strcpy (error_msg, error_message);
7726    handling_signal = 0;    handling_signal = 0;
7727      
7728    /* Prevent being called recursively because of an error condition    /* Prevent being called recursively because of an error condition
7729       below.  Otherwise, we might end up with printing ``can't find per       below.  Otherwise, we might end up with printing ``can't find per
7730       display information'' in the recursive call instead of printing       display information'' in the recursive call instead of printing
7731       the original message here.  */       the original message here.  */
7732    count = x_catch_errors (dpy);    count = x_catch_errors (dpy);
7733      
7734    /* We have to close the display to inform Xt that it doesn't    /* We have to close the display to inform Xt that it doesn't
7735       exist anymore.  If we don't, Xt will continue to wait for       exist anymore.  If we don't, Xt will continue to wait for
7736       events from the display.  As a consequence, a sequence of       events from the display.  As a consequence, a sequence of
# Line 12166  x_connection_closed (dpy, error_message) Line 7745  x_connection_closed (dpy, error_message)
7745       Closing the display is reported to lead to a bus error on       Closing the display is reported to lead to a bus error on
7746       OpenWindows in certain situations.  I suspect that is a bug       OpenWindows in certain situations.  I suspect that is a bug
7747       in OpenWindows.  I don't know how to cicumvent it here.  */       in OpenWindows.  I don't know how to cicumvent it here.  */
7748      
7749  #ifdef USE_X_TOOLKIT  #ifdef USE_X_TOOLKIT
7750    /* If DPYINFO is null, this means we didn't open the display    /* If DPYINFO is null, this means we didn't open the display
7751       in the first place, so don't try to close it.  */       in the first place, so don't try to close it.  */
# Line 12214  x_connection_closed (dpy, error_message) Line 7793  x_connection_closed (dpy, error_message)
7793      x_delete_display (dpyinfo);      x_delete_display (dpyinfo);
7794    
7795    x_uncatch_errors (dpy, count);    x_uncatch_errors (dpy, count);
7796      
7797    if (x_display_list == 0)    if (x_display_list == 0)
7798      {      {
7799        fprintf (stderr, "%s\n", error_msg);        fprintf (stderr, "%s\n", error_msg);
# Line 12307  x_new_font (f, fontname) Line 7886  x_new_font (f, fontname)
7886    f->output_data.x->baseline_offset = fontp->baseline_offset;    f->output_data.x->baseline_offset = fontp->baseline_offset;
7887    f->output_data.x->fontset = -1;    f->output_data.x->fontset = -1;
7888    
7889    x_compute_fringe_widths (f, 1);    compute_fringe_widths (f, 1);
7890    
7891    /* Compute the scroll bar width in character columns.  */    /* Compute the scroll bar width in character columns.  */
7892    if (f->scroll_bar_pixel_width > 0)    if (f->scroll_bar_pixel_width > 0)
# Line 12368  x_new_fontset (f, fontsetname) Line 7947  x_new_fontset (f, fontsetname)
7947         to do.  */         to do.  */
7948      return fontset_name (fontset);      return fontset_name (fontset);
7949    
7950    result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));    result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
7951    
7952    if (!STRINGP (result))    if (!STRINGP (result))
7953      /* Can't load ASCII font.  */      /* Can't load ASCII font.  */
# Line 12380  x_new_fontset (f, fontsetname) Line 7959  x_new_fontset (f, fontsetname)
7959  #ifdef HAVE_X_I18N  #ifdef HAVE_X_I18N
7960    if (FRAME_XIC (f)    if (FRAME_XIC (f)
7961        && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))        && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
7962      xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);      xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
7963  #endif  #endif
7964      
7965    return build_string (fontsetname);    return build_string (fontsetname);
7966  }  }
7967    
 /* Compute actual fringe widths */  
   
 void  
 x_compute_fringe_widths (f, redraw)  
      struct frame *f;  
      int redraw;  
 {  
   int o_left = f->output_data.x->left_fringe_width;  
   int o_right = f->output_data.x->right_fringe_width;  
   int o_cols = f->output_data.x->fringe_cols;  
   
   Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);  
   Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);  
   int left_fringe_width, right_fringe_width;  
   
   if (!NILP (left_fringe))  
     left_fringe = Fcdr (left_fringe);  
   if (!NILP (right_fringe))  
     right_fringe = Fcdr (right_fringe);  
   
   left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :  
                        XINT (left_fringe));  
   right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :  
                         XINT (right_fringe));  
   
   if (left_fringe_width || right_fringe_width)  
     {  
       int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;  
       int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;  
       int conf_wid = left_wid + right_wid;  
       int font_wid = FONT_WIDTH (f->output_data.x->font);  
       int cols = (left_wid + right_wid + font_wid-1) / font_wid;  
       int real_wid = cols * font_wid;  
       if (left_wid && right_wid)  
         {  
           if (left_fringe_width < 0)  
             {  
               /* Left fringe width is fixed, adjust right fringe if necessary */  
               f->output_data.x->left_fringe_width = left_wid;  
               f->output_data.x->right_fringe_width = real_wid - left_wid;  
             }  
           else if (right_fringe_width < 0)  
             {  
               /* Right fringe width is fixed, adjust left fringe if necessary */  
               f->output_data.x->left_fringe_width = real_wid - right_wid;  
               f->output_data.x->right_fringe_width = right_wid;  
             }  
           else  
             {  
               /* Adjust both fringes with an equal amount.  
                  Note that we are doing integer arithmetic here, so don't  
                  lose a pixel if the total width is an odd number.  */  
               int fill = real_wid - conf_wid;  
               f->output_data.x->left_fringe_width = left_wid + fill/2;  
               f->output_data.x->right_fringe_width = right_wid + fill - fill/2;  
             }  
         }  
       else if (left_fringe_width)  
         {  
           f->output_data.x->left_fringe_width = real_wid;  
           f->output_data.x->right_fringe_width = 0;  
         }  
       else  
         {  
           f->output_data.x->left_fringe_width = 0;  
           f->output_data.x->right_fringe_width = real_wid;  
         }  
       f->output_data.x->fringe_cols = cols;  
       f->output_data.x->fringes_extra = real_wid;  
     }  
   else  
     {  
       f->output_data.x->left_fringe_width = 0;  
       f->output_data.x->right_fringe_width = 0;  
       f->output_data.x->fringe_cols = 0;  
       f->output_data.x->fringes_extra = 0;  
     }  
   
   if (redraw && FRAME_VISIBLE_P (f))  
     if (o_left != f->output_data.x->left_fringe_width ||  
         o_right != f->output_data.x->right_fringe_width ||  
         o_cols != f->output_data.x->fringe_cols)  
       redraw_frame (f);  
 }  
7968    
7969  /***********************************************************************  /***********************************************************************
7970                             X Input Methods                             X Input Methods
# Line 12491  xim_destroy_callback (xim, client_data, Line 7986  xim_destroy_callback (xim, client_data,
7986  {  {
7987    struct x_display_info *dpyinfo = (struct x_display_info *) client_data;    struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
7988    Lisp_Object frame, tail;    Lisp_Object frame, tail;
7989      
7990    BLOCK_INPUT;    BLOCK_INPUT;
7991      
7992    /* No need to call XDestroyIC.. */    /* No need to call XDestroyIC.. */
7993    FOR_EACH_FRAME (tail, frame)    FOR_EACH_FRAME (tail, frame)
7994      {      {
# Line 12508  xim_destroy_callback (xim, client_data, Line 8003  xim_destroy_callback (xim, client_data,
8003              }              }
8004          }          }
8005      }      }
8006      
8007    /* No need to call XCloseIM.  */    /* No need to call XCloseIM.  */
8008    dpyinfo->xim = NULL;    dpyinfo->xim = NULL;
8009    XFree (dpyinfo->xim_styles);    XFree (dpyinfo->xim_styles);
# Line 12517  xim_destroy_callback (xim, client_data, Line 8012  xim_destroy_callback (xim, client_data,
8012    
8013  #endif /* HAVE_X11R6 */  #endif /* HAVE_X11R6 */
8014    
8015    #ifdef HAVE_X11R6
8016    /* This isn't prototyped in OSF 5.0 or 5.1a.  */
8017    extern char *XSetIMValues P_ ((XIM, ...));
8018    #endif
8019    
8020  /* Open the connection to the XIM server on display DPYINFO.  /* Open the connection to the XIM server on display DPYINFO.
8021     RESOURCE_NAME is the resource name Emacs uses.  */     RESOURCE_NAME is the resource name Emacs uses.  */
8022    
# Line 12536  xim_open_dpy (dpyinfo, resource_name) Line 8036  xim_open_dpy (dpyinfo, resource_name)
8036  #ifdef HAVE_X11R6  #ifdef HAVE_X11R6
8037        XIMCallback destroy;        XIMCallback destroy;
8038  #endif  #endif
8039          
8040        /* Get supported styles and XIM values.  */        /* Get supported styles and XIM values.  */
8041        XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);        XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
8042          
8043  #ifdef HAVE_X11R6  #ifdef HAVE_X11R6
8044        destroy.callback = xim_destroy_callback;        destroy.callback = xim_destroy_callback;
8045        destroy.client_data = (XPointer)dpyinfo;        destroy.client_data = (XPointer)dpyinfo;
       /* This isn't prototyped in OSF 5.0.  */  
8046        XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);        XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
8047  #endif  #endif
8048      }      }
8049      
8050  #else /* not USE_XIM */  #else /* not USE_XIM */
8051    dpyinfo->xim = NULL;    dpyinfo->xim = NULL;
8052  #endif /* not USE_XIM */  #endif /* not USE_XIM */
# Line 12563  struct xim_inst_t Line 8062  struct xim_inst_t
8062  };  };
8063    
8064  /* XIM instantiate callback function, which is called whenever an XIM  /* XIM instantiate callback function, which is called whenever an XIM
8065     server is available.  DISPLAY is teh display of the XIM.     server is available.  DISPLAY is the display of the XIM.
8066     CLIENT_DATA contains a pointer to an xim_inst_t structure created     CLIENT_DATA contains a pointer to an xim_inst_t structure created
8067     when the callback was registered.  */     when the callback was registered.  */
8068    
# Line 12579  xim_instantiate_callback (display, clien Line 8078  xim_instantiate_callback (display, clien
8078    /* We don't support multiple XIM connections. */    /* We don't support multiple XIM connections. */
8079    if (dpyinfo->xim)    if (dpyinfo->xim)
8080      return;      return;
8081      
8082    xim_open_dpy (dpyinfo, xim_inst->resource_name);    xim_open_dpy (dpyinfo, xim_inst->resource_name);
8083    
8084    /* Create XIC for the existing frames on the same display, as long    /* Create XIC for the existing frames on the same display, as long
# Line 12592  xim_instantiate_callback (display, clien Line 8091  xim_instantiate_callback (display, clien
8091        FOR_EACH_FRAME (tail, frame)        FOR_EACH_FRAME (tail, frame)
8092          {          {
8093            struct frame *f = XFRAME (frame);            struct frame *f = XFRAME (frame);
8094              
8095            if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)            if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
8096              if (FRAME_XIC (f) == NULL)              if (FRAME_XIC (f) == NULL)
8097                {                {
# Line 12606  xim_instantiate_callback (display, clien Line 8105  xim_instantiate_callback (display, clien
8105                    }                    }
8106                }                }
8107          }          }
8108          
8109        UNBLOCK_INPUT;        UNBLOCK_INPUT;
8110      }      }
8111  }  }
# Line 12628  xim_initialize (dpyinfo, resource_name) Line 8127  xim_initialize (dpyinfo, resource_name)
8127  #ifdef HAVE_X11R6_XIM  #ifdef HAVE_X11R6_XIM
8128    struct xim_inst_t *xim_inst;    struct xim_inst_t *xim_inst;
8129    int len;    int len;
8130      
8131    dpyinfo->xim = NULL;    dpyinfo->xim = NULL;
8132    xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));    xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
8133    xim_inst->dpyinfo = dpyinfo;    xim_inst->dpyinfo = dpyinfo;
# Line 12646  xim_initialize (dpyinfo, resource_name) Line 8145  xim_initialize (dpyinfo, resource_name)
8145    dpyinfo->xim = NULL;    dpyinfo->xim = NULL;
8146    xim_open_dpy (dpyinfo, resource_name);    xim_open_dpy (dpyinfo, resource_name);
8147  #endif /* not HAVE_X11R6_XIM */  #endif /* not HAVE_X11R6_XIM */
8148      
8149  #else /* not USE_XIM */  #else /* not USE_XIM */
8150    dpyinfo->xim = NULL;    dpyinfo->xim = NULL;
8151  #endif /* not USE_XIM */  #endif /* not USE_XIM */
# Line 12694  x_calc_absolute_position (f) Line 8193  x_calc_absolute_position (f)
8193    if (! ((flags & XNegative) || (flags & YNegative)))    if (! ((flags & XNegative) || (flags & YNegative)))
8194      return;      return;
8195    
8196  #ifdef USE_X_TOOLKIT    this_window = FRAME_OUTER_WINDOW (f);
   this_window = XtWindow (f->output_data.x->widget);  
 #else  
   this_window = FRAME_X_WINDOW (f);  
 #endif  
8197    
8198    /* Find the position of the outside upper-left corner of    /* Find the position of the outside upper-left corner of
8199       the inner window, with respect to the outer window.       the inner window, with respect to the outer window.
# Line 12768  x_calc_absolute_position (f) Line 8263  x_calc_absolute_position (f)
8263    
8264         It's not obvious where the initial small difference comes from.         It's not obvious where the initial small difference comes from.
8265         2000-12-01, gerd.  */         2000-12-01, gerd.  */
8266        
8267      XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);      XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
8268  #endif  #endif
8269    
# Line 12779  x_calc_absolute_position (f) Line 8274  x_calc_absolute_position (f)
8274                                   - height                                   - height
8275                                   + f->output_data.x->top_pos);                                   + f->output_data.x->top_pos);
8276    }    }
8277      
8278    /* The left_pos and top_pos    /* The left_pos and top_pos
8279       are now relative to the top and left screen edges,       are now relative to the top and left screen edges,
8280       so the flags should correspond.  */       so the flags should correspond.  */
# Line 12829  x_set_offset (f, xoff, yoff, change_grav Line 8324  x_set_offset (f, xoff, yoff, change_grav
8324      }      }
8325  #endif  #endif
8326    
8327  #ifdef USE_X_TOOLKIT    XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8328    XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),                 modified_left, modified_top);
                modified_left, modified_top);  
 #else /* not USE_X_TOOLKIT */  
   XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),  
                modified_left, modified_top);  
 #endif /* not USE_X_TOOLKIT */  
8329    UNBLOCK_INPUT;    UNBLOCK_INPUT;
8330  }  }
8331    
# Line 12848  x_check_fullscreen (f) Line 8338  x_check_fullscreen (f)
8338    if (f->output_data.x->want_fullscreen & FULLSCREEN_BOTH)    if (f->output_data.x->want_fullscreen & FULLSCREEN_BOTH)
8339      {      {
8340        int width, height, ign;        int width, height, ign;
8341                          
8342        x_real_positions (f, &f->output_data.x->left_pos,        x_real_positions (f, &f->output_data.x->left_pos,
8343                          &f->output_data.x->top_pos);                          &f->output_data.x->top_pos);
8344    
8345        x_fullscreen_adjust (f, &width, &height, &ign, &ign);        x_fullscreen_adjust (f, &width, &height, &ign, &ign);
8346                      
8347        /* We do not need to move the window, it shall be taken care of        /* We do not need to move the window, it shall be taken care of
8348           when setting WM manager hints.           when setting WM manager hints.
8349           If the frame is visible already, the position is checked by           If the frame is visible already, the position is checked by
# Line 12866  x_check_fullscreen (f) Line 8356  x_check_fullscreen (f)
8356    
8357            /* Wait for the change of frame size to occur */            /* Wait for the change of frame size to occur */
8358            f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT;            f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT;
             
8359          }          }
8360      }      }
8361  }  }
# Line 12890  x_check_fullscreen_move (f) Line 8379  x_check_fullscreen_move (f)
8379        expect_top = 0;        expect_top = 0;
8380      if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)      if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
8381        expect_left = 0;        expect_left = 0;
8382        
8383      if (expect_top != f->output_data.x->top_pos      if (expect_top != f->output_data.x->top_pos
8384          || expect_left != f->output_data.x->left_pos)          || expect_left != f->output_data.x->left_pos)
8385        x_set_offset (f, expect_left, expect_top, 1);        x_set_offset (f, expect_left, expect_top, 1);
# Line 12901  x_check_fullscreen_move (f) Line 8390  x_check_fullscreen_move (f)
8390  }  }
8391    
8392    
 /* Calculate fullscreen size.  Return in *TOP_POS and *LEFT_POS the  
    wanted positions of the WM window (not emacs window).  
    Return in *WIDTH and *HEIGHT the wanted width and height of Emacs  
    window (FRAME_X_WINDOW).  
  */  
 void  
 x_fullscreen_adjust (f, width, height, top_pos, left_pos)  
      struct frame *f;  
      int *width;  
      int *height;  
      int *top_pos;  
      int *left_pos;  
 {  
   int newwidth = f->width, newheight = f->height;  
   
   *top_pos = f->output_data.x->top_pos;  
   *left_pos = f->output_data.x->left_pos;  
     
   if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)  
     {  
       int ph;  
         
       ph = FRAME_X_DISPLAY_INFO (f)->height;  
       newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);  
       ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)  
         - f->output_data.x->y_pixels_diff;  
       newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);  
       *top_pos = 0;  
     }  
   
   if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)  
     {  
       int pw;  
         
       pw = FRAME_X_DISPLAY_INFO (f)->width;  
       newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);  
       pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)  
         - f->output_data.x->x_pixels_diff;  
       newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);  
       *left_pos = 0;  
     }  
   
   *width = newwidth;  
   *height = newheight;  
 }  
   
   
8393  /* Change the size of frame F's X window to COLS/ROWS in the case F  /* Change the size of frame F's X window to COLS/ROWS in the case F
8394     doesn't have a widget.  If CHANGE_GRAVITY is 1, we change to     doesn't have a widget.  If CHANGE_GRAVITY is 1, we change to
8395     top-left-corner window gravity for this size change and subsequent     top-left-corner window gravity for this size change and subsequent
# Line 12969  x_set_window_size_1 (f, change_gravity, Line 8411  x_set_window_size_1 (f, change_gravity,
8411         ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)         ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
8412         : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));         : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
8413    
8414    x_compute_fringe_widths (f, 0);    compute_fringe_widths (f, 0);
8415    
8416    pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);    pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
8417    pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);    pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
# Line 13021  x_set_window_size (f, change_gravity, co Line 8463  x_set_window_size (f, change_gravity, co
8463  {  {
8464    BLOCK_INPUT;    BLOCK_INPUT;
8465    
8466  #ifdef USE_X_TOOLKIT  #ifdef USE_GTK
8467        if (FRAME_GTK_WIDGET (f))
8468        xg_frame_set_char_size (f, cols, rows);
8469      else
8470        x_set_window_size_1 (f, change_gravity, cols, rows);
8471    #elif USE_X_TOOLKIT
8472    
8473    if (f->output_data.x->widget != NULL)    if (f->output_data.x->widget != NULL)
8474      {      {
8475        /* The x and y position of the widget is clobbered by the        /* The x and y position of the widget is clobbered by the
# Line 13037  x_set_window_size (f, change_gravity, co Line 8484  x_set_window_size (f, change_gravity, co
8484      }      }
8485    else    else
8486      x_set_window_size_1 (f, change_gravity, cols, rows);      x_set_window_size_1 (f, change_gravity, cols, rows);
8487      
8488  #else /* not USE_X_TOOLKIT */  #else /* not USE_X_TOOLKIT */
8489      
8490    x_set_window_size_1 (f, change_gravity, cols, rows);    x_set_window_size_1 (f, change_gravity, cols, rows);
8491      
8492  #endif /* not USE_X_TOOLKIT */  #endif /* not USE_X_TOOLKIT */
8493    
8494    /* If cursor was outside the new size, mark it as off.  */    /* If cursor was outside the new size, mark it as off.  */
8495    mark_window_cursors_off (XWINDOW (f->root_window));    mark_window_cursors_off (XWINDOW (f->root_window));
8496    
8497    /* Clear out any recollection of where the mouse highlighting was,    /* Clear out any recollection of where the mouse highlighting was,
8498       since it might be in a place that's outside the new frame size.       since it might be in a place that's outside the new frame size.
8499       Actually checking whether it is outside is a pain in the neck,       Actually checking whether it is outside is a pain in the neck,
8500       so don't try--just let the highlighting be done afresh with new size.  */       so don't try--just let the highlighting be done afresh with new size.  */
8501    cancel_mouse_face (f);    cancel_mouse_face (f);
# Line 13134  x_raise_frame (f) Line 8581  x_raise_frame (f)
8581    if (f->async_visible)    if (f->async_visible)
8582      {      {
8583        BLOCK_INPUT;        BLOCK_INPUT;
8584  #ifdef USE_X_TOOLKIT        XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
       XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));  
 #else /* not USE_X_TOOLKIT */  
       XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));  
 #endif /* not USE_X_TOOLKIT */  
8585        XFlush (FRAME_X_DISPLAY (f));        XFlush (FRAME_X_DISPLAY (f));
8586        UNBLOCK_INPUT;        UNBLOCK_INPUT;
8587      }      }
# Line 13153  x_lower_frame (f) Line 8596  x_lower_frame (f)
8596    if (f->async_visible)    if (f->async_visible)
8597      {      {
8598        BLOCK_INPUT;        BLOCK_INPUT;
8599  #ifdef USE_X_TOOLKIT        XLowerWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
       XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));  
 #else /* not USE_X_TOOLKIT */  
       XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));  
 #endif /* not USE_X_TOOLKIT */  
8600        XFlush (FRAME_X_DISPLAY (f));        XFlush (FRAME_X_DISPLAY (f));
8601        UNBLOCK_INPUT;        UNBLOCK_INPUT;
8602      }      }
# Line 13217  x_make_frame_visible (f) Line 8656  x_make_frame_visible (f)
8656        /* This was XtPopup, but that did nothing for an iconified frame.  */        /* This was XtPopup, but that did nothing for an iconified frame.  */
8657        XtMapWidget (f->output_data.x->widget);        XtMapWidget (f->output_data.x->widget);
8658  #else /* not USE_X_TOOLKIT */  #else /* not USE_X_TOOLKIT */
8659    #ifdef USE_GTK
8660          gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
8661          gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
8662    #else
8663        XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));        XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
8664    #endif /* not USE_GTK */
8665  #endif /* not USE_X_TOOLKIT */  #endif /* not USE_X_TOOLKIT */
8666  #if 0 /* This seems to bring back scroll bars in the wrong places  #if 0 /* This seems to bring back scroll bars in the wrong places
8667           if the window configuration has changed.  They seem           if the window configuration has changed.  They seem
# Line 13264  x_make_frame_visible (f) Line 8708  x_make_frame_visible (f)
8708          Drawable rootw;          Drawable rootw;
8709          int x, y;          int x, y;
8710          unsigned int width, height, border, depth;          unsigned int width, height, border, depth;
8711            
8712          BLOCK_INPUT;          BLOCK_INPUT;
8713    
8714          /* On some window managers (such as FVWM) moving an existing          /* On some window managers (such as FVWM) moving an existing
# Line 13327  x_make_frame_visible (f) Line 8771  x_make_frame_visible (f)
8771         FreeBSD, Linux and Solaris.  It turns out that, for some         FreeBSD, Linux and Solaris.  It turns out that, for some
8772         unknown reason, the call to XtMapWidget is completely ignored.         unknown reason, the call to XtMapWidget is completely ignored.
8773         Mapping the widget a second time works.  */         Mapping the widget a second time works.  */
8774        
8775      if (!FRAME_VISIBLE_P (f) && --retry_count > 0)      if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
8776        goto retry;        goto retry;
8777    }    }
# Line 13343  x_make_frame_invisible (f) Line 8787  x_make_frame_invisible (f)
8787  {  {
8788    Window window;    Window window;
8789    
 #ifdef USE_X_TOOLKIT  
8790    /* Use the frame's outermost window, not the one we normally draw on.  */    /* Use the frame's outermost window, not the one we normally draw on.  */
8791    window = XtWindow (f->output_data.x->widget);    window = FRAME_OUTER_WINDOW (f);
 #else /* not USE_X_TOOLKIT */  
   window = FRAME_X_WINDOW (f);  
 #endif /* not USE_X_TOOLKIT */  
8792    
8793    /* Don't keep the highlight on an invisible frame.  */    /* Don't keep the highlight on an invisible frame.  */
8794    if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)    if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
# Line 13368  x_make_frame_invisible (f) Line 8808  x_make_frame_invisible (f)
8808       by hand again (they have already done that once for this window.)  */       by hand again (they have already done that once for this window.)  */
8809    x_wm_set_size_hint (f, (long) 0, 1);    x_wm_set_size_hint (f, (long) 0, 1);
8810    
8811    #ifdef USE_GTK
8812      if (FRAME_GTK_OUTER_WIDGET (f))
8813        gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
8814      else
8815    #endif
8816      {
8817  #ifdef HAVE_X11R4  #ifdef HAVE_X11R4
8818    
8819    if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,    if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
# Line 13401  x_make_frame_invisible (f) Line 8847  x_make_frame_invisible (f)
8847    /* Unmap the window ourselves.  Cheeky!  */    /* Unmap the window ourselves.  Cheeky!  */
8848    XUnmapWindow (FRAME_X_DISPLAY (f), window);    XUnmapWindow (FRAME_X_DISPLAY (f), window);
8849  #endif /* ! defined (HAVE_X11R4) */  #endif /* ! defined (HAVE_X11R4) */
8850      }
8851    
8852    /* We can't distinguish this from iconification    /* We can't distinguish this from iconification
8853       just by the event that we get from the server.       just by the event that we get from the server.
# Line 13441  x_iconify_frame (f) Line 8888  x_iconify_frame (f)
8888    if (!NILP (type))    if (!NILP (type))
8889      x_bitmap_icon (f, type);      x_bitmap_icon (f, type);
8890    
8891    #ifdef USE_GTK
8892      if (FRAME_GTK_OUTER_WIDGET (f))
8893        {
8894          if (! FRAME_VISIBLE_P (f))
8895            gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
8896    
8897          gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
8898          f->iconified = 1;
8899          f->visible = 1;
8900          f->async_iconified = 1;
8901          f->async_visible = 0;
8902          UNBLOCK_INPUT;
8903          return;
8904        }
8905    #endif
8906    
8907  #ifdef USE_X_TOOLKIT  #ifdef USE_X_TOOLKIT
8908    
8909    if (! FRAME_VISIBLE_P (f))    if (! FRAME_VISIBLE_P (f))
# Line 13575  x_free_frame_resources (f) Line 9038  x_free_frame_resources (f)
9038    
9039        free_frame_menubar (f);        free_frame_menubar (f);
9040  #else  /* !USE_X_TOOLKIT */  #else  /* !USE_X_TOOLKIT */
9041    
9042    #ifdef USE_GTK
9043          /* In the GTK version, tooltips are normal X
9044             frames.  We must check and free both types. */
9045          if (FRAME_GTK_OUTER_WIDGET (f))
9046            {
9047              gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
9048              FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow below */
9049              FRAME_GTK_OUTER_WIDGET (f) = 0;
9050            }
9051    #endif /* USE_GTK */
9052    
9053        if (FRAME_X_WINDOW (f))        if (FRAME_X_WINDOW (f))
9054          XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));          XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
9055  #endif /* !USE_X_TOOLKIT */  #endif /* !USE_X_TOOLKIT */
# Line 13604  x_free_frame_resources (f) Line 9079  x_free_frame_resources (f)
9079    
9080        if (FRAME_FACE_CACHE (f))        if (FRAME_FACE_CACHE (f))
9081          free_frame_faces (f);          free_frame_faces (f);
9082          
9083        x_free_gcs (f);        x_free_gcs (f);
9084        XFlush (FRAME_X_DISPLAY (f));        XFlush (FRAME_X_DISPLAY (f));
9085      }      }
# Line 13614  x_free_frame_resources (f) Line 9089  x_free_frame_resources (f)
9089    
9090    xfree (f->output_data.x);    xfree (f->output_data.x);
9091    f->output_data.x = NULL;    f->output_data.x = NULL;
9092      
9093    if (f == dpyinfo->x_focus_frame)    if (f == dpyinfo->x_focus_frame)
9094      dpyinfo->x_focus_frame = 0;      dpyinfo->x_focus_frame = 0;
9095    if (f == dpyinfo->x_focus_event_frame)    if (f == dpyinfo->x_focus_event_frame)
# Line 13660  x_destroy_window (f) Line 9135  x_destroy_window (f)
9135     FLAGS is the flags word to use--or 0 meaning preserve the flags     FLAGS is the flags word to use--or 0 meaning preserve the flags
9136     that the window now has.     that the window now has.
9137     If USER_POSITION is nonzero, we set the USPosition     If USER_POSITION is nonzero, we set the USPosition
9138     flag (this is useful when FLAGS is 0).  */     flag (this is useful when FLAGS is 0).
9139       The GTK version is in gtkutils.c  */
9140    
9141    #ifndef USE_GTK
9142  void  void
9143  x_wm_set_size_hint (f, flags, user_position)  x_wm_set_size_hint (f, flags, user_position)
9144       struct frame *f;       struct frame *f;
# Line 13674  x_wm_set_size_hint (f, flags, user_posit Line 9151  x_wm_set_size_hint (f, flags, user_posit
9151    Arg al[2];    Arg al[2];
9152    int ac = 0;    int ac = 0;
9153    Dimension widget_width, widget_height;    Dimension widget_width, widget_height;
9154    Window window = XtWindow (f->output_data.x->widget);  #endif
9155  #else /* not USE_X_TOOLKIT */  
9156    Window window = FRAME_X_WINDOW (f);    Window window = FRAME_OUTER_WINDOW (f);
 #endif /* not USE_X_TOOLKIT */  
9157    
9158    /* Setting PMaxSize caused various problems.  */    /* Setting PMaxSize caused various problems.  */
9159    size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;    size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
# Line 13804  x_wm_set_size_hint (f, flags, user_posit Line 9280  x_wm_set_size_hint (f, flags, user_posit
9280    XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);    XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
9281  #endif  #endif
9282  }  }
9283    #endif /* not USE_GTK */
9284    
9285  /* Used for IconicState or NormalState */  /* Used for IconicState or NormalState */
9286    
# Line 13835  x_wm_set_icon_pixmap (f, pixmap_id) Line 9312  x_wm_set_icon_pixmap (f, pixmap_id)
9312    Pixmap icon_pixmap;    Pixmap icon_pixmap;
9313    
9314  #ifndef USE_X_TOOLKIT  #ifndef USE_X_TOOLKIT
9315    Window window = FRAME_X_WINDOW (f);    Window window = FRAME_OUTER_WINDOW (f);
9316  #endif  #endif
9317    
9318    if (pixmap_id > 0)    if (pixmap_id > 0)
# Line 13868  x_wm_set_icon_pixmap (f, pixmap_id) Line 9345  x_wm_set_icon_pixmap (f, pixmap_id)
9345    }    }
9346    
9347  #else /* not USE_X_TOOLKIT */  #else /* not USE_X_TOOLKIT */
9348      
9349    f->output_data.x->wm_hints.flags |= IconPixmapHint;    f->output_data.x->wm_hints.flags |= IconPixmapHint;
9350    XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);    XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
9351    
# Line 13880  x_wm_set_icon_position (f, icon_x, icon_ Line 9357  x_wm_set_icon_position (f, icon_x, icon_
9357       struct frame *f;       struct frame *f;
9358       int icon_x, icon_y;       int icon_x, icon_y;
9359  {  {
9360  #ifdef USE_X_TOOLKIT    Window window = FRAME_OUTER_WINDOW (f);
   Window window = XtWindow (f->output_data.x->widget);  
 #else  
   Window window = FRAME_X_WINDOW (f);  
 #endif  
9361    
9362    f->output_data.x->wm_hints.flags |= IconPositionHint;    f->output_data.x->wm_hints.flags |= IconPositionHint;
9363    f->output_data.x->wm_hints.icon_x = icon_x;    f->output_data.x->wm_hints.icon_x = icon_x;
# Line 13980  x_list_fonts (f, pattern, size, maxnames Line 9453  x_list_fonts (f, pattern, size, maxnames
9453            XFontStruct *font;            XFontStruct *font;
9454            unsigned long value;            unsigned long value;
9455    
9456            font = XLoadQueryFont (dpy, XSTRING (pattern)->data);            font = XLoadQueryFont (dpy, SDATA (pattern));
9457            if (x_had_errors_p (dpy))            if (x_had_errors_p (dpy))
9458              {              {
9459                /* This error is perhaps due to insufficient memory on X                /* This error is perhaps due to insufficient memory on X
# Line 14023  x_list_fonts (f, pattern, size, maxnames Line 9496  x_list_fonts (f, pattern, size, maxnames
9496          {          {
9497            /* We try at least 10 fonts because XListFonts will return            /* We try at least 10 fonts because XListFonts will return
9498               auto-scaled fonts at the head.  */               auto-scaled fonts at the head.  */
9499            names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),            if (maxnames < 0)
9500                                &num_fonts);              {
9501                  int limit;
9502    
9503                  for (limit = 500;;)
9504                    {
9505                      names = XListFonts (dpy, SDATA (pattern), limit, &num_fonts);
9506                      if (num_fonts == limit)
9507                        {
9508                          BLOCK_INPUT;
9509                          XFreeFontNames (names);
9510                          UNBLOCK_INPUT;
9511                          limit *= 2;
9512                        }
9513                      else
9514                        break;
9515                    }
9516                }
9517              else
9518                names = XListFonts (dpy, SDATA (pattern), max (maxnames, 10),
9519                                    &num_fonts);
9520    
9521            if (x_had_errors_p (dpy))            if (x_had_errors_p (dpy))
9522              {              {
9523                /* This error is perhaps due to insufficient memory on X                /* This error is perhaps due to insufficient memory on X
# Line 14048  x_list_fonts (f, pattern, size, maxnames Line 9541  x_list_fonts (f, pattern, size, maxnames
9541                int width = 0;                int width = 0;
9542                char *p = names[i];                char *p = names[i];
9543                int average_width = -1, dashes = 0;                int average_width = -1, dashes = 0;
9544                  
9545                /* Count the number of dashes in NAMES[I].  If there are                /* Count the number of dashes in NAMES[I].  If there are
9546                   14 dashes, and the field value following 12th dash                   14 dashes, and the field value following 12th dash
9547                   (AVERAGE_WIDTH) is 0, this is a auto-scaled font which                   (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
# Line 14063  x_list_fonts (f, pattern, size, maxnames Line 9556  x_list_fonts (f, pattern, size, maxnames
9556                      else if (dashes == 12) /* AVERAGE_WIDTH field */                      else if (dashes == 12) /* AVERAGE_WIDTH field */
9557                        average_width = atoi (p);                        average_width = atoi (p);
9558                    }                    }
9559                  
9560                if (allow_scalable_fonts_p                if (allow_scalable_fonts_p
9561                    || dashes < 14 || average_width != 0)                    || dashes < 14 || average_width != 0)
9562                  {                  {
# Line 14083  x_list_fonts (f, pattern, size, maxnames Line 9576  x_list_fonts (f, pattern, size, maxnames
9576                      }                      }
9577                  }                  }
9578              }              }
9579              
9580            if (!try_XLoadQueryFont)            if (!try_XLoadQueryFont)
9581              {              {
9582                BLOCK_INPUT;                BLOCK_INPUT;
# Line 14124  x_list_fonts (f, pattern, size, maxnames Line 9617  x_list_fonts (f, pattern, size, maxnames
9617                BLOCK_INPUT;                BLOCK_INPUT;
9618                count = x_catch_errors (dpy);                count = x_catch_errors (dpy);
9619                thisinfo = XLoadQueryFont (dpy,                thisinfo = XLoadQueryFont (dpy,
9620                                           XSTRING (XCAR (tem))->data);                                           SDATA (XCAR (tem)));
9621                if (x_had_errors_p (dpy))                if (x_had_errors_p (dpy))
9622                  {                  {
9623                    /* This error is perhaps due to insufficient memory on X                    /* This error is perhaps due to insufficient memory on X
# Line 14183  x_list_fonts (f, pattern, size, maxnames Line 9676  x_list_fonts (f, pattern, size, maxnames
9676      }      }
9677    
9678    return newlist;    return newlist;
9679  }    }
9680    
9681    
9682  #if GLYPH_DEBUG  #if GLYPH_DEBUG
# Line 14202  x_check_font (f, font) Line 9695  x_check_font (f, font)
9695    xassert (font != NULL);    xassert (font != NULL);
9696    
9697    for (i = 0; i < dpyinfo->n_fonts; i++)    for (i = 0; i < dpyinfo->n_fonts; i++)
9698      if (dpyinfo->font_table[i].name      if (dpyinfo->font_table[i].name
9699          && font == dpyinfo->font_table[i].font)          && font == dpyinfo->font_table[i].font)
9700        break;        break;
9701    
# Line 14248  x_compute_min_glyph_bounds (f) Line 9741  x_compute_min_glyph_bounds (f)
9741    XFontStruct *font;    XFontStruct *font;
9742    int old_width = dpyinfo->smallest_char_width;    int old_width = dpyinfo->smallest_char_width;
9743    int old_height = dpyinfo->smallest_font_height;    int old_height = dpyinfo->smallest_font_height;
9744      
9745    dpyinfo->smallest_font_height = 100000;    dpyinfo->smallest_font_height = 100000;
9746    dpyinfo->smallest_char_width = 100000;    dpyinfo->smallest_char_width = 100000;
9747      
9748    for (i = 0; i < dpyinfo->n_fonts; ++i)    for (i = 0; i < dpyinfo->n_fonts; ++i)
9749      if (dpyinfo->font_table[i].name)      if (dpyinfo->font_table[i].name)
9750        {        {
9751          struct font_info *fontp = dpyinfo->font_table + i;          struct font_info *fontp = dpyinfo->font_table + i;
9752          int w, h;          int w, h;
9753            
9754          font = (XFontStruct *) fontp->font;          font = (XFontStruct *) fontp->font;
9755          xassert (font != (XFontStruct *) ~0);          xassert (font != (XFontStruct *) ~0);
9756          x_font_min_bounds (font, &w, &h);          x_font_min_bounds (font, &w, &h);
9757            
9758          dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);          dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
9759          dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);          dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
9760        }        }
# Line 14304  x_load_font (f, fontname, size) Line 9797  x_load_font (f, fontname, size)
9797          for (tail = font_names; CONSP (tail); tail = XCDR (tail))          for (tail = font_names; CONSP (tail); tail = XCDR (tail))
9798            if (dpyinfo->font_table[i].name            if (dpyinfo->font_table[i].name
9799                && (!strcmp (dpyinfo->font_table[i].name,                && (!strcmp (dpyinfo->font_table[i].name,
9800                             XSTRING (XCAR (tail))->data)                             SDATA (XCAR (tail)))
9801                    || !strcmp (dpyinfo->font_table[i].full_name,                    || !strcmp (dpyinfo->font_table[i].full_name,
9802                                XSTRING (XCAR (tail))->data)))                                SDATA (XCAR (tail)))))
9803              return (dpyinfo->font_table + i);              return (dpyinfo->font_table + i);
9804      }      }
9805    
# Line 14324  x_load_font (f, fontname, size) Line 9817  x_load_font (f, fontname, size)
9817         a bug of not finding a font even if the font surely exists and         a bug of not finding a font even if the font surely exists and
9818         is loadable by XLoadQueryFont.  */         is loadable by XLoadQueryFont.  */
9819      if (size > 0 && !NILP (font_names))      if (size > 0 && !NILP (font_names))
9820        fontname = (char *) XSTRING (XCAR (font_names))->data;        fontname = (char *) SDATA (XCAR (font_names));
9821    
9822      BLOCK_INPUT;      BLOCK_INPUT;
9823      count = x_catch_errors (FRAME_X_DISPLAY (f));      count = x_catch_errors (FRAME_X_DISPLAY (f));
# Line 14396  x_load_font (f, fontname, size) Line 9889  x_load_font (f, fontname, size)
9889    
9890          XFree (name);          XFree (name);
9891        }        }
9892        
9893      if (full_name != 0)      if (full_name != 0)
9894        fontp->full_name = full_name;        fontp->full_name = full_name;
9895      else      else
# Line 14528  x_find_ccl_program (fontp) Line 10021  x_find_ccl_program (fontp)
10021                    >= 0)))                    >= 0)))
10022          break;          break;
10023      }      }
10024      
10025    if (! NILP (list))    if (! NILP (list))
10026      {      {
10027        struct ccl_program *ccl        struct ccl_program *ccl
# Line 14573  static int x_initialized; Line 10066  static int x_initialized;
10066     the screen number from the server number.  */     the screen number from the server number.  */
10067  static int  static int
10068  same_x_server (name1, name2)  same_x_server (name1, name2)
10069       char *name1, *name2;       const char *name1, *name2;
10070  {  {
10071    int seen_colon = 0;    int seen_colon = 0;
10072    unsigned char *system_name = XSTRING (Vsystem_name)->data;    const unsigned char *system_name = SDATA (Vsystem_name);
10073    int system_name_length = strlen (system_name);    int system_name_length = strlen (system_name);
10074    int length_until_period = 0;    int length_until_period = 0;
10075    
# Line 14636  x_term_init (display_name, xrm_option, r Line 10129  x_term_init (display_name, xrm_option, r
10129        x_initialized = 1;        x_initialized = 1;
10130      }      }
10131    
10132    #ifdef USE_GTK
10133      {
10134    #define NUM_ARGV 10
10135        int argc;
10136        char *argv[NUM_ARGV];
10137        char **argv2 = argv;
10138        GdkAtom atom;
10139    
10140        /* GTK 2.0 can only handle one display, GTK 2.2 can handle more
10141           than one, but this remains to be implemented.  */
10142        if (x_initialized > 1)
10143          return 0;
10144    
10145        x_initialized++;
10146    
10147        for (argc = 0; argc < NUM_ARGV; ++argc)
10148          argv[argc] = 0;
10149    
10150        argc = 0;
10151        argv[argc++] = initial_argv[0];
10152    
10153        if (! NILP (display_name))
10154          {
10155            argv[argc++] = "--display";
10156            argv[argc++] = SDATA (display_name);
10157          }
10158    
10159        argv[argc++] = "--name";
10160        argv[argc++] = resource_name;
10161    
10162    #ifdef HAVE_X11R5
10163        XSetLocaleModifiers ("");
10164    #endif
10165    
10166        gtk_init (&argc, &argv2);
10167    
10168        /* gtk_init does set_locale.  We must fix locale after calling it.  */
10169        fixup_locale ();
10170        xg_initialize ();
10171    
10172        dpy = GDK_DISPLAY ();
10173    
10174        /* NULL window -> events for all windows go to our function */
10175        gdk_window_add_filter (NULL, event_handler_gdk, NULL);
10176    
10177        /* Load our own gtkrc if it exists.  */
10178        {
10179          struct gcpro gcpro1, gcpro2;
10180          char *file = "~/.emacs.d/gtkrc";
10181          Lisp_Object s, abs_file;
10182    
10183          GCPRO2 (s, abs_file);
10184          s = make_string (file, strlen (file));
10185          abs_file = Fexpand_file_name(s, Qnil);
10186    
10187          if (! NILP (abs_file) && Ffile_readable_p (abs_file))
10188            gtk_rc_parse (SDATA (abs_file));
10189    
10190          UNGCPRO;
10191        }
10192    
10193        XSetErrorHandler (x_error_handler);
10194        XSetIOErrorHandler (x_io_error_quitter);
10195      }
10196    #else /* not USE_GTK */
10197  #ifdef USE_X_TOOLKIT  #ifdef USE_X_TOOLKIT
10198    /* weiner@footloose.sps.mot.com reports that this causes    /* weiner@footloose.sps.mot.com reports that this causes
10199       errors with X11R5:       errors with X11R5:
# Line 14657  x_term_init (display_name, xrm_option, r Line 10215  x_term_init (display_name, xrm_option, r
10215          argv[argc++] = "-xrm";          argv[argc++] = "-xrm";
10216          argv[argc++] = xrm_option;          argv[argc++] = xrm_option;
10217        }        }
10218      dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,      turn_on_atimers (0);
10219        dpy = XtOpenDisplay (Xt_app_con, SDATA (display_name),
10220                           resource_name, EMACS_CLASS,                           resource_name, EMACS_CLASS,
10221                           emacs_options, XtNumber (emacs_options),                           emacs_options, XtNumber (emacs_options),
10222                           &argc, argv);                           &argc, argv);
10223        turn_on_atimers (1);
10224    
10225  #ifdef HAVE_X11XTR6  #ifdef HAVE_X11XTR6
10226      /* I think this is to compensate for XtSetLanguageProc.  */      /* I think this is to compensate for XtSetLanguageProc.  */
# Line 14672  x_term_init (display_name, xrm_option, r Line 10232  x_term_init (display_name, xrm_option, r
10232  #ifdef HAVE_X11R5  #ifdef HAVE_X11R5
10233    XSetLocaleModifiers ("");    XSetLocaleModifiers ("");
10234  #endif  #endif
10235    dpy = XOpenDisplay (XSTRING (display_name)->data);    dpy = XOpenDisplay (SDATA (display_name));
10236  #endif /* not USE_X_TOOLKIT */  #endif /* not USE_X_TOOLKIT */
10237    #endif /* not USE_GTK*/
10238    
10239    /* Detect failure.  */    /* Detect failure.  */
10240    if (dpy == 0)    if (dpy == 0)
# Line 14694  x_term_init (display_name, xrm_option, r Line 10255  x_term_init (display_name, xrm_option, r
10255    
10256      for (share = x_display_list, tail = x_display_name_list; share;      for (share = x_display_list, tail = x_display_name_list; share;
10257           share = share->next, tail = XCDR (tail))           share = share->next, tail = XCDR (tail))
10258        if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,        if (same_x_server (SDATA (XCAR (XCAR (tail))),
10259                           XSTRING (display_name)->data))                           SDATA (display_name)))
10260          break;          break;
10261      if (share)      if (share)
10262        dpyinfo->kboard = share->kboard;        dpyinfo->kboard = share->kboard;
# Line 14729  x_term_init (display_name, xrm_option, r Line 10290  x_term_init (display_name, xrm_option, r
10290    dpyinfo->next = x_display_list;    dpyinfo->next = x_display_list;
10291    x_display_list = dpyinfo;    x_display_list = dpyinfo;
10292    
10293    /* Put it on x_display_name_list as well, to keep them parallel.  */    /* Put it on x_display_name_list as well, to keep them parallel.  */
10294    x_display_name_list = Fcons (Fcons (display_name, Qnil),    x_display_name_list = Fcons (Fcons (display_name, Qnil),
10295                                 x_display_name_list);                                 x_display_name_list);
10296    dpyinfo->name_list_element = XCAR (x_display_name_list);    dpyinfo->name_list_element = XCAR (x_display_name_list);
# Line 14741  x_term_init (display_name, xrm_option, r Line 10302  x_term_init (display_name, xrm_option, r
10302  #endif /* ! 0 */  #endif /* ! 0 */
10303    
10304    dpyinfo->x_id_name    dpyinfo->x_id_name
10305      = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))      = (char *) xmalloc (SBYTES (Vinvocation_name)
10306                          + STRING_BYTES (XSTRING (Vsystem_name))                          + SBYTES (Vsystem_name)
10307                          + 2);                          + 2);
10308    sprintf (dpyinfo->x_id_name, "%s@%s",    sprintf (dpyinfo->x_id_name, "%s@%s",
10309             XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);             SDATA (Vinvocation_name), SDATA (Vsystem_name));
10310    
10311    /* Figure out which modifier bits mean what.  */    /* Figure out which modifier bits mean what.  */
10312    x_find_modifier_meanings (dpyinfo);    x_find_modifier_meanings (dpyinfo);
# Line 14808  x_term_init (display_name, xrm_option, r Line 10369  x_term_init (display_name, xrm_option, r
10369                                            build_string ("PrivateColormap"),                                            build_string ("PrivateColormap"),
10370                                            Qnil, Qnil);                                            Qnil, Qnil);
10371            if (STRINGP (value)            if (STRINGP (value)
10372                && (!strcmp (XSTRING (value)->data, "true")                && (!strcmp (SDATA (value), "true")
10373                    || !strcmp (XSTRING (value)->data, "on")))                    || !strcmp (SDATA (value), "on")))
10374              dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);              dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
10375          }          }
10376      }      }
10377    else    else
10378      dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,      dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
10379                                       dpyinfo->visual, AllocNone);                                       dpyinfo->visual, AllocNone);
10380          
10381    {    {
10382      int screen_number = XScreenNumberOfScreen (dpyinfo->screen);      int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
10383      double pixels = DisplayHeight (dpyinfo->display, screen_number);      double pixels = DisplayHeight (dpyinfo->display, screen_number);
# Line 14826  x_term_init (display_name, xrm_option, r Line 10387  x_term_init (display_name, xrm_option, r
10387      mm = DisplayWidthMM (dpyinfo->display, screen_number);      mm = DisplayWidthMM (dpyinfo->display, screen_number);
10388      dpyinfo->resx = pixels * 25.4 / mm;      dpyinfo->resx = pixels * 25.4 / mm;
10389    }    }
10390      
10391    dpyinfo->Xatom_wm_protocols    dpyinfo->Xatom_wm_protocols
10392      = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);      = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
10393    dpyinfo->Xatom_wm_take_focus    dpyinfo->Xatom_wm_take_focus
# Line 14851  x_term_init (display_name, xrm_option, r Line 10412  x_term_init (display_name, xrm_option, r
10412      = XInternAtom (dpyinfo->display, "TEXT", False);      = XInternAtom (dpyinfo->display, "TEXT", False);
10413    dpyinfo->Xatom_COMPOUND_TEXT    dpyinfo->Xatom_COMPOUND_TEXT
10414      = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);      = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
10415      dpyinfo->Xatom_UTF8_STRING
10416        = XInternAtom (dpyinfo->display, "UTF8_STRING", False);
10417    dpyinfo->Xatom_DELETE    dpyinfo->Xatom_DELETE
10418      = XInternAtom (dpyinfo->display, "DELETE", False);      = XInternAtom (dpyinfo->display, "DELETE", False);
10419    dpyinfo->Xatom_MULTIPLE    dpyinfo->Xatom_MULTIPLE
# Line 14878  x_term_init (display_name, xrm_option, r Line 10441  x_term_init (display_name, xrm_option, r
10441    /* Ghostscript support.  */    /* Ghostscript support.  */
10442    dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);    dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
10443    dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);    dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
10444      
10445    dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",    dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
10446                                            False);                                            False);
10447    
# Line 14893  x_term_init (display_name, xrm_option, r Line 10456  x_term_init (display_name, xrm_option, r
10456      null_bits[0] = 0x00;      null_bits[0] = 0x00;
10457    
10458      dpyinfo->null_pixel      dpyinfo->null_pixel
10459        = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,        = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
10460                                       null_bits, 1, 1, (long) 0, (long) 0,                                       null_bits, 1, 1, (long) 0, (long) 0,
10461                                       1);                                       1);
10462    }    }
# Line 14911  x_term_init (display_name, xrm_option, r Line 10474  x_term_init (display_name, xrm_option, r
10474  #ifdef HAVE_X_I18N  #ifdef HAVE_X_I18N
10475    xim_initialize (dpyinfo, resource_name);    xim_initialize (dpyinfo, resource_name);
10476  #endif  #endif
10477      
10478  #ifdef subprocesses  #ifdef subprocesses
10479    /* This is only needed for distinguishing keyboard and process input.  */    /* This is only needed for distinguishing keyboard and process input.  */
10480    if (connection != 0)    if (connection != 0)
# Line 14943  x_term_init (display_name, xrm_option, r Line 10506  x_term_init (display_name, xrm_option, r
10506      XrmValue d, fr, to;      XrmValue d, fr, to;
10507      Font font;      Font font;
10508      int count;      int count;
10509        
10510      d.addr = (XPointer)&dpy;      d.addr = (XPointer)&dpy;
10511      d.size = sizeof (Display *);      d.size = sizeof (Display *);
10512      fr.addr = XtDefaultFont;      fr.addr = XtDefaultFont;
# Line 14969  x_term_init (display_name, xrm_option, r Line 10532  x_term_init (display_name, xrm_option, r
10532                                      build_string ("Synchronous"),                                      build_string ("Synchronous"),
10533                                      Qnil, Qnil);                                      Qnil, Qnil);
10534      if (STRINGP (value)      if (STRINGP (value)
10535          && (!strcmp (XSTRING (value)->data, "true")          && (!strcmp (SDATA (value), "true")
10536              || !strcmp (XSTRING (value)->data, "on")))              || !strcmp (SDATA (value), "on")))
10537        XSynchronize (dpyinfo->display, True);        XSynchronize (dpyinfo->display, True);
10538    }    }
10539      
10540    UNBLOCK_INPUT;    UNBLOCK_INPUT;
10541    
10542    return dpyinfo;    return dpyinfo;
# Line 15036  x_delete_display (dpyinfo) Line 10599  x_delete_display (dpyinfo)
10599    if (dpyinfo->xim)    if (dpyinfo->xim)
10600      xim_close_dpy (dpyinfo);      xim_close_dpy (dpyinfo);
10601  #endif  #endif
10602      
10603    xfree (dpyinfo->font_table);    xfree (dpyinfo->font_table);
10604    xfree (dpyinfo->x_id_name);    xfree (dpyinfo->x_id_name);
10605    xfree (dpyinfo->color_cells);    xfree (dpyinfo->color_cells);
10606    xfree (dpyinfo);    xfree (dpyinfo);
10607  }  }
10608    
10609    #ifdef USE_X_TOOLKIT
10610    
10611    /* Atimer callback function for TIMER.  Called every 0.1s to process
10612       Xt timeouts, if needed.  We must avoid calling XtAppPending as
10613       much as possible because that function does an implicit XFlush
10614       that slows us down.  */
10615    
10616    static void
10617    x_process_timeouts (timer)
10618         struct atimer *timer;
10619    {
10620      if (toolkit_scroll_bar_interaction || popup_activated ())
10621        {
10622          BLOCK_INPUT;
10623          while (XtAppPending (Xt_app_con) & XtIMTimer)
10624            XtAppProcessEvent (Xt_app_con, XtIMTimer);
10625          UNBLOCK_INPUT;
10626        }
10627    }
10628    
10629    #endif /* USE_X_TOOLKIT */
10630    
10631    
10632  /* Set up use of X before we make the first connection.  */  /* Set up use of X before we make the first connection.  */
10633    
10634    extern frame_parm_handler x_frame_parm_handlers[];
10635    
10636  static struct redisplay_interface x_redisplay_interface =  static struct redisplay_interface x_redisplay_interface =
10637  {  {
10638      x_frame_parm_handlers,
10639    x_produce_glyphs,    x_produce_glyphs,
10640    x_write_glyphs,    x_write_glyphs,
10641    x_insert_glyphs,    x_insert_glyphs,
# Line 15056  static struct redisplay_interface x_redi Line 10644  static struct redisplay_interface x_redi
10644    x_after_update_window_line,    x_after_update_window_line,
10645    x_update_window_begin,    x_update_window_begin,
10646    x_update_window_end,    x_update_window_end,
10647    XTcursor_to,    x_cursor_to,
10648      x_flush,
10649    #ifndef XFlush
10650    x_flush,    x_flush,
10651    x_clear_mouse_face,  #else
10652      0,  /* flush_display_optional */
10653    #endif
10654      x_clear_window_mouse_face,
10655    x_get_glyph_overhangs,    x_get_glyph_overhangs,
10656    x_fix_overlapping_area    x_fix_overlapping_area,
10657      x_draw_fringe_bitmap,
10658      x_per_char_metric,
10659      x_encode_char,
10660      x_compute_glyph_string_overhangs,
10661      x_draw_glyph_string,
10662      x_define_frame_cursor,
10663      x_clear_frame_area,
10664      x_draw_window_cursor,
10665      x_draw_vertical_window_border,
10666      x_shift_glyphs_for_insert
10667  };  };
10668    
10669  void  void
# Line 15086  x_initialize () Line 10689  x_initialize ()
10689    condemn_scroll_bars_hook = XTcondemn_scroll_bars;    condemn_scroll_bars_hook = XTcondemn_scroll_bars;
10690    redeem_scroll_bar_hook = XTredeem_scroll_bar;    redeem_scroll_bar_hook = XTredeem_scroll_bar;
10691    judge_scroll_bars_hook = XTjudge_scroll_bars;    judge_scroll_bars_hook = XTjudge_scroll_bars;
   estimate_mode_line_height_hook = x_estimate_mode_line_height;  
10692    
10693    scroll_region_ok = 1;         /* we'll scroll partial frames */    scroll_region_ok = 1;         /* we'll scroll partial frames */
10694    char_ins_del_ok = 1;    char_ins_del_ok = 1;
# Line 15099  x_initialize () Line 10701  x_initialize ()
10701    x_noop_count = 0;    x_noop_count = 0;
10702    last_tool_bar_item = -1;    last_tool_bar_item = -1;
10703    any_help_event_p = 0;    any_help_event_p = 0;
10704      
10705    /* Try to use interrupt input; if we can't, then start polling.  */    /* Try to use interrupt input; if we can't, then start polling.  */
10706    Fset_input_mode (Qt, Qnil, Qt, Qnil);    Fset_input_mode (Qt, Qnil, Qt, Qnil);
10707    
# Line 15107  x_initialize () Line 10709  x_initialize ()
10709    XtToolkitInitialize ();    XtToolkitInitialize ();
10710    
10711    Xt_app_con = XtCreateApplicationContext ();    Xt_app_con = XtCreateApplicationContext ();
10712      
10713    /* Register a converter from strings to pixels, which uses    /* Register a converter from strings to pixels, which uses
10714       Emacs' color allocation infrastructure.  */       Emacs' color allocation infrastructure.  */
10715    XtAppSetTypeConverter (Xt_app_con,    XtAppSetTypeConverter (Xt_app_con,
# Line 15129  x_initialize () Line 10731  x_initialize ()
10731      start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);      start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
10732    }    }
10733  #endif  #endif
10734      
10735  #ifdef USE_TOOLKIT_SCROLL_BARS  #ifdef USE_TOOLKIT_SCROLL_BARS
10736    #ifndef USE_GTK
10737    xaw3d_arrow_scroll = False;    xaw3d_arrow_scroll = False;
10738    xaw3d_pick_top = True;    xaw3d_pick_top = True;
10739  #endif  #endif
10740    #endif
10741    
10742    /* Note that there is no real way portable across R3/R4 to get the    /* Note that there is no real way portable across R3/R4 to get the
10743       original error handler.  */       original error handler.  */
# Line 15176  syms_of_xterm () Line 10780  syms_of_xterm ()
10780    staticpro (&last_mouse_press_frame);    staticpro (&last_mouse_press_frame);
10781    last_mouse_press_frame = Qnil;    last_mouse_press_frame = Qnil;
10782    
   help_echo = Qnil;  
   staticpro (&help_echo);  
   help_echo_object = Qnil;  
   staticpro (&help_echo_object);  
   help_echo_window = Qnil;  
   staticpro (&help_echo_window);  
   previous_help_echo = Qnil;  
   staticpro (&previous_help_echo);  
   help_echo_pos = -1;  
   
   DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,  
     doc: /* *Non-nil means autoselect window with mouse pointer.  */);  
   mouse_autoselect_window = 0;  
   
   DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,  
     doc: /* *Non-nil means draw block cursor as wide as the glyph under it.  
 For example, if a block cursor is over a tab, it will be drawn as  
 wide as that tab on the display.  */);  
   x_stretch_cursor_p = 0;  
   
10783    DEFVAR_BOOL ("x-use-underline-position-properties",    DEFVAR_BOOL ("x-use-underline-position-properties",
10784                 &x_use_underline_position_properties,                 &x_use_underline_position_properties,
10785       doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.       doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
# Line 15213  Otherwise, value is a symbol describing Line 10797  Otherwise, value is a symbol describing
10797    Vx_toolkit_scroll_bars = intern ("motif");    Vx_toolkit_scroll_bars = intern ("motif");
10798  #elif defined HAVE_XAW3D  #elif defined HAVE_XAW3D
10799    Vx_toolkit_scroll_bars = intern ("xaw3d");    Vx_toolkit_scroll_bars = intern ("xaw3d");
10800    #elif USE_GTK
10801      Vx_toolkit_scroll_bars = intern ("gtk");
10802  #else  #else
10803    Vx_toolkit_scroll_bars = intern ("xaw");    Vx_toolkit_scroll_bars = intern ("xaw");
10804  #endif  #endif
# Line 15222  Otherwise, value is a symbol describing Line 10808  Otherwise, value is a symbol describing
10808    
10809    staticpro (&last_mouse_motion_frame);    staticpro (&last_mouse_motion_frame);
10810    last_mouse_motion_frame = Qnil;    last_mouse_motion_frame = Qnil;
10811      
10812    Qmodifier_value = intern ("modifier-value");    Qmodifier_value = intern ("modifier-value");
10813    Qalt = intern ("alt");    Qalt = intern ("alt");
10814    Fput (Qalt, Qmodifier_value, make_number (alt_modifier));    Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
# Line 15232  Otherwise, value is a symbol describing Line 10818  Otherwise, value is a symbol describing
10818    Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));    Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
10819    Qsuper = intern ("super");    Qsuper = intern ("super");
10820    Fput (Qsuper, Qmodifier_value, make_number (super_modifier));    Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
10821      
10822    DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,    DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,
10823      doc: /* Which keys Emacs uses for the alt modifier.      doc: /* Which keys Emacs uses for the alt modifier.
10824  This should be one of the symbols `alt', `hyper', `meta', `super'.  This should be one of the symbols `alt', `hyper', `meta', `super'.
10825  For example, `alt' means use the Alt_L and Alt_R keysyms.  The default  For example, `alt' means use the Alt_L and Alt_R keysyms.  The default
10826  is nil, which is the same as `alt'.  */);  is nil, which is the same as `alt'.  */);
10827    Vx_alt_keysym = Qnil;    Vx_alt_keysym = Qnil;
10828      
10829    DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym,    DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym,
10830      doc: /* Which keys Emacs uses for the hyper modifier.      doc: /* Which keys Emacs uses for the hyper modifier.
10831  This should be one of the symbols `alt', `hyper', `meta', `super'.  This should be one of the symbols `alt', `hyper', `meta', `super'.
10832  For example, `hyper' means use the Hyper_L and Hyper_R keysyms.  The  For example, `hyper' means use the Hyper_L and Hyper_R keysyms.  The
10833  default is nil, which is the same as `hyper'.  */);  default is nil, which is the same as `hyper'.  */);
10834    Vx_hyper_keysym = Qnil;    Vx_hyper_keysym = Qnil;
10835      
10836    DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym,    DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym,
10837      doc: /* Which keys Emacs uses for the meta modifier.      doc: /* Which keys Emacs uses for the meta modifier.
10838  This should be one of the symbols `alt', `hyper', `meta', `super'.  This should be one of the symbols `alt', `hyper', `meta', `super'.
10839  For example, `meta' means use the Meta_L and Meta_R keysyms.  The  For example, `meta' means use the Meta_L and Meta_R keysyms.  The
10840  default is nil, which is the same as `meta'.  */);  default is nil, which is the same as `meta'.  */);
10841    Vx_meta_keysym = Qnil;    Vx_meta_keysym = Qnil;
10842      
10843    DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym,    DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym,
10844      doc: /* Which keys Emacs uses for the super modifier.      doc: /* Which keys Emacs uses for the super modifier.
10845  This should be one of the symbols `alt', `hyper', `meta', `super'.  This should be one of the symbols `alt', `hyper', `meta', `super'.
# Line 15261  For example, `super' means use the Super Line 10847  For example, `super' means use the Super
10847  default is nil, which is the same as `super'.  */);  default is nil, which is the same as `super'.  */);
10848    Vx_super_keysym = Qnil;    Vx_super_keysym = Qnil;
10849    
10850      DEFVAR_LISP ("x-keysym-table", &Vx_keysym_table,
10851        doc: /* Hash table of character codes indexed by X keysym codes.  */);
10852      Vx_keysym_table = make_hash_table (Qeql, make_number (900),
10853                                         make_float (DEFAULT_REHASH_SIZE),
10854                                         make_float (DEFAULT_REHASH_THRESHOLD),
10855                                         Qnil, Qnil, Qnil);
10856  }  }
10857    
10858  #endif /* HAVE_X_WINDOWS */  #endif /* HAVE_X_WINDOWS */

Legend:
Removed from v.1.735  
changed lines
  Added in v.1.735.2.1

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26