home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / lemacs-19.6 / src / xterm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-24  |  69.5 KB  |  2,608 lines

  1. /* X Communication module for terminals which understand the X protocol.
  2.    Copyright (C) 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Emacs.
  5.  
  6. GNU Emacs is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU Emacs is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "config.h"
  21. #include "lisp.h"
  22.  
  23. #include <stdio.h>
  24. #include <X11/Xlib.h>
  25. #include <X11/Xmu/Error.h>
  26. #include <X11/IntrinsicP.h>    /* CoreP.h needs this */
  27. #include <X11/CoreP.h>        /* foul, but we need this to use our own
  28.                    window inside a widget instead of one 
  29.                    that Xt creates... */
  30. #include "EmacsShellP.h"
  31. #include "ScreenWidget.h"
  32.  
  33. #include "hash.h"
  34.  
  35. extern XtAppContext Xt_app_con;
  36. extern Widget Xt_app_shell;
  37.  
  38. #ifdef HAVE_X_WINDOWS
  39.  
  40. /* On 4.3 this loses if it comes after xterm.h.  */
  41. #include <signal.h>
  42.  
  43. /* This may include sys/types.h, and that somehow loses
  44.    if this is not done before the other system files.  */
  45. #include "xterm.h"
  46.  
  47. #include "lwlib.h"
  48.  
  49. /* Load sys/types.h if not already loaded.
  50.    In some systems loading it twice is suicidal.  */
  51. #ifndef makedev
  52. #include <sys/types.h>
  53. #endif
  54.  
  55. #ifdef O_NDELAY
  56. #undef O_NDELAY
  57. #endif
  58. #include <fcntl.h>
  59. #include <stdio.h>
  60. #include <ctype.h>
  61. #include <errno.h>
  62. #include <setjmp.h>
  63. #ifdef BSD
  64. #include <sys/ioctl.h>
  65. #include <strings.h>
  66. #else
  67. #include <sys/termio.h>
  68. #include <string.h>
  69. #endif
  70. #include <sys/stat.h>
  71. #include <sys/param.h>
  72.  
  73. #include "termhooks.h"
  74. #include "termopts.h"
  75. #include "termchar.h"
  76. #include "buffer.h"
  77. #include "screen.h"
  78. #include "disptab.h"
  79. #include "window.h"
  80. #include "bitmaps.h"
  81.  
  82. #include "events.h"
  83.  
  84. extern void emacs_Xt_make_event_stream ();
  85.  
  86.  
  87. #define min(a,b) ((a)<(b) ? (a) : (b))
  88. #define max(a,b) ((a)>(b) ? (a) : (b))
  89. #define focus_cursor_p(s) \
  90.     (((s) == selected_screen) && ((s)->display.x->focus_p))
  91.  
  92.  
  93. /* Nonzero after BLOCK_INPUT; prevents input events from being
  94.    processed until later.  */
  95. int x_input_blocked;
  96.  
  97. #if defined (SIGIO) && defined (FIONREAD)
  98. int BLOCK_INPUT_mask;
  99. #endif
  100.  
  101.  
  102. /* Stuff for dealing with the title. */
  103. extern Lisp_Object Vinvocation_name;
  104. static char *hostname, *id_name;
  105.  
  106. /* This is the X connection that we are using.  */
  107. Display *x_current_display;
  108.  
  109.  
  110. /* File descriptor of the X connection.  Used in sysdep.c to set the
  111.    X connection in SIGIO mode.  */
  112. int x_file_descriptor;
  113.  
  114. /* Screen being updated by update_screen.
  115.    
  116.    This is set by XTupdate_begin and looked at by all the
  117.    XT functions.  It is zero while not inside an update.
  118.    In that case, the XT functions assume that `selected_screen'
  119.    is the screen to apply to.  */
  120. static struct screen *updating_screen;
  121.  
  122. /* During an update, maximum vpos which ins/del of lines
  123.    may affect.  This is  specified by higher levels.
  124.  
  125.    This is the number of lines, from the top of screen downwards,
  126.    which can participate in insert-line/delete-line operations.
  127.  
  128.    Effectively it excludes the bottom screen_height - specified_window_size
  129.    lines from those operations.  */
  130. static int update_height;
  131.  
  132. /* Number of pixels below each line. */
  133. int x_interline_space;
  134.  
  135. /* Tells if a window manager is present or not. */
  136. extern Lisp_Object Vx_no_window_manager;
  137.  
  138. /* Timestamp that we requested selection data was made. */
  139. extern Time requestor_time;
  140.  
  141. /* ID of the window requesting selection data. */
  142. extern Window requestor_window;
  143.  
  144. /* Nonzero enables some debugging for the X interface code. */
  145. extern int _Xdebug;
  146.  
  147. extern int errno;
  148.  
  149. extern Lisp_Object Vglobal_minibuffer_screen;
  150.  
  151. extern Display *XOpenDisplay ();
  152. extern Window XCreateWindow ();
  153.  
  154. extern Cursor XCreateCursor ();
  155. extern FONT_TYPE *XOpenFont ();
  156.  
  157. void
  158. x_lower_screen (struct screen* s);
  159. void
  160. x_make_screen_visible (struct screen *s);
  161.  
  162. void
  163. x_raise_screen (struct screen* s, int force);
  164.  
  165. #ifdef LINE_INFO_COLUMN
  166. void x_draw_lineinfo_border(), x_clear_lineinfo_glyph();
  167. #endif
  168.  
  169. extern struct screen *
  170. x_any_window_to_screen (Window);
  171.  
  172. static int x_display_cursor ();
  173.  
  174. /* Remember if the last cursor displayed was a bar or a box */
  175. static Lisp_Object last_bar_cursor;
  176.  
  177. extern Lisp_Object Vbar_cursor;
  178.  
  179.  
  180. static void
  181. erase_screen_cursor_if_needed (s)
  182.      struct screen *s;
  183. {
  184.   if (!s->cursor_erased)
  185.     {
  186.       s->cursor_erased = 1;
  187.       s->cursor_erased =
  188.     x_display_cursor (s, 0);
  189.     }
  190. }
  191.  
  192. static void
  193. erase_cursor_if_needed ()
  194. {
  195.   erase_screen_cursor_if_needed (updating_screen
  196.                  ? updating_screen
  197.                  : selected_screen);
  198. }
  199.  
  200. #define UP_TO_EOL ~0
  201.  
  202. static void
  203. erase_screen_cursor_if_needed_and_in_region (s, x, y, n)
  204.      struct screen *s;
  205.      int x, y, n;
  206. {
  207.   if (!s->cursor_erased && s->phys_cursor_y == y
  208.       && x <= s->phys_cursor_x
  209.       && (n == UP_TO_EOL || s->phys_cursor_x <= x + n))
  210.     {
  211.       s->cursor_erased = 1;
  212.       s->cursor_erased =
  213.     x_display_cursor (s, 0);
  214.     }
  215. }
  216.  
  217. static void
  218. draw_screen_cursor_if_needed (s)
  219.      struct screen *s;
  220. {
  221.   if (s->cursor_erased)
  222.     {
  223.       s->cursor_erased =
  224.     !x_display_cursor (s, 1);
  225.     }
  226. }
  227.  
  228. /* These hooks are called by update_screen at the beginning and end
  229.    of a screen update.  We record in `updating_screen' the identity
  230.    of the screen being updated, so that the XT... functions do not
  231.    need to take a screen as argument.  Most of the XT... functions
  232.    should never be called except during an update, the only exceptions
  233.    being XTcursor_to, and XTwrite_glyphs.  */
  234.  
  235. static void
  236. XTupdate_begin (s)
  237.      struct screen *s;
  238. {    
  239.   updating_screen = s;
  240.   update_height = s->height;
  241.  
  242.   if (last_bar_cursor != Vbar_cursor)
  243.     s->cursor_erased = x_display_cursor (s, 0);
  244.  
  245. #ifdef ENERGIZE
  246.   BLOCK_INPUT;
  247. #if 0
  248.  *  xc_begin_note_update (s->display.x->edit_widget);
  249. #endif
  250.   UNBLOCK_INPUT;
  251. #endif
  252. }
  253.  
  254. extern Lisp_Object text_part_sym;
  255. extern Lisp_Object modeline_part_sym;
  256.  
  257. enum window_type
  258. {
  259.   scrollbar_window,
  260.   text_window
  261. };
  262.  
  263. /* Nonzero when emacs is garbage-collecting. */
  264. extern int gc_in_progress;
  265.  
  266. static void
  267. XTupdate_end (s)
  268.      struct screen *s;
  269. {    
  270.   BLOCK_INPUT;
  271. #ifdef ENERGIZE
  272. #if 0
  273.  *  xc_flush_note_update (s->display.x->edit_widget);
  274. #endif
  275. #endif
  276.   /*  adjust_scrollbars (s);*/
  277.  
  278.   draw_screen_cursor_if_needed (s);
  279.   updating_screen = 0;
  280.  
  281.   XFlushQueue ();
  282.   UNBLOCK_INPUT;
  283. }
  284.  
  285. /* Set the nominal cursor position of the screen:
  286.    where display update commands will take effect.
  287.    This does not affect the place where the cursor-box is displayed.  */
  288.  
  289. static void
  290. XTcursor_to (row, col)
  291.      int row, col;
  292. {
  293.   struct screen* s = updating_screen ? updating_screen : selected_screen;
  294.  
  295.   if (s->phys_cursor_x != col || s->phys_cursor_y != row)
  296.     {
  297.       if (updating_screen == 0)
  298.     {
  299.       erase_screen_cursor_if_needed (s);
  300.       s->cursor_x = col;
  301.       s->cursor_y = row;
  302.       s->phys_cursor_x = col;
  303.       s->phys_cursor_y = row;
  304.       draw_screen_cursor_if_needed (s);
  305.       BLOCK_INPUT;
  306.       XFlushQueue ();
  307.       UNBLOCK_INPUT;
  308.     }
  309.       else
  310.     {    
  311.       erase_screen_cursor_if_needed (s);
  312.       s->phys_cursor_x = col;
  313.       s->phys_cursor_y = row;
  314.     }
  315.     }
  316. }
  317.  
  318.  
  319.  
  320. #ifdef ENERGIZE
  321. static void
  322. notify_note_update (Widget parent, int x, int y, int width, int height)
  323. {
  324. #if 0
  325.  *  disable_strict_free_check ();
  326.  *  BLOCK_INPUT;
  327.  *  xc_note_xywh_updated (parent, x, y, width, height);
  328.  *  UNBLOCK_INPUT;
  329.  *  enable_strict_free_check ();
  330. #endif
  331. }
  332. #endif /* ENERGIZE */
  333.  
  334.  
  335. static int really_abort;
  336. static void
  337. maybe_abort ()
  338. {
  339.   if (really_abort) abort();
  340. }
  341.  
  342. int
  343. x_write_glyphs (s, left, top, n, force_gc, box_p)
  344.      struct screen *s;
  345.      int left, top, n;
  346.      GC force_gc;
  347.      int box_p;
  348. {
  349.   Widget widget = s->display.x->edit_widget;
  350.   Window x_win = XtWindow (widget);
  351.   int pix_x = s->current_glyphs->top_left_x[top];
  352.   int pix_y = s->current_glyphs->top_left_y[top];
  353. #if 0
  354.   int line_height = (s->current_glyphs->pix_height[top]);
  355. #else
  356.   int line_height = s->display.x->text_height;
  357. #endif
  358.   int max_ascent = s->current_glyphs->max_ascent[top];
  359.   struct run *face_list = s->current_glyphs->face_list[top];
  360.   int this_run;
  361.   int run_len;
  362.   int this_run_len, this_pix_len;
  363.   XFontStruct *this_font;
  364.   GC drawing_gc;
  365.   GLYPH *gp;
  366.   char *buf;
  367.   char *cp;
  368.  
  369.   /* don't do anything if nothing needs to be drawn */
  370.   if (n <= 0)
  371.     return 0;
  372.  
  373.   if (top >= s->height
  374.       || top < 0
  375.       || s->current_glyphs->used[top] == 0
  376.       || s->current_glyphs->enable[top] == 0
  377.       || left >= s->current_glyphs->used[top]
  378.       || n < 0
  379.       || !face_list)
  380.     /* calling abort () here maks emacs19 unusable under Energize.
  381.        I try it in a mode where the bug is plainly ignored by returning 
  382.        instead */
  383.     return 0;
  384.  
  385.   erase_screen_cursor_if_needed_and_in_region (s, left, top, n);
  386.  
  387.   buf = (char *) alloca (s->current_glyphs->used[top] + 1);
  388.   cp = buf;
  389.  
  390.   /* Advance to the correct run. */
  391.   this_run = run_len = 0;
  392.   while (left >= run_len + face_list[this_run].length)
  393.     {
  394.       run_len += face_list[this_run].length;
  395.       pix_x += face_list[this_run].pix_length;
  396.       this_run++;
  397.  
  398.       /* check for end of runs */
  399.       if (this_run >= s->current_glyphs->nruns [top])
  400.     return 0;
  401.     }
  402.  
  403.   /* If we're starting at the beginning of the line, don't skip over the
  404.      lineinfo run. */
  405. #if 0
  406.  *  if (this_run > 0 &&
  407.  *      left == 0 &&
  408.  *      /* !force_gc && */
  409.  *      face_list[this_run-1].type == column_glyph &&
  410.  *      pix_x == s->current_glyphs->top_left_x[top])
  411.  *    this_run--;
  412. #endif
  413.  
  414.   this_run_len = face_list[this_run].length;
  415.   this_pix_len = face_list[this_run].pix_length;
  416.   this_font = face_list[this_run].faceptr->font;
  417.   if (! this_font)
  418.     this_font = SCREEN_NORMAL_FACE (s).font;
  419.  
  420.   BLOCK_INPUT;
  421.  
  422. /*
  423.   if (this_run == 0 || this_run == 1) 
  424.     x_clear_lineinfo_glyph (s, top);
  425. */
  426.  
  427.   if (force_gc)
  428.     {
  429.       drawing_gc = force_gc;
  430.       XSetFont (x_current_display, drawing_gc, this_font->fid);
  431.     }
  432.   else
  433.     if (! (drawing_gc = face_list[this_run].faceptr->facegc))
  434.       if (face_list[this_run].faceptr->hilited)
  435.     drawing_gc = s->display.x->reverse_gc;
  436.       else
  437.     drawing_gc = s->display.x->normal_gc;
  438.  
  439.   /* If we're starting in the middle of a run, get to the proper offset. */
  440.   if (face_list[this_run].type == font && left > run_len)
  441.     {
  442.       int len = left - run_len;
  443.       int l = len;
  444.  
  445.       gp = &s->current_glyphs->glyphs[top][run_len];
  446.       cp = buf;
  447.       while (l--)
  448.     if (*gp == TABGLYPH)
  449.       {
  450.         *cp++ = ' ';
  451.         gp++;
  452.       }
  453.     else
  454.       *cp++ = 0377 & *gp++;
  455.       this_run_len -= len;
  456.       pix_x += XTextWidth (this_font, buf, len);
  457.     }
  458.  
  459.    while (1)
  460.     {
  461.       switch (face_list[this_run].type)
  462.     {
  463.     case font:
  464.       {
  465.         int len = min (this_run_len, n);
  466.         int l = len;
  467.         
  468.         gp = &s->current_glyphs->glyphs[top][left];
  469.         cp = buf;
  470.         while (l--)
  471.           if (*gp == TABGLYPH)
  472.         {
  473.           *cp++ = ' ';
  474.           gp++;
  475.         }
  476.           else
  477.         *cp++ = 0377 & *gp++;
  478.         
  479.         left += len;
  480.         n -= len;
  481.         this_run_len -= len;
  482.  
  483.         this_pix_len = XTextWidth (this_font, buf, len);
  484.  
  485.         if ((this_font->ascent + this_font->descent) < line_height)
  486.           XClearArea (x_current_display, x_win, pix_x, pix_y, this_pix_len,
  487.               line_height, False);
  488.  
  489.         if (face_list[this_run].faceptr->back_pixmap &&
  490.         face_list[this_run].faceptr->back_pixmap != (~0))
  491.           {
  492.         if (force_gc)
  493.           {
  494.             if (box_p)
  495.               {        /* The hollow cursor with a stipple */
  496.             XGCValues values;
  497.  
  498.             if (! XGetGCValues (x_current_display, drawing_gc,
  499.                         GCBackground | GCForeground,
  500.                         &values))
  501.               abort ();
  502.             XDrawString (x_current_display, x_win,
  503.                       (face_list[this_run].faceptr->facegc
  504.                        ? face_list[this_run].faceptr->facegc
  505.                        : (face_list[this_run].faceptr->hilited
  506.                           ? s->display.x->reverse_gc
  507.                           : s->display.x->normal_gc)),
  508.                       pix_x, pix_y + max_ascent, buf, len);
  509.             XSetForeground (x_current_display, drawing_gc,
  510.                     values.background);
  511.             XDrawRectangle (x_current_display, x_win,
  512.                     drawing_gc,
  513.                     pix_x, pix_y,
  514.                     this_pix_len - 1, line_height - 1);
  515.             XSetForeground (x_current_display, drawing_gc,
  516.                     values.foreground);
  517.               }
  518.             else
  519.               {        /* The solid cursor with a stipple */
  520.             XGCValues old_values, new_values;
  521.  
  522.             if (! XGetGCValues (x_current_display, drawing_gc,
  523.                         GCStipple | GCFillStyle,
  524.                         &old_values))
  525.               abort ();
  526.             if (!XGetGCValues (x_current_display,
  527.                        face_list[this_run].faceptr->facegc,
  528.                        GCStipple | GCFillStyle,
  529.                        &new_values))
  530.               abort ();
  531.             XSetFillStyle (x_current_display, drawing_gc,
  532.                        FillOpaqueStippled);
  533.             XSetStipple (x_current_display, drawing_gc,
  534.                      new_values.stipple);
  535.             XFillRectangle (x_current_display, x_win, drawing_gc,
  536.                     pix_x, pix_y, this_pix_len,
  537.                     line_height);
  538.             XSetStipple (x_current_display, drawing_gc,
  539.                      old_values.stipple);
  540.             XSetFillStyle (x_current_display, drawing_gc,
  541.                        old_values.fill_style);
  542.             XDrawString (x_current_display, x_win,
  543.                      drawing_gc,
  544.                      pix_x, pix_y + max_ascent, buf, len);
  545.               }
  546.           }
  547.         else
  548.           {        /* The non cursor stipple with text */
  549.             XGCValues old_values;
  550.  
  551.             if (! XGetGCValues (x_current_display, drawing_gc,
  552.                     GCStipple | GCFillStyle, &old_values))
  553.               abort ();
  554.             XSetFillStyle (x_current_display, drawing_gc,
  555.                    FillOpaqueStippled);
  556.             XFillRectangle (x_current_display, x_win, drawing_gc,
  557.                     pix_x, pix_y, this_pix_len, line_height);
  558.             XSetFillStyle (x_current_display, drawing_gc,
  559.                    old_values.fill_style);
  560.             XDrawString (x_current_display, x_win,
  561.                  drawing_gc, pix_x, pix_y + max_ascent,
  562.                  buf, len);
  563.           }
  564.           }
  565.         else
  566.           {
  567.         if (box_p)
  568.           {        /* The hollow cursor, no stipple */
  569.             XGCValues values;
  570.  
  571.             if (! XGetGCValues (x_current_display, drawing_gc,
  572.                     GCBackground | GCForeground,
  573.                     &values))
  574.               abort ();
  575.             XDrawImageString (x_current_display, x_win,
  576.                       (face_list[this_run].faceptr->facegc
  577.                        ? face_list[this_run].faceptr->facegc
  578.                        : (face_list[this_run].faceptr->hilited
  579.                       ? s->display.x->reverse_gc
  580.                       : s->display.x->normal_gc)),
  581.                       pix_x, pix_y + max_ascent, buf, len);
  582.             XSetForeground (x_current_display, drawing_gc,
  583.                     values.background);
  584.             XDrawRectangle (x_current_display, x_win,
  585.                     drawing_gc,
  586.                     pix_x, pix_y,
  587.                     this_pix_len - 1, line_height - 1);
  588.             XSetForeground (x_current_display, drawing_gc,
  589.                     values.foreground);
  590.           }
  591.         else        /* Plain or cursor, no stipple */
  592.           XDrawImageString (x_current_display, x_win,
  593.                     drawing_gc,
  594.                     pix_x,
  595.                     pix_y + max_ascent, buf, len);
  596.           }
  597.  
  598. #if 0    /* first stab at implementing boxing; doesn't work well enough yet */
  599.  
  600. /*        if (face_list[this_run].faceptr->boxed)  #### */
  601.         if (face_list[this_run].faceptr->underline)
  602.           {
  603.         int box_ascent;
  604.         int box_descent;
  605.         unsigned int uthick;
  606.         if (!XGetFontProperty (this_font, XA_STRIKEOUT_ASCENT,
  607.                        (unsigned long *) &box_ascent))
  608.           box_ascent = max_ascent;
  609.         if (!XGetFontProperty (this_font, XA_STRIKEOUT_DESCENT,
  610.                        (unsigned long *) &box_descent))
  611.           box_descent = line_height - max_ascent - 1;
  612.         if (!XGetFontProperty (this_font, XA_UNDERLINE_THICKNESS,
  613.                        (unsigned long *) &uthick))
  614.           uthick = 1;
  615.         /* top line */
  616.         if (face_list[this_run].faceptr->underline && (1<<1))
  617.           XFillRectangle (x_current_display, x_win, drawing_gc,
  618.                   pix_x, pix_y + max_ascent - box_ascent,
  619.                   this_pix_len, uthick);
  620.         /* bottom line */
  621.         if (face_list[this_run].faceptr->underline && (1<<2))
  622.           XFillRectangle (x_current_display, x_win, drawing_gc,
  623.                   pix_x, pix_y + max_ascent + box_descent,
  624.                   this_pix_len, uthick);
  625.  
  626.         /* left line */
  627. #if 0
  628.         if (this_run == 0 ||
  629.             face_list[this_run-1].type != font ||
  630.             ! face_list[this_run-1].faceptr->underline) /* #### */
  631. #else
  632.         if (face_list[this_run].faceptr->underline && (1<<3))
  633. #endif
  634.           XFillRectangle (x_current_display, x_win, drawing_gc,
  635.                   pix_x, pix_y + max_ascent - box_ascent,
  636.                   uthick, box_ascent + box_descent);
  637.         /* right line */
  638. #if 0
  639.         if (this_run >= s->current_glyphs->nruns [top] ||
  640.             face_list[this_run+1].type != font ||
  641.             ! face_list[this_run+1].faceptr->underline) /* #### */
  642. #else
  643.         if (face_list[this_run].faceptr->underline && (1<<4))
  644. #endif
  645.           XFillRectangle (x_current_display, x_win, drawing_gc,
  646.                   pix_x + this_pix_len,
  647.                   pix_y + max_ascent - box_ascent,
  648.                   uthick, box_ascent + box_descent);
  649.           }
  650.  
  651.         else
  652.  
  653. #endif /* 0 */
  654.  
  655.         if (face_list[this_run].faceptr->underline)
  656.           {
  657.         int upos;
  658.         unsigned int uthick;
  659.         if (!XGetFontProperty (this_font, XA_UNDERLINE_POSITION,
  660.                        (unsigned long *) &upos))
  661.           upos = 0;
  662.         if (!XGetFontProperty (this_font, XA_UNDERLINE_THICKNESS,
  663.                        (unsigned long *) &uthick))
  664.           uthick = 1;
  665.         XFillRectangle (x_current_display, x_win, drawing_gc,
  666.                 pix_x, pix_y + max_ascent + upos,
  667.                 this_pix_len, uthick);
  668.           }
  669.       }
  670.       break;
  671.  
  672. #ifdef LINE_INFO_COLUMN
  673.     case column_glyph:
  674.       {
  675.         int index = face_list[this_run].lineinfo_glyph_index;
  676.         int width, height;
  677.         int bitmap_y_offset = 0;
  678.         int y = pix_y;
  679.         int ibw = s->display.x->internal_border_width;
  680.         left += 1;
  681.         
  682.         if (index == -1)
  683.           {
  684.         /* just clears the lineinfo column */
  685.         x_clear_lineinfo_glyph (s, top);
  686.           }
  687.         else
  688.           {
  689.         width = s->display.x->line_info_column_width-(ibw+1);
  690.         height = line_height;
  691.         
  692.         if (!width || !height) 
  693.                   {
  694.                     maybe_abort ();
  695.             break;
  696.                   }
  697.         
  698.         /* Center the glyph vertically in the display line. */
  699.         if (height < line_height)
  700.           y += ((line_height - height) / 2);
  701.         else if (height > line_height)
  702.           {
  703.             bitmap_y_offset += ((height - line_height) / 2);
  704.             height -= (height - line_height);
  705.           }
  706.         
  707.         XCopyPlane (x_current_display,
  708.                 x_bitmaps[index].image,
  709.                 x_win,
  710.                 s->display.x->normal_gc,
  711.                 0, bitmap_y_offset, width, height,
  712.                 s->display.x->internal_border_width+1, y, 1L);
  713.         x_draw_lineinfo_border (s, top);
  714.           }
  715.       }
  716.       break;
  717. #endif
  718.  
  719.     case glyph:
  720.       {
  721.         GLYPH index = s->current_glyphs->glyphs[top][left];
  722.         struct x_pixmap *p = glyph_to_x_pixmap (index);
  723.         int height = (p ? p->height : 0);
  724.         int bitmap_y_offset = 0;
  725.         int y = pix_y;
  726. #ifdef LINE_INFO_WIDGET
  727.         int use_lineinfo = (s->display.x->lineinfo_widget &&
  728.                 XtIsManaged (s->display.x->lineinfo_widget));
  729. #endif
  730.         int real_pix_x = pix_x;
  731.         struct face *face = 0;
  732.  
  733.         if (! p)    /* #### KLUDGE */
  734.           break;
  735.  
  736.         if (!p->width || !p->height)
  737.           abort ();
  738.  
  739.         if (height < line_height || p->mask)
  740.           {
  741.         if (face_list[this_run].faceptr->back_pixmap &&
  742.             face_list[this_run].faceptr->back_pixmap != (~0))
  743.           {
  744.             XGCValues old_values;
  745.             if (! XGetGCValues (x_current_display, drawing_gc,
  746.                     GCStipple | GCFillStyle, &old_values))
  747.               abort ();
  748.             XSetFillStyle (x_current_display, drawing_gc,
  749.                    FillOpaqueStippled);
  750.             XFillRectangle (x_current_display, x_win, drawing_gc,
  751.                     pix_x, pix_y, this_pix_len, line_height);
  752.             XSetFillStyle (x_current_display, drawing_gc,
  753.                    old_values.fill_style);
  754.           }
  755.         else if (face_list[this_run].faceptr->background != ~0 &&
  756.              face_list[this_run].faceptr->background !=
  757.              SCREEN_NORMAL_FACE(s).background)
  758.           {
  759.             XGCValues old_values;
  760.             if (! XGetGCValues (x_current_display, drawing_gc,
  761.                     GCForeground, &old_values))
  762.               abort ();
  763.             XSetForeground (x_current_display, drawing_gc,
  764.                     face_list[this_run].faceptr->background);
  765.             XFillRectangle (x_current_display, x_win, drawing_gc,
  766.                     pix_x, pix_y, this_pix_len, line_height);
  767.             XSetForeground (x_current_display, drawing_gc,
  768.                     old_values.foreground);
  769.           }
  770.         else
  771.           XClearArea (x_current_display, x_win,
  772.                   pix_x, pix_y, this_pix_len,
  773.                   line_height, False);
  774.           }
  775.         
  776.         /* Center the glyph vertically in the display line. */
  777.         bitmap_y_offset = (height - line_height) / 2;
  778.         if (height > line_height)
  779.           height = line_height;
  780.  
  781.         /* ## warning, assumes x_pixmap->face_id is unsigned short... */
  782.         if (p->face_id != (unsigned short) ~0)
  783.           face = s->faces [p->face_id];
  784.  
  785.         if (face && face->foreground == ~0 && face->background == ~0)
  786.           face = 0;
  787.  
  788.         if (p->mask)
  789.           {
  790.         XSetFunction (x_current_display, drawing_gc, GXcopy);
  791.         XSetClipMask (x_current_display, drawing_gc, p->mask);
  792.         XSetClipOrigin (x_current_display, drawing_gc,
  793.                 pix_x, y - bitmap_y_offset);
  794.           }
  795.  
  796.         /* depth of 0 means it's a bitmap, not a pixmap, and we should
  797.            use XCopyPlane (1 = current foreground color, 0 = background)
  798.            instead of XCopyArea, which means that the bits in the pixmap
  799.            are actual pixel values, instead of symbolic of fg/bg.
  800.          */
  801.         if (p->depth > 0 && p->depth == widget->core.depth)
  802.           XCopyArea (x_current_display, p->pixmap, x_win, drawing_gc,
  803.              0, bitmap_y_offset, this_pix_len, height,
  804.              pix_x, y);
  805.         else if (! face)
  806.           XCopyPlane (x_current_display, p->pixmap, x_win, drawing_gc,
  807.               0, bitmap_y_offset < 0 ? 0 : bitmap_y_offset,
  808.               this_pix_len, height,
  809.               pix_x, bitmap_y_offset < 0 ? y - bitmap_y_offset : y,
  810.               1L);
  811.         else /* face */
  812.           {
  813.         XGCValues values, old_values;
  814.         int change_p;
  815.         unsigned long fg = face->foreground;
  816.         unsigned long bg = face->background;
  817.  
  818.         memset (&old_values, 0xDEADBEEF, sizeof(old_values));
  819.         /* this shouldn't cause a server trip; Xlib caches this. */
  820.         if (! XGetGCValues (x_current_display, drawing_gc,
  821.                   GCForeground | GCBackground, &old_values))
  822.           abort ();
  823.         /* we don't get here if both fg and bg are unspecified */
  824.         if (fg == ~0) fg = old_values.foreground;
  825.         if (bg == ~0) bg = old_values.background;
  826.         values.foreground = fg;
  827.         values.background = bg;
  828.  
  829.         change_p = (values.background != old_values.background ||
  830.                 values.foreground != old_values.foreground);
  831.  
  832.         if (change_p)
  833.           XChangeGC (x_current_display, drawing_gc,
  834.                  GCForeground | GCBackground,
  835.                  &values);
  836.         XCopyPlane (x_current_display,
  837.                 p->pixmap,
  838.                 x_win, drawing_gc,
  839.                 0, bitmap_y_offset, this_pix_len, height,
  840.                 pix_x, y, 1L);
  841.         if (change_p)
  842.           XChangeGC (x_current_display, drawing_gc,
  843.                  GCForeground | GCBackground,
  844.                  &old_values);
  845.           }
  846.  
  847.         if (p->mask)
  848.           XSetClipMask (x_current_display, drawing_gc, None);
  849.  
  850.         n--;
  851.         left++;
  852.  
  853.         pix_x = real_pix_x;
  854.       }
  855.       break;
  856.  
  857.     case space:
  858.       {
  859.         XGCValues ovalues, values;
  860.         int height;
  861.         if (face_list[this_run].faceptr &&
  862.         face_list[this_run].faceptr->font &&
  863.         face_list[this_run].faceptr->font != (XFontStruct *) (~0))
  864.           height = (face_list[this_run].faceptr->font->ascent +
  865.             face_list[this_run].faceptr->font->descent);
  866.         else
  867.           height = line_height;
  868.  
  869.         if (! XGetGCValues (x_current_display, drawing_gc,
  870.                 GCFillStyle | GCForeground | GCBackground,
  871.                 &ovalues))
  872.           abort ();
  873.         values.foreground = ovalues.background;
  874.         values.background = ovalues.foreground;
  875.         values.fill_style = FillSolid;
  876.         XChangeGC (x_current_display, drawing_gc,
  877.                GCFillStyle | GCForeground | GCBackground,
  878.                &values);
  879.         XFillRectangle (x_current_display, x_win, drawing_gc,
  880.                 pix_x, pix_y, this_pix_len, height);
  881.         XChangeGC (x_current_display, drawing_gc,
  882.                GCFillStyle | GCForeground | GCBackground,
  883.                &ovalues);
  884.         n--;
  885.         left++;
  886.       }
  887.       break;
  888.  
  889.     case window:
  890.       break;
  891.  
  892.     default:
  893.           {
  894.             maybe_abort();
  895.         break;
  896.           }
  897.     }
  898.  
  899. #ifdef ENERGIZE        
  900.       notify_note_update (s->display.x->edit_widget, pix_x, pix_y,
  901.                 this_pix_len, line_height);
  902. #endif
  903.       if (n == 0) goto ALL_DONE;
  904.  
  905.       pix_x += face_list[this_run].pix_length;
  906.       this_run++;
  907.  
  908.       /* check if finished */
  909.       if (this_run >= s->current_glyphs->nruns [top])
  910.     goto ALL_DONE;
  911.  
  912.       if (face_list[this_run].type == unused_run) goto ALL_DONE;
  913.  
  914.       if (! force_gc)
  915.     if (! (drawing_gc = face_list[this_run].faceptr->facegc))
  916.       if (face_list[this_run].faceptr->hilited)
  917.         drawing_gc = s->display.x->reverse_gc;
  918.       else
  919.         drawing_gc = s->display.x->normal_gc;
  920.  
  921.       this_run_len = face_list[this_run].length;
  922.       this_pix_len = face_list[this_run].pix_length;
  923.       this_font = face_list[this_run].faceptr->font;
  924.       if (!this_font)
  925.     this_font = SCREEN_NORMAL_FACE (s).font;
  926.     }
  927.  ALL_DONE:
  928.   UNBLOCK_INPUT;
  929.   return 1;
  930. }
  931.  
  932. void
  933. x_clear_display_line_end (vpos)
  934.      int vpos;
  935. {
  936.   struct screen_glyphs *current_screen
  937.     = SCREEN_CURRENT_GLYPHS (updating_screen);
  938.   int pix_x = (current_screen->top_left_x[vpos] +
  939.            current_screen->pix_width[vpos]);
  940.   int pix_y = current_screen->top_left_y[vpos];
  941.   int pix_width = (PIXEL_WIDTH (updating_screen)
  942.            - current_screen->pix_width[vpos]
  943.            - updating_screen->display.x->internal_border_width);
  944.   int pix_height = current_screen->pix_height[vpos];
  945.  
  946.   erase_screen_cursor_if_needed_and_in_region (updating_screen, 0,
  947.                            vpos, UP_TO_EOL);
  948.  
  949.   BLOCK_INPUT;
  950.   XClearArea (x_current_display,
  951.           XtWindow (updating_screen->display.x->edit_widget),
  952.           pix_x, pix_y, pix_width, pix_height, False);
  953. #ifdef ENERGIZE        
  954.   notify_note_update (updating_screen->display.x->edit_widget, pix_x, pix_y,
  955.             pix_width, pix_height);
  956. #endif
  957.   UNBLOCK_INPUT;
  958. }
  959.  
  960. void
  961. x_clear_display_line (vpos, pix_width)
  962.      int vpos, pix_width;
  963. {
  964.   struct screen_glyphs *current_screen
  965.     = SCREEN_CURRENT_GLYPHS (updating_screen);
  966.   int pix_x = current_screen->top_left_x[vpos];
  967.   int pix_y = current_screen->top_left_y[vpos];
  968.   int pix_height = current_screen->pix_height[vpos];
  969.  
  970.   /* utter kludge to prevent characters with negative left-bearing from
  971.      leaving turds down the left side of the screen... */
  972.   if (pix_x == updating_screen->display.x->internal_border_width)
  973.     pix_x = 0, pix_width += updating_screen->display.x->internal_border_width;
  974.  
  975.   erase_screen_cursor_if_needed_and_in_region (updating_screen, 0,
  976.                            vpos, UP_TO_EOL);
  977.  
  978.   BLOCK_INPUT;
  979.   XClearArea (x_current_display,
  980.           XtWindow (updating_screen->display.x->edit_widget),
  981.           pix_x, pix_y, pix_width, pix_height, False);
  982.  
  983. #ifdef ENERGIZE        
  984.   notify_note_update (updating_screen->display.x->edit_widget, pix_x, pix_y,
  985.             pix_width, pix_height);
  986. #endif
  987.   UNBLOCK_INPUT;
  988. }
  989.  
  990. #ifdef LINE_INFO_COLUMN
  991.  
  992. void x_draw_lineinfo_border (screen, vpos)
  993.      struct screen* screen;
  994.      int vpos;
  995. {
  996.   struct screen_glyphs *current_screen = SCREEN_CURRENT_GLYPHS (screen);
  997.   int ibw = screen->display.x->internal_border_width;
  998.   int pix_x = screen->display.x->internal_border_width;
  999.   int pix_y = current_screen->top_left_y[vpos];
  1000.   int pix_width  = screen->display.x->line_info_column_width - ibw;
  1001.   int pix_height = current_screen->pix_height[vpos];
  1002.   GC gc = screen->display.x->line_info_gc;
  1003.  
  1004.   if (pix_width <= 0) return;
  1005.  
  1006.   BLOCK_INPUT;
  1007.   XDrawLine (x_current_display, XtWindow (screen->display.x->edit_widget), gc,
  1008.          pix_x + pix_width - 1, pix_y,
  1009.          pix_x + pix_width - 1, pix_y + pix_height);
  1010.   
  1011.   XDrawLine (x_current_display, XtWindow (screen->display.x->edit_widget), gc,
  1012.          pix_x, pix_y,
  1013.          pix_x, pix_y + pix_height);
  1014.   
  1015. #if 0
  1016.   if (vpos == 0)
  1017. #else
  1018.   if (vpos == 0 || (vpos && !current_screen->bufp[vpos-1]))
  1019. #endif
  1020.     XDrawLine (x_current_display, XtWindow (screen->display.x->edit_widget), gc,
  1021.            pix_x, pix_y,
  1022.            pix_x + pix_width - 1, pix_y);
  1023. #if 0
  1024.   if (vpos == screen->height - 1)
  1025. #else
  1026.   if (vpos == screen->height - 1 || ! current_screen->bufp[vpos+1])
  1027. #endif
  1028.     XDrawLine (x_current_display, XtWindow (screen->display.x->edit_widget), gc,
  1029.            pix_x, pix_y + pix_height,
  1030.            pix_x + pix_width, pix_y + pix_height);
  1031.   UNBLOCK_INPUT;
  1032. }
  1033.  
  1034. void x_clear_lineinfo_glyph (screen, vpos)
  1035.      struct screen* screen;
  1036.      int vpos;
  1037. {
  1038.   struct screen_glyphs *current_screen = SCREEN_CURRENT_GLYPHS (screen);
  1039.   int ibw = screen->display.x->internal_border_width;
  1040.   int pix_x = screen->display.x->internal_border_width;
  1041.   int pix_y = current_screen->top_left_y[vpos];
  1042.   int pix_width  = screen->display.x->line_info_column_width - ibw;
  1043.   int pix_height = current_screen->pix_height[vpos];
  1044.  
  1045.   if (pix_width > 0) {
  1046. #if 1
  1047.   if (current_screen->bufp[vpos] &&
  1048.       !(screen->has_minibuffer &&
  1049.     vpos >= screen->height - XWINDOW(screen->minibuffer_window)->height)
  1050.       )
  1051.     {
  1052. #endif
  1053.     XGCValues gcv;
  1054.     GC gc = screen->display.x->line_info_gc;
  1055.     unsigned long ofg;
  1056.  
  1057.     BLOCK_INPUT;
  1058.     XFillRectangle (x_current_display, XtWindow (screen->display.x->edit_widget),
  1059.             screen->display.x->reverse_gc,
  1060.             pix_x+pix_width, pix_y, ibw, pix_height);
  1061.  
  1062.     if (! XGetGCValues (x_current_display, gc, GCForeground|GCBackground,&gcv))
  1063.       abort ();
  1064.     ofg = gcv.foreground;
  1065.     gcv.foreground = gcv.background;
  1066.     XChangeGC (x_current_display, gc, GCForeground, &gcv);
  1067.     XFillRectangle (x_current_display, XtWindow (screen->display.x->edit_widget),
  1068.             gc, pix_x, pix_y, pix_width, pix_height);
  1069.     gcv.foreground = ofg;
  1070.     XChangeGC (x_current_display, gc, GCForeground, &gcv);
  1071.     x_draw_lineinfo_border (screen, vpos);
  1072.     UNBLOCK_INPUT;
  1073. #if 1
  1074.     }
  1075.   else if (screen->has_minibuffer &&
  1076.        vpos >= screen->height -
  1077.        XWINDOW(screen->minibuffer_window)->height)
  1078.     {
  1079.       GC gc = screen->display.x->reverse_gc;
  1080.       BLOCK_INPUT;
  1081.       XFillRectangle (x_current_display, XtWindow (screen->display.x->edit_widget),
  1082.               gc, pix_x, pix_y, pix_width+ibw, pix_height);
  1083.       UNBLOCK_INPUT;
  1084.     }
  1085.   else
  1086.     {
  1087.       BLOCK_INPUT;
  1088.       XFillRectangle (x_current_display, XtWindow (screen->display.x->edit_widget),
  1089.               screen->display.x->normal_gc,
  1090.               pix_x, pix_y, pix_width+ibw,
  1091.               pix_height - x_interline_space);
  1092.       XFillRectangle (x_current_display, XtWindow (screen->display.x->edit_widget),
  1093.               screen->display.x->reverse_gc,
  1094.               pix_x, pix_y + pix_height - x_interline_space,
  1095.               pix_width+ibw, x_interline_space);
  1096.       XFillRectangle (x_current_display, XtWindow (screen->display.x->edit_widget),
  1097.               screen->display.x->reverse_gc,
  1098.               pix_x, pix_y - x_interline_space,
  1099.               pix_width+ibw, x_interline_space);
  1100.       XDrawLine (x_current_display, XtWindow (screen->display.x->edit_widget),
  1101.          screen->display.x->normal_gc,
  1102.          pix_x, pix_y - (x_interline_space + 1),
  1103.          pix_x + pix_width - 1, pix_y - (x_interline_space + 1));
  1104.  
  1105.       UNBLOCK_INPUT;
  1106.     }
  1107. #endif
  1108.   }
  1109. }
  1110. #endif
  1111.  
  1112.  
  1113.  
  1114. /* Output some text at the nominal screen cursor position,
  1115.    advancing the cursor over the text.
  1116.    Output LEN glyphs at START.  */
  1117.  
  1118. static void
  1119. XTwrite_glyphs (hpos, vpos, len)
  1120.      int hpos, vpos, len;
  1121. {
  1122.   struct screen *s;
  1123.  
  1124.   if (updating_screen == 0)
  1125.     {
  1126.       s = selected_screen;
  1127.       erase_screen_cursor_if_needed (s);
  1128.     }
  1129.   else
  1130.     s = updating_screen;
  1131.  
  1132.   if (hpos != s->cursor_x || vpos != s->cursor_y)
  1133.     /* abort ();   fuck this */
  1134.     return;
  1135.  
  1136.   x_write_glyphs (s, hpos, vpos, len, 0, 0);
  1137.   s->cursor_x += len;
  1138.  
  1139.   if (updating_screen == 0)
  1140.     {
  1141.       draw_screen_cursor_if_needed (s);
  1142.       s->cursor_x -= len;
  1143.       BLOCK_INPUT;
  1144.       XFlushQueue ();
  1145.       UNBLOCK_INPUT;
  1146.     }
  1147. }
  1148.  
  1149. /* Erase the current text line from the nominal cursor position (inclusive)
  1150.    to column FIRST_UNUSED (exclusive).  The idea is that everything
  1151.    from FIRST_UNUSED onward is already erased.  */
  1152.  
  1153. static void
  1154. XTclear_end_of_line (first_unused)
  1155.      int first_unused;
  1156. {
  1157.   struct screen *s = updating_screen;
  1158.   int pix_x, pix_y, pix_width, pix_height;
  1159.   struct glyph_dimensions *dimensions;
  1160.  
  1161.   if (s == 0)
  1162.     /* abort ();   fuck this */
  1163.     return;
  1164.  
  1165.   if (s->cursor_y < 0 || s->cursor_y >= s->height || first_unused <= 0)
  1166.     return;
  1167.  
  1168.   BLOCK_INPUT;
  1169.   pix_height = s->current_glyphs->pix_height[s->cursor_y];
  1170.   dimensions = get_glyph_dimensions (s, s->cursor_x, s->cursor_y);
  1171.   if (!dimensions)
  1172.     goto cancel;
  1173.  
  1174.   pix_x = dimensions->top_left_x;
  1175.   pix_y = dimensions->top_left_y;
  1176.  
  1177.   if (first_unused >= s->width
  1178.       || first_unused > s->current_glyphs->used[s->cursor_y])
  1179.     {
  1180.       pix_width = (PIXEL_WIDTH (s)
  1181.            - s->display.x->internal_border_width
  1182.            - pix_x);
  1183.     }
  1184.   else
  1185.     {
  1186.       dimensions = get_glyph_dimensions (s, first_unused - 1, s->cursor_y);
  1187.       if (!dimensions)
  1188.     goto cancel;
  1189.  
  1190.       pix_width = pix_x + dimensions->top_left_x - 1;
  1191.     }
  1192.  
  1193.   erase_screen_cursor_if_needed (s);
  1194.   XClearArea (x_current_display, XtWindow (s->display.x->edit_widget),
  1195.           pix_x, pix_y, pix_width, pix_height, False);
  1196. #ifdef ENERGIZE        
  1197.   notify_note_update (s->display.x->edit_widget, pix_x, pix_y,
  1198.             pix_width, pix_height);
  1199. #endif
  1200.  
  1201.  cancel:
  1202.   UNBLOCK_INPUT;
  1203. }
  1204.  
  1205. static void
  1206. XTclear_screen ()
  1207. {
  1208.   struct screen *s;
  1209.  
  1210.   if (updating_screen == 0)
  1211.     s = selected_screen;
  1212.   else
  1213.     s = updating_screen;
  1214.  
  1215.   s->cursor_x = s->cursor_y = 0;
  1216.   s->phys_cursor_x = -1;
  1217.   BLOCK_INPUT;
  1218.   XClearWindow (x_current_display, XtWindow (s->display.x->edit_widget));
  1219. #ifdef ENERGIZE        
  1220.   notify_note_update (s->display.x->edit_widget, 0, 0,
  1221.               s->display.x->pixel_width, s->display.x->pixel_height);
  1222. #endif
  1223.   UNBLOCK_INPUT;
  1224. }
  1225.  
  1226. /* briefly swap the foreground and background colors.
  1227.  */
  1228.  
  1229. extern int select();
  1230.  
  1231. static void
  1232. XTflash (s)
  1233.      struct screen *s;
  1234. {
  1235.   unsigned long frob;
  1236.   struct face *face;
  1237.   Display *dpy;
  1238.   Window w;
  1239.  
  1240.   if (updating_screen != 0)
  1241.     return;
  1242.  
  1243.   BLOCK_INPUT;
  1244.   face = &SCREEN_NORMAL_FACE (s);
  1245.   frob = face->foreground ^ face->background;
  1246.   dpy = XtDisplay (s->display.x->widget);
  1247.   w = XtWindow (s->display.x->edit_widget);
  1248.   XSetState (dpy, face->facegc, frob, face->background, GXxor, -1);
  1249.   XFillRectangle (dpy, w, face->facegc, 0, 0, s->display.x->widget->core.width,
  1250.           s->display.x->widget->core.height);
  1251.   XSync (dpy, False);
  1252.   UNBLOCK_INPUT;
  1253.  
  1254.   {
  1255.     int usecs = 100000;
  1256.     struct timeval tv;
  1257.     tv.tv_sec  = usecs / 1000000L;
  1258.     tv.tv_usec = usecs % 1000000L;
  1259.     /* I'm sure someone is going to complain about this... */
  1260.     (void) select (0, 0, 0, 0, &tv);
  1261.   }
  1262.  
  1263.   BLOCK_INPUT;
  1264.   XFillRectangle (dpy, w, face->facegc, 0, 0, s->display.x->widget->core.width,
  1265.           s->display.x->widget->core.height);
  1266.   XSetState (dpy, face->facegc, face->foreground, face->background,
  1267.          GXcopy, -1);
  1268.   XSync (dpy, False);
  1269.   UNBLOCK_INPUT;
  1270. }
  1271.  
  1272. /* Make audible bell.  */
  1273.  
  1274. /* X defines volume as from -100 to 100; we use 0 to 100 */
  1275. extern Lisp_Object Vbell_volume;
  1276.  
  1277. static void
  1278. XTsimple_beep (volume)
  1279.      int volume;
  1280. {
  1281.   if (volume < 0) volume = 0;
  1282.   else if (volume > 100) volume = 100;
  1283.   BLOCK_INPUT;
  1284.   XBell (x_current_display, (volume * 2) - 100);
  1285.   XFlushQueue ();
  1286.   UNBLOCK_INPUT;
  1287. }
  1288.  
  1289. static void
  1290. XTring_bell (sound)
  1291.      Lisp_Object sound;
  1292. {
  1293.   if (visible_bell)
  1294.     XTflash (selected_screen);
  1295.   else
  1296.     Fplay_sound (sound, Qnil);
  1297. }
  1298.  
  1299. /* Specify how many text lines, from the top of the window,
  1300.    should be affected by insert-lines and delete-lines operations.
  1301.    This, and those operations, are used only within an update
  1302.    that is bounded by calls to XTupdate_begin and XTupdate_end.  */
  1303.  
  1304. static void
  1305. XTset_terminal_window (n)
  1306.      int n;
  1307. {
  1308.   if (updating_screen == 0)
  1309.     /* abort ();   fuck this */
  1310.     return;
  1311.  
  1312.   if ((n <= 0) || (n > updating_screen->height))
  1313.     update_height = updating_screen->height;
  1314.   else
  1315.     update_height = n;
  1316. }
  1317.  
  1318. /* Perform an insert-lines operation, inserting N lines
  1319.    at a vertical position s->cursor_y.  */
  1320.  
  1321. static void
  1322. stufflines (n)
  1323.      int n;
  1324. {
  1325.   int width, copy_height, clear_height, from_x, from_y, to_x, to_y;
  1326.   struct screen *s = updating_screen;
  1327.   struct screen_glyphs *current_glyphs = s->current_glyphs;
  1328.   int iborder = s->display.x->internal_border_width;
  1329.   from_x = to_x = iborder;
  1330.   from_y = current_glyphs->top_left_y[s->cursor_y];
  1331.   to_y = current_glyphs->top_left_y[s->cursor_y + n];
  1332.   to_y = min (to_y, current_glyphs->top_left_y[update_height]);
  1333.  
  1334.   width = PIXEL_WIDTH (s) - (2 * iborder);
  1335.   copy_height = current_glyphs->top_left_y[update_height - n] - from_y;
  1336.   clear_height = to_y - from_y;
  1337.  
  1338.   BLOCK_INPUT;
  1339.   if (copy_height > 0)
  1340.     {
  1341.       XCopyArea (x_current_display, XtWindow (s->display.x->edit_widget),
  1342.          XtWindow (s->display.x->edit_widget), s->display.x->normal_gc,
  1343.          from_x, from_y, width, copy_height, to_x, to_y);
  1344. #ifdef ENERGIZE
  1345. #if 0
  1346.  *      xc_note_parent_scrolled (s->display.x->edit_widget,
  1347.  *                   from_x, from_y, width, copy_height, 
  1348.  *                   to_x - from_x, to_y - from_y);
  1349. #endif
  1350. #endif
  1351.       XClearArea (x_current_display, XtWindow (s->display.x->edit_widget),
  1352.           from_x, from_y, width, clear_height, False);
  1353. #ifdef ENERGIZE
  1354.       notify_note_update (s->display.x->edit_widget, from_x, from_y,
  1355.               width, clear_height);
  1356.  
  1357. #endif
  1358.     }
  1359.   UNBLOCK_INPUT;
  1360. }
  1361.  
  1362. /* Perform a delete-lines operation, deleting N lines
  1363.    at a vertical position s->cursor_y.  */
  1364.  
  1365. static void
  1366. scraplines (n)
  1367.      int n;
  1368. {
  1369.   struct screen *s = updating_screen;
  1370.   struct screen_glyphs *current_glyphs = s->current_glyphs;
  1371.   int top = s->cursor_y;
  1372.   int width, height;
  1373.   int iborder = s->display.x->internal_border_width;
  1374.  
  1375.   BLOCK_INPUT;
  1376.   if ((s->cursor_y + n) >= update_height
  1377.       && (update_height >= (s->cursor_y + 1)))
  1378.     {
  1379.       width = PIXEL_WIDTH (s) - (2 * iborder);
  1380.       height = (current_glyphs->top_left_y[update_height]
  1381.         + current_glyphs->pix_height[update_height]
  1382.         - current_glyphs->top_left_y[top]);
  1383.       XClearArea (x_current_display, XtWindow (s->display.x->edit_widget),
  1384.           current_glyphs->top_left_x[top],
  1385.           current_glyphs->top_left_y[top],
  1386.           width, height, False);
  1387. #ifdef ENERGIZE
  1388.       notify_note_update (s->display.x->edit_widget, 
  1389.               current_glyphs->top_left_x[top],
  1390.               current_glyphs->top_left_y[top],
  1391.               width, height);
  1392. #endif
  1393.     }
  1394.   else
  1395.     {
  1396.       int from_x = iborder;
  1397.       int from_y = current_glyphs->top_left_y[top + n];
  1398.       int to_x = iborder;
  1399.       int to_y = current_glyphs->top_left_y[top];
  1400.  
  1401.       width = PIXEL_WIDTH (s) - (2 * iborder);
  1402.       height = current_glyphs->top_left_y[update_height] - from_y;
  1403.  
  1404.       /* Move lines under the deleted area upwards. */
  1405.       XCopyArea (x_current_display, XtWindow (s->display.x->edit_widget),
  1406.          XtWindow (s->display.x->edit_widget), s->display.x->normal_gc,
  1407.          from_x, from_y, width, height, to_x, to_y);
  1408. #ifdef ENERGIZE
  1409. #if 0
  1410.  *      xc_note_parent_scrolled (s->display.x->edit_widget,
  1411.  *                   from_x, from_y, width, height, 
  1412.  *                   to_x - from_x, to_y - from_y);
  1413. #endif
  1414. #endif
  1415.       to_y = to_y + height;
  1416.       height = current_glyphs->top_left_y[update_height] - to_y;
  1417.       /* Clear any lines below those just moved. */
  1418.       XClearArea (x_current_display, XtWindow (s->display.x->edit_widget),
  1419.           from_x, to_y, width, height, False);
  1420. #ifdef ENERGIZE        
  1421.       notify_note_update (s->display.x->edit_widget, from_x, to_y,
  1422.               width, height);
  1423. #endif
  1424.  
  1425.   UNBLOCK_INPUT;
  1426.     }
  1427. }
  1428.  
  1429. /* Perform an insert-lines or delete-lines operation,
  1430.    inserting N lines or deleting -N lines at vertical position VPOS.  */
  1431.  
  1432. static void
  1433. XTins_del_lines (vpos, n)
  1434.      int vpos, n;
  1435. {
  1436.   if (updating_screen == 0)
  1437.     /* abort ();   fuck this */
  1438.     return;
  1439.   if (vpos >= update_height)
  1440.     return;
  1441.  
  1442.   erase_cursor_if_needed ();
  1443.  
  1444.   updating_screen->cursor_x = 0;
  1445.   updating_screen->cursor_y = vpos;
  1446.  
  1447.   if (n >= 0)
  1448.     stufflines (n);
  1449.   else
  1450.     scraplines (-n);
  1451. }
  1452.  
  1453. /* Repaint all lines encompassed by an Expose region. */
  1454.  
  1455. void
  1456. repaint_lines (s, left, top, width, height)
  1457.      struct screen *s;
  1458.      int left, top, width, height;
  1459. {
  1460.   struct screen_glyphs *current_screen = SCREEN_CURRENT_GLYPHS (s);
  1461.   int this_line;
  1462.   int bottom = top + height;
  1463.   int line_top;
  1464.   int line_bottom;
  1465.   int line_used; 
  1466.  
  1467.   if (s->garbaged)
  1468.     return;
  1469.  
  1470.   erase_screen_cursor_if_needed (s);
  1471.  
  1472.   for (this_line = 0; this_line < SCREEN_HEIGHT (s); this_line++)
  1473.     if (current_screen->enable [this_line])
  1474.       {
  1475.     line_top = current_screen->top_left_y [this_line];
  1476.     line_bottom = line_top + current_screen->pix_height [this_line];
  1477.     line_used = current_screen->used [this_line];
  1478.  
  1479.     if (line_top > bottom)
  1480.       break;
  1481.     if (line_bottom >= top && line_used > 0)
  1482.       x_write_glyphs (s, 0, this_line, line_used, 0, 0);
  1483.       }
  1484.  
  1485.   draw_screen_cursor_if_needed (s);
  1486. }
  1487.  
  1488. void
  1489. x_screen_redraw_cursor (screen)
  1490.      struct screen *screen;
  1491. {
  1492.   erase_screen_cursor_if_needed (screen);
  1493.   draw_screen_cursor_if_needed (screen);
  1494. }
  1495.  
  1496. /* Make SCREEN the current input screen.  */
  1497. void
  1498. x_new_selected_screen (screen)
  1499.      struct screen *screen;
  1500. {
  1501.   struct screen* previous_screen = selected_screen;
  1502.  
  1503.   if (previous_screen != screen)
  1504.     {
  1505.       selected_screen = screen;
  1506.  
  1507.       if (previous_screen)
  1508.     x_screen_redraw_cursor (previous_screen);
  1509.       x_screen_redraw_cursor (screen);
  1510.     }
  1511. }
  1512.  
  1513.  
  1514. static char *events[] =
  1515. {
  1516.    "0: ERROR!",
  1517.    "1: REPLY",
  1518.    "KeyPress",
  1519.    "KeyRelease",
  1520.    "ButtonPress",
  1521.    "ButtonRelease",
  1522.    "MotionNotify",
  1523.    "EnterNotify",
  1524.    "LeaveNotify",
  1525.    "FocusIn",
  1526.    "FocusOut",
  1527.    "KeymapNotify",
  1528.    "Expose",
  1529.    "GraphicsExpose",
  1530.    "NoExpose",
  1531.    "VisibilityNotify",
  1532.    "CreateNotify",
  1533.    "DestroyNotify",
  1534.    "UnmapNotify",
  1535.    "MapNotify",
  1536.    "MapRequest",
  1537.    "ReparentNotify",
  1538.    "ConfigureNotify",
  1539.    "ConfigureRequest",
  1540.    "GravityNotify",
  1541.    "ResizeRequest",
  1542.    "CirculateNotify",
  1543.    "CirculateRequest",
  1544.    "PropertyNotify",
  1545.    "SelectionClear",
  1546.    "SelectionRequest",
  1547.    "SelectionNotify",
  1548.    "ColormapNotify",
  1549.    "ClientMessage",
  1550.    "MappingNotify",
  1551.    "LASTEvent"
  1552. };
  1553.  
  1554. char *
  1555. x_event_name (event_type)
  1556.      int event_type;
  1557. {
  1558.   if (event_type < 0) return 0;
  1559.   if (event_type >= (sizeof (events) / sizeof (char *))) return 0;
  1560.   return events [event_type];
  1561. }
  1562.  
  1563.  
  1564. static void
  1565. x_display_bar_cursor (s, on)
  1566.      struct screen *s;
  1567.      int on;
  1568. {
  1569.   int x0, x1, y0, y1;
  1570.  
  1571.   if (! s->visible || (! on && s->phys_cursor_x < 0))
  1572.     return;
  1573.  
  1574.   if (s->phys_cursor_x >= 0 &&
  1575.       (!on || s->phys_cursor_x != s->cursor_x
  1576.        || s->phys_cursor_y != s->cursor_y))
  1577.     {
  1578.       if (s->phys_cursor_x < s->current_glyphs->used[s->phys_cursor_y])
  1579.     {
  1580.       struct glyph_dimensions *dimensions
  1581.         = get_glyph_dimensions (s, s->phys_cursor_x, s->phys_cursor_y);
  1582.       if (!dimensions)
  1583.         return;
  1584.  
  1585.       x0 = dimensions->top_left_x;
  1586.       x1 = x0;
  1587.       y0 = s->current_glyphs->top_left_y[s->phys_cursor_y];
  1588.       y1 = (y0 + s->current_glyphs->pix_height[s->phys_cursor_y]
  1589.         - x_interline_space);
  1590.  
  1591.       BLOCK_INPUT;
  1592.       XDrawLine (x_current_display, XtWindow (s->display.x->edit_widget),
  1593.              s->display.x->reverse_gc, x0, y0, x1, y1);
  1594.       UNBLOCK_INPUT;
  1595.       x_write_glyphs (s, s->phys_cursor_x, s->phys_cursor_y, 1, 0, 0);
  1596.     }
  1597.       else
  1598.     {
  1599.       x0 = (s->current_glyphs->top_left_x[s->phys_cursor_y]
  1600.         + s->current_glyphs->pix_width[s->phys_cursor_y]);
  1601.       x1 = x0;
  1602.       y0 = s->current_glyphs->top_left_y[s->phys_cursor_y];
  1603.       y1 = y0 + s->current_glyphs->pix_height[s->phys_cursor_y];
  1604.  
  1605.       BLOCK_INPUT;
  1606.       XDrawLine (x_current_display, XtWindow (s->display.x->edit_widget),
  1607.              s->display.x->reverse_gc, x0, y0, x1, y1);
  1608.       UNBLOCK_INPUT;
  1609.     }
  1610.       s->phys_cursor_x = -1;
  1611.     }
  1612.  
  1613.   if (on && focus_cursor_p (s))
  1614.     {
  1615.       if (s->cursor_x < s->current_glyphs->used[s->cursor_y])
  1616.     {
  1617.       struct glyph_dimensions *dimensions
  1618.         = get_glyph_dimensions (s, s->cursor_x, s->cursor_y);
  1619.       if (!dimensions)
  1620.         return;
  1621.  
  1622.       x0 = dimensions->top_left_x;
  1623.       x1 = x0;
  1624.       y0 = s->current_glyphs->top_left_y[s->cursor_y];
  1625.       y1 = y0 + s->current_glyphs->pix_height[s->cursor_y];
  1626.     }
  1627.       else
  1628.     {
  1629.       x0 = (s->current_glyphs->top_left_x[s->cursor_y]
  1630.         + s->current_glyphs->pix_width[s->cursor_y]);
  1631.       x1 = x0;
  1632.       y0 = s->current_glyphs->top_left_y[s->cursor_y];
  1633.       y1 = y0 + s->current_glyphs->pix_height[s->cursor_y];
  1634.     }
  1635.  
  1636.       BLOCK_INPUT;
  1637.       XDrawLine (x_current_display, XtWindow (s->display.x->edit_widget),
  1638.          s->display.x->cursor_gc, x0, y0, x1, y1);
  1639.       UNBLOCK_INPUT;
  1640.       s->phys_cursor_x = s->cursor_x;
  1641.       s->phys_cursor_y = s->cursor_y;
  1642.     }
  1643. }
  1644.  
  1645. /* Draw an empty box at the end of the line. */
  1646.  
  1647. static int
  1648. x_draw_empty_box (s)
  1649.      struct screen *s;
  1650. {
  1651.   int height, x, y;
  1652.   XGCValues values;
  1653.   
  1654.   BLOCK_INPUT;
  1655.   if (! XGetGCValues (x_current_display, s->display.x->cursor_gc,
  1656.               GCBackground | GCForeground, &values))
  1657.     abort ();
  1658.   height = s->current_glyphs->pix_height[s->phys_cursor_y] - x_interline_space;
  1659.   x = s->current_glyphs->top_left_x[s->phys_cursor_y]
  1660.     + s->current_glyphs->pix_width[s->phys_cursor_y];
  1661.   y = s->current_glyphs->top_left_y[s->phys_cursor_y];
  1662.  
  1663.   XClearArea (x_current_display, XtWindow (s->display.x->edit_widget),
  1664.           x, y, EOL_CURSOR_WIDTH, height, False);
  1665.  
  1666.   XSetForeground (x_current_display, s->display.x->cursor_gc,
  1667.           values.background);
  1668.   XDrawRectangle (x_current_display, XtWindow (s->display.x->edit_widget),
  1669.           s->display.x->cursor_gc,
  1670.           x, y,
  1671.           EOL_CURSOR_WIDTH - 1, height - 1);
  1672.   XSetForeground (x_current_display, s->display.x->cursor_gc,
  1673.           values.foreground);
  1674.   UNBLOCK_INPUT;
  1675.   return 1;
  1676. }
  1677.  
  1678. /* Draw a square with the cursor gc at the end of the line. */
  1679.  
  1680. static int
  1681. x_draw_square (s)
  1682.      struct screen *s;
  1683. {
  1684.   int height, x, y;
  1685.   XGCValues values;
  1686.   
  1687.   BLOCK_INPUT;
  1688.   if (! XGetGCValues (x_current_display, s->display.x->cursor_gc,
  1689.               GCBackground | GCForeground, &values))
  1690.     abort ();
  1691.   height = s->current_glyphs->pix_height[s->phys_cursor_y] - x_interline_space;
  1692.   x = s->current_glyphs->top_left_x[s->phys_cursor_y]
  1693.     + s->current_glyphs->pix_width[s->phys_cursor_y];
  1694.   y = s->current_glyphs->top_left_y[s->phys_cursor_y];
  1695.  
  1696.   XSetForeground (x_current_display, s->display.x->cursor_gc,
  1697.           values.background);
  1698.   XFillRectangle (x_current_display, XtWindow (s->display.x->edit_widget),
  1699.           s->display.x->cursor_gc,
  1700.           x, y,
  1701.           EOL_CURSOR_WIDTH, height);
  1702.   XSetForeground (x_current_display, s->display.x->cursor_gc,
  1703.           values.foreground);
  1704.   UNBLOCK_INPUT;
  1705.   return 1;
  1706. }
  1707.  
  1708. /* Erase the cursor square at the end of the line. */
  1709.  
  1710. static int
  1711. x_erase_square (s)
  1712.      struct screen *s;
  1713. {
  1714.   int height, x, y;
  1715.  
  1716.   height = s->current_glyphs->pix_height[s->phys_cursor_y];
  1717.   x = s->current_glyphs->top_left_x[s->phys_cursor_y]
  1718.     + s->current_glyphs->pix_width[s->phys_cursor_y];
  1719.   y = s->current_glyphs->top_left_y[s->phys_cursor_y];
  1720.  
  1721.   BLOCK_INPUT;
  1722.   XClearArea (x_current_display, XtWindow (s->display.x->edit_widget),
  1723.           x, y,
  1724.           /* EOL_CURSOR_WIDTH, */
  1725.           PIXEL_WIDTH (s) - x,
  1726.           height, False);
  1727.   UNBLOCK_INPUT;
  1728.   return 1;
  1729. }
  1730.  
  1731. /* Turn the displayed cursor of screen S on or off according to ON.
  1732.    If ON is nonzero, where to put the cursor is specified
  1733.    by S->cursor_x and S->cursor_y.  Return 1 if it does something,
  1734.    0 if it does nothing. */
  1735.  
  1736. static int
  1737. x_display_box_cursor (s, on)
  1738.      struct screen *s;
  1739.      int on;
  1740. {
  1741.   struct screen_glyphs *current_screen;
  1742.   int value = 0;
  1743.  
  1744.   if (! s->visible)
  1745.     return 0;
  1746.  
  1747.   if (!on && s->phys_cursor_x < 0)
  1748.     return 1;
  1749.  
  1750.   current_screen = SCREEN_CURRENT_GLYPHS (s);
  1751.  
  1752.   if (! current_screen) return 0;  /* added by jwz */
  1753.  
  1754.   if (on)
  1755.     {
  1756.       if (!s->cursor_erased
  1757.        && ((s->phys_cursor_x != s->cursor_x)
  1758.            || (s->phys_cursor_y != s->cursor_y)))
  1759.      x_display_box_cursor (s, 0);
  1760.       s->phys_cursor_x = s->cursor_x;
  1761.       s->phys_cursor_y = s->cursor_y;
  1762.       
  1763.       /* Case where cursor is in text. */
  1764.       if (current_screen->enable[s->cursor_y])
  1765.     {
  1766.       if (s->cursor_x < current_screen->used[s->cursor_y])
  1767.         {
  1768.           return x_write_glyphs (s, s->cursor_x, s->cursor_y,
  1769.                      1, s->display.x->cursor_gc,
  1770.                      ! focus_cursor_p (s));
  1771.         }
  1772.       else
  1773.         {
  1774.           /* No text here. */
  1775.           if (! focus_cursor_p (s))
  1776.         return x_draw_empty_box (s);
  1777.           else
  1778.         return x_draw_square (s);
  1779.         }
  1780.     } else {
  1781.       return 0;
  1782.     }
  1783.     }
  1784.  
  1785.   /* Turn cursor OFF. */
  1786.   if (current_screen->enable[s->phys_cursor_y])
  1787.     {
  1788.       if (s->phys_cursor_x < current_screen->used[s->phys_cursor_y])
  1789.     value = x_write_glyphs (s, s->phys_cursor_x, s->phys_cursor_y, 1, 0, 0);
  1790.       else
  1791.     value = x_erase_square (s);
  1792.     }
  1793.  
  1794.   s->phys_cursor_x = -1;
  1795.   return value;
  1796. }
  1797.  
  1798. static int
  1799. x_display_cursor (s, on)
  1800.      struct screen *s;
  1801.      int on;
  1802. {
  1803.   if (on)
  1804.     last_bar_cursor = Vbar_cursor;
  1805.   
  1806.   if (EQ (last_bar_cursor, Qnil))
  1807.     return x_display_box_cursor (s, on);
  1808.   else
  1809.     {
  1810.       x_display_bar_cursor (s, on);
  1811.       return 1;
  1812.     }
  1813. }
  1814.  
  1815. static int
  1816. x_error_handler (disp, event)
  1817.      Display *disp;
  1818.      XErrorEvent *event;
  1819. {
  1820.   /* It would be nice to be able to signal a Lisp error here, but we can't,
  1821.      because the guts of Xlib expect this function to either return or exit.
  1822.      Also, we can't print things in the minibuffer with Fmessage(), because
  1823.      this function isn't allowed to do IO on the display connection.  So all
  1824.      we can do is write to stderr.
  1825.    */
  1826.   XmuPrintDefaultErrorMessage (disp, event, stderr);
  1827.   return 0;
  1828. }
  1829.  
  1830. extern char *sys_errlist[];
  1831.  
  1832. /* This is called when the display connection becomes hosed.
  1833.    It may not return.
  1834.  */
  1835. static int
  1836. x_IO_error_handler (disp)
  1837.      Display *disp;
  1838. {
  1839.   fprintf (stderr, "\nFatal I/O Error %d (%s) on display connection \"%s\"\n",
  1840.        errno, sys_errlist [errno], DisplayString (disp));
  1841.   fprintf (stderr,
  1842.       "after %lu requests (%lu known processed) with %d events remaining.\n",
  1843.        NextRequest (disp) - 1, LastKnownRequestProcessed (disp),
  1844.        QLength(disp));
  1845.   if (_Xdebug)
  1846.     abort ();
  1847.   else
  1848.     {
  1849.       fprintf (stderr, "Autosaving and exiting...\n");
  1850.       x_current_display = 0; /* it's dead! */
  1851.       Vwindow_system = Qnil; /* let it lie! */
  1852.       Fset (intern ("kill-emacs-hook"), Qnil); /* too dangerous */
  1853.       Fkill_emacs (make_number (70));
  1854.     }
  1855.   return 0; /* not reached; suppress warnings */
  1856. }
  1857.  
  1858.  
  1859.  
  1860. /* Pixmap cache */
  1861.  
  1862. c_hashtable x_pixmap_table;
  1863.  
  1864. struct x_pixmap builtin_continuer_pixmap;
  1865. struct x_pixmap builtin_truncator_pixmap;
  1866. struct x_pixmap builtin_rarrow_pixmap;
  1867.  
  1868. static int glyph_to_x_pixmaps_size, max_pixmap_id;
  1869. struct x_pixmap **glyph_to_x_pixmaps_table;
  1870.  
  1871.  
  1872. struct x_pixmap *
  1873. glyph_to_x_pixmap (GLYPH g)
  1874. {
  1875.   struct x_pixmap *p;
  1876.   if (g >= max_pixmap_id)
  1877. /*    abort (); */
  1878.     return 0; /* #### KLUDGE */
  1879.   p = glyph_to_x_pixmaps_table [g];
  1880.   if (! p) abort ();
  1881.   if (g != p->glyph_id) abort ();
  1882.   return p;
  1883. }
  1884.  
  1885. static void
  1886. init_bitmap_tables ()
  1887. {
  1888.   Display *dpy = x_current_display;
  1889.   Window root = DefaultRootWindow (dpy);
  1890.  
  1891.   glyph_to_x_pixmaps_size = 50;
  1892.   glyph_to_x_pixmaps_table = (struct x_pixmap **)
  1893.     xmalloc (glyph_to_x_pixmaps_size * sizeof (glyph_to_x_pixmaps_table[0]));
  1894.   max_pixmap_id = 0;
  1895.  
  1896.   BLOCK_INPUT;
  1897.   builtin_continuer_pixmap.glyph_id = max_pixmap_id++;
  1898.   builtin_continuer_pixmap.width = continuer_width;
  1899.   builtin_continuer_pixmap.height = continuer_height;
  1900.   builtin_continuer_pixmap.depth = 0;
  1901.   builtin_continuer_pixmap.pixmap =
  1902.     XCreateBitmapFromData (dpy, root, (char *) continuer_bits,
  1903.                continuer_width, continuer_height);
  1904.   builtin_continuer_pixmap.mask = builtin_continuer_pixmap.pixmap;
  1905.   glyph_to_x_pixmaps_table [builtin_continuer_pixmap.glyph_id] =
  1906.     &builtin_continuer_pixmap;
  1907.  
  1908.   builtin_truncator_pixmap.glyph_id = max_pixmap_id++;
  1909.   builtin_truncator_pixmap.width = truncator_width;
  1910.   builtin_truncator_pixmap.height = truncator_height;
  1911.   builtin_truncator_pixmap.depth = 0;
  1912.   builtin_truncator_pixmap.pixmap =
  1913.     XCreateBitmapFromData (dpy, root, (char *) truncator_bits,
  1914.                continuer_width, continuer_height);
  1915.   builtin_truncator_pixmap.mask = builtin_truncator_pixmap.pixmap;
  1916.   glyph_to_x_pixmaps_table [builtin_truncator_pixmap.glyph_id] =
  1917.     &builtin_truncator_pixmap;
  1918.  
  1919.   builtin_rarrow_pixmap.glyph_id = max_pixmap_id++;
  1920.   builtin_rarrow_pixmap.width = rarrow_width;
  1921.   builtin_rarrow_pixmap.height = rarrow_height;
  1922.   builtin_rarrow_pixmap.depth = 0;
  1923.   builtin_rarrow_pixmap.pixmap =
  1924.     XCreateBitmapFromData (dpy, root, (char *) rarrow_bits,
  1925.                rarrow_width, rarrow_height);
  1926.   builtin_rarrow_pixmap.mask = builtin_rarrow_pixmap.pixmap;
  1927.   glyph_to_x_pixmaps_table [builtin_rarrow_pixmap.glyph_id] =
  1928.     &builtin_rarrow_pixmap;
  1929.   UNBLOCK_INPUT;
  1930.  
  1931.   x_pixmap_table = make_strings_hashtable (20);
  1932. }
  1933.  
  1934.  
  1935. extern Pixmap load_pixmap_1 (Display *, Window, Lisp_Object,
  1936.                  unsigned int *, unsigned int *, unsigned int *,
  1937.                  Pixmap *);
  1938.  
  1939.  
  1940. struct x_pixmap *
  1941. x_get_pixmap (Lisp_Object lisp_name, char *hash_suffix)
  1942. {
  1943.   Display *dpy = x_current_display;
  1944.   char hash_buf [255];
  1945.   char *name = (char *) XSTRING (lisp_name)->data;
  1946.   struct x_pixmap *value = 0;
  1947.   struct x_pixmap dummy;
  1948.  
  1949.   strcpy (hash_buf, name);
  1950.   if (hash_suffix)
  1951.     strcat (hash_buf, hash_suffix);
  1952.  
  1953.   if (gethash ((void *) hash_buf, x_pixmap_table, (void *) &value))
  1954.     if (value) return value;
  1955.  
  1956.   dummy.pixmap = load_pixmap_1 (dpy, DefaultRootWindow (dpy), lisp_name,
  1957.                 &dummy.width, &dummy.height, &dummy.depth,
  1958.                 &dummy.mask);
  1959.   /* we malloc after load_pixmap_1 has returned because that function
  1960.      can signal a lisp error.  We could also use unwind-protect... */
  1961.   name = strdup (name);
  1962.   value = (struct x_pixmap *) xmalloc (sizeof (struct x_pixmap));
  1963.   dummy.face_id = ~0;
  1964.   memcpy (value, &dummy, sizeof (struct x_pixmap));
  1965.   puthash ((void *) strdup (hash_buf), (void *) value, x_pixmap_table);
  1966.   value->glyph_id = max_pixmap_id;
  1967.   if (max_pixmap_id >= glyph_to_x_pixmaps_size)
  1968.     {
  1969.       glyph_to_x_pixmaps_size += 50;
  1970.       glyph_to_x_pixmaps_table = (struct x_pixmap **)
  1971.     xrealloc (glyph_to_x_pixmaps_table,
  1972.           glyph_to_x_pixmaps_size * sizeof (struct x_pixmap *));
  1973.     }
  1974.   glyph_to_x_pixmaps_table [max_pixmap_id] = value;
  1975.   max_pixmap_id++;
  1976.   return value;
  1977. }
  1978.  
  1979.  
  1980. extern void (*beep_hook) ();
  1981.  
  1982. static void
  1983. make_argc_argv (argv_list, argc, argv)
  1984.      Lisp_Object argv_list;
  1985.      int* argc;
  1986.      char*** argv;
  1987. {
  1988.   Lisp_Object next;
  1989.   int n = Flength (argv_list);
  1990.   int i;
  1991.   *argv = (char**)xmalloc (n * sizeof (char*));
  1992.  
  1993.   for (i = 0, next = argv_list; i < n; i++, next = XCONS (next)->cdr)
  1994.     {
  1995.       CHECK_STRING (XCONS (next)->car, 0);
  1996.       (*argv) [i] = (char*)(XSTRING (XCONS (next)->car)->data);
  1997.     }
  1998.   *argc = i;
  1999. }
  2000.  
  2001. static Lisp_Object
  2002. make_arg_list (argc, argv)
  2003.      int argc;
  2004.      char** argv;
  2005. {
  2006.   Lisp_Object result;
  2007.   int i;
  2008.  
  2009.   for (i = 0, result = Qnil; i < argc; i++)
  2010.     result = Fcons (build_string (argv [i]), result);
  2011.   return Fnreverse (result);
  2012. }
  2013.  
  2014. static XrmOptionDescRec 
  2015. emacs_options[] =
  2016. {
  2017.   {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
  2018.      XrmoptionSepArg, NULL},
  2019.   {"-ib",    "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
  2020.   {"-geometry",    "*EmacsScreen.initialGeometry", XrmoptionSepArg, NULL},
  2021.   {"-iconic",    "*EmacsShell.iconic", XrmoptionNoArg, (XtPointer) "on"},
  2022.   {"-T",    "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
  2023.   {"-wn",    "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
  2024.   {"-title",    "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
  2025.   {"-iconname",    "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
  2026.   {"-in",    "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
  2027.   {"-mc",    "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
  2028.   {"-cr",    "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
  2029. };
  2030.  
  2031.  
  2032. static void sanity_check_geometry_resource (Display *);
  2033. extern void x_init_modifier_mapping (Display *);
  2034.  
  2035. #ifdef SIGIO
  2036. extern void init_sigio (void);
  2037. #endif
  2038.  
  2039. extern Lisp_Object Vx_emacs_application_class;
  2040. extern int x_selection_timeout;
  2041.  
  2042. Lisp_Object
  2043. x_term_init (argv_list)
  2044.      Lisp_Object argv_list;
  2045. {
  2046.   int argc;
  2047.   char** argv;
  2048.   char *app_class;
  2049. #ifdef F_SETOWN
  2050.   extern int old_fcntl_owner;
  2051. #endif
  2052.  
  2053.   if (STRINGP (Vx_emacs_application_class) &&
  2054.       XSTRING (Vx_emacs_application_class)->size > 0)
  2055.     app_class = (char *) XSTRING (Vx_emacs_application_class)->data;
  2056.   else
  2057.     app_class = "Emacs";
  2058.  
  2059.   make_argc_argv (argv_list, &argc, &argv);
  2060.  
  2061.   Xt_app_shell = XtAppInitialize (&Xt_app_con, app_class,
  2062.                   emacs_options, XtNumber(emacs_options),
  2063.                   &argc, argv,
  2064.                   0, NULL, 0);
  2065.   x_current_display = XtDisplay (Xt_app_shell);
  2066.  
  2067.   if (x_current_display == 0)
  2068.     fatal ("X server not responding; check the DISPLAY environment variable or use \"-d\"\n");
  2069.   
  2070.   x_file_descriptor = ConnectionNumber (x_current_display);
  2071.  
  2072.   sanity_check_geometry_resource (x_current_display);
  2073.  
  2074.   /* In event-Xt.c */
  2075.   x_init_modifier_mapping (x_current_display);
  2076.   
  2077.   /* In xselect.c */
  2078.   x_selection_timeout = (XtAppGetSelectionTimeout (Xt_app_con) / 1000);
  2079.  
  2080.   {
  2081.     char tem_name[MAXPATHLEN];
  2082.     int l;
  2083.  
  2084.     gethostname (tem_name, MAXPATHLEN - 1);
  2085.     tem_name[99] = 0;
  2086.     if ((l = strlen (tem_name)) < MAXPATHLEN -1)
  2087.       {
  2088.     hostname = (char *) xmalloc (l+1);
  2089.     memcpy (hostname, tem_name, l + 1);
  2090.       }
  2091.     else
  2092.       {
  2093.     hostname = (char *) xmalloc (10);
  2094.     memcpy (hostname, "Somewhere", 9);
  2095.     hostname[10] = 0;
  2096.       }
  2097.     id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size +
  2098.                 strlen (hostname) + 2);
  2099.     sprintf (id_name, "%s@%s", XSTRING (Vinvocation_name)->data, hostname);
  2100.   }
  2101.   
  2102. #ifdef F_SETOWN
  2103.   old_fcntl_owner = fcntl (x_file_descriptor, F_GETOWN, 0);
  2104. #ifdef F_SETOWN_SOCK_NEG
  2105.   /* stdin is a socket here */
  2106.   fcntl (x_file_descriptor, F_SETOWN, -getpid ());
  2107. #else
  2108.   fcntl (x_file_descriptor, F_SETOWN, getpid ());
  2109. #endif /* F_SETOWN_SOCK_NEG */
  2110. #endif /* F_SETOWN */
  2111.  
  2112. #ifdef SIGIO
  2113.   init_sigio ();
  2114. #endif
  2115.  
  2116.   /* Must use interrupt input because we cannot otherwise
  2117.      arrange for C-g to be noticed immediately.
  2118.      We cannot connect it to SIGINT.  */
  2119.   Fset_input_mode (Qt, Qnil, Qt);
  2120.  
  2121.   clear_screen_hook = XTclear_screen;
  2122.   clear_end_of_line_hook = XTclear_end_of_line;
  2123.   ins_del_lines_hook = XTins_del_lines;
  2124.   ring_bell_hook = XTring_bell;
  2125.   beep_hook = XTsimple_beep;
  2126.   write_glyphs_hook = XTwrite_glyphs;
  2127.   update_begin_hook = XTupdate_begin;
  2128.   update_end_hook = XTupdate_end;
  2129.   set_terminal_window_hook = XTset_terminal_window;
  2130.   read_socket_hook = (int (*)())-1;
  2131.   cursor_to_hook = XTcursor_to;
  2132.  
  2133.   scroll_region_ok = 1;        /* we'll scroll partial screens */
  2134.   char_ins_del_ok = 0;        /* just as fast to write the line */
  2135.   line_ins_del_ok = 1;        /* we'll just blt 'em */
  2136.   fast_clear_end_of_line = 1;    /* X does this well */
  2137.   memory_below_screen = 0;    /* we don't remember what scrolls 
  2138.                    off the bottom */
  2139.   baud_rate = 19200;
  2140.   x_interline_space = 0;
  2141.  
  2142.   last_bar_cursor = Qnil;
  2143.  
  2144.   init_bitmap_tables ();
  2145.  
  2146.   XSetErrorHandler (x_error_handler);
  2147.   XSetIOErrorHandler (x_IO_error_handler);
  2148.  
  2149.   emacs_Xt_make_event_stream ();
  2150.  
  2151.   /* Disable Window Change signals;  they are handled by X events. */
  2152. #ifdef SIGWINCH
  2153.   signal (SIGWINCH, SIG_IGN);
  2154. #endif /* SIGWINCH */
  2155.  
  2156.   {
  2157.     Lisp_Object L = make_arg_list (argc, argv);
  2158.     xfree (argv);
  2159.     return L;
  2160.   }
  2161. }
  2162.  
  2163. static void
  2164. sanity_check_geometry_resource (Display *dpy)
  2165. {
  2166.   char *app_name, *app_class, *s;
  2167.   char buf1 [255], buf2 [255];
  2168.   char *type;
  2169.   XrmValue value;
  2170.   XtGetApplicationNameAndClass (dpy, &app_name, &app_class);
  2171.   strcpy (buf1, app_name);
  2172.   strcpy (buf2, app_class);
  2173.   for (s = buf1; *s; s++) if (*s == '.') *s = '_';
  2174.   strcat (buf1, "._no_._such_._resource_.geometry");
  2175.   strcat (buf2, "._no_._such_._resource_.Geometry");
  2176.   if (XrmGetResource (XtDatabase (dpy), buf1, buf2, &type, &value) == True)
  2177.     {
  2178.       fprintf (stderr, "\n\
  2179. Apparently \"%s*geometry: %s\" or \"%s*geometry: %s\" was\n\
  2180. specified in the resource database.  Specifying \"*geometry\" will make\n\
  2181. emacs (and most other X programs) malfunction in obscure ways.  You\n\
  2182. should always use \".geometry\" instead.\n\n",
  2183.            app_name, (char *) value.addr,
  2184.            app_class, (char *) value.addr);
  2185.       exit (-1);
  2186.     }
  2187. }
  2188.  
  2189.  
  2190. static void
  2191. x_update_wm_hints (widget)
  2192.      Widget widget;
  2193. {
  2194.   XSizeHints hints;
  2195.   long supplied = 0;
  2196.   BLOCK_INPUT;
  2197.   if (XGetWMNormalHints (XtDisplay (widget), XtWindow (widget),
  2198.              &hints, &supplied))
  2199.     {
  2200.       hints.flags |= USPosition;
  2201.       hints.x = widget->core.x;
  2202.       hints.y = widget->core.y;
  2203.     }
  2204.   else
  2205.     {
  2206.       memset ((char *) &hints, 0, sizeof (hints));
  2207.       hints.flags = USPosition;
  2208.     }
  2209.   XSetWMNormalHints (XtDisplay (widget), XtWindow (widget), &hints);
  2210.   UNBLOCK_INPUT;
  2211. }
  2212.  
  2213.  
  2214. static void
  2215. x_calc_absolute_position (s)
  2216.      struct screen *s;
  2217. {
  2218.   Display *dpy = XtDisplay (s->display.x->widget);
  2219.   int screen_w = DisplayWidth (dpy, DefaultScreen (dpy));
  2220.   int screen_h = DisplayHeight (dpy, DefaultScreen (dpy));
  2221.   int shell_w = s->display.x->widget->core.width;
  2222.   int shell_h = s->display.x->widget->core.height;
  2223.   /* #### We should increment shell_w and shell_h by the size of the
  2224.      window-manager decoration.  Is there any easy way to find that?
  2225.    */
  2226.   if (s->display.x->left_pos < 0)
  2227.     s->display.x->left_pos = screen_w - shell_w + s->display.x->left_pos;
  2228.   if (s->display.x->top_pos < 0)
  2229.     s->display.x->top_pos = screen_h - shell_h + s->display.x->top_pos;
  2230. }
  2231.  
  2232. void
  2233. x_set_offset (s, xoff, yoff)
  2234.      struct screen *s;
  2235.      int xoff, yoff;
  2236. {
  2237.   s->display.x->top_pos = yoff;
  2238.   s->display.x->left_pos = xoff;
  2239.   x_calc_absolute_position (s);
  2240.   s->display.x->widget->core.y = s->display.x->top_pos;
  2241.   s->display.x->widget->core.x = s->display.x->left_pos;
  2242.   BLOCK_INPUT;
  2243.   XMoveWindow (XtDisplay (s->display.x->widget),
  2244.            XtWindow (s->display.x->widget),
  2245.            s->display.x->widget->core.x,
  2246.            s->display.x->widget->core.y);
  2247.   UNBLOCK_INPUT;
  2248.   /* Update the hints so that, if this window is iconified, it will come back
  2249.      at the same place.  We can't look at s->visible to determine this because
  2250.      it might not be up-to-date yet (the queue might not be processed.)
  2251.    */
  2252.   x_update_wm_hints (s->display.x->widget);
  2253. }
  2254.  
  2255. /* Call this to change the size of screen S's x-window. */
  2256.  
  2257. extern void EmacsScreenSetCharSize (Widget, int, int);
  2258.  
  2259. void
  2260. x_set_window_size (s, cols, rows)
  2261.      struct screen *s;
  2262.      int cols, rows;
  2263. {
  2264.   BLOCK_INPUT;
  2265.   EmacsScreenSetCharSize (s->display.x->edit_widget, cols, rows);
  2266.   UNBLOCK_INPUT;
  2267. }
  2268.  
  2269.  
  2270.  
  2271. void
  2272. x_set_mouse_position (s, x, y)
  2273.      struct screen *s;
  2274.      int x, y;
  2275. {
  2276.   int pix_x, pix_y;
  2277.   struct glyph_dimensions *dimensions;
  2278.  
  2279.   x_raise_screen (s, 0);
  2280.  
  2281.   if (x >= 0)
  2282.     dimensions = get_glyph_dimensions (s, s->phys_cursor_x, s->phys_cursor_y);
  2283.   if (!dimensions)
  2284.     return;
  2285.  
  2286.   if (x < 0)
  2287.     pix_x = PIXEL_WIDTH (s) / 2;
  2288.   else
  2289.     pix_x = dimensions->top_left_x + dimensions->width / 2;
  2290.  
  2291.   if (y < 0)
  2292.     pix_y = PIXEL_HEIGHT (s) / 2;
  2293.   else
  2294.     pix_y = (s->current_glyphs->top_left_y[y]
  2295.          + s->current_glyphs->pix_height[y] / 2);
  2296.  
  2297.   BLOCK_INPUT;
  2298.   XWarpPointer (x_current_display, None, XtWindow (s->display.x->edit_widget),
  2299.            0, 0, 0, 0, pix_x, pix_y);
  2300.   UNBLOCK_INPUT;
  2301. }
  2302.  
  2303.  
  2304. static int
  2305. should_raise_by_send_event;
  2306.  
  2307. static int
  2308. handle_raise_error (Display* display, XErrorEvent* event)
  2309. {
  2310.   should_raise_by_send_event = 1;
  2311.   return 0;
  2312. }
  2313.  
  2314. /* Raise screen S.  */
  2315. void
  2316. x_raise_screen (s, force)
  2317.      struct screen *s;
  2318.      int force;
  2319. {
  2320.   Widget bottom_dialog;
  2321.   Window emacs_window;
  2322.   XWindowChanges xwc;
  2323.   int flags;
  2324.   int (*prev_handler) (Display*, XErrorEvent*);
  2325.  
  2326.   BLOCK_INPUT;
  2327.   if (s->visible || force)
  2328.     {
  2329.       emacs_window = XtWindow (s->display.x->widget);
  2330.       /* first raises all the dialog boxes, then put emacs just below the 
  2331.        * bottom most dialog box */
  2332.       bottom_dialog = lw_raise_all_pop_up_widgets ();
  2333.       if (bottom_dialog && XtWindow (bottom_dialog))
  2334.     {
  2335.       xwc.sibling = XtWindow (bottom_dialog);
  2336.       xwc.stack_mode = Below;
  2337.       flags = CWSibling | CWStackMode;
  2338.     }
  2339.       else
  2340.     {
  2341.       xwc.stack_mode = Above;
  2342.       flags = CWStackMode;
  2343.     }
  2344.  
  2345.       /* get ready to handle the error generated by XConfigureWindow */
  2346.       XSync (x_current_display, False);
  2347.       should_raise_by_send_event = 0;
  2348.       prev_handler = XSetErrorHandler (handle_raise_error);
  2349.       /* first try the plain configure notify and detect an error */
  2350.       XConfigureWindow (x_current_display, emacs_window, flags, &xwc);
  2351.  
  2352.       /* try to see if some error is generated */
  2353.       XSync (x_current_display, False);
  2354.       XSetErrorHandler (prev_handler);
  2355.       if (should_raise_by_send_event)
  2356.     {
  2357.       XConfigureRequestEvent ev;
  2358.       Window root = RootWindow (x_current_display,
  2359.                     DefaultScreen (x_current_display));
  2360.       ev.type = ConfigureRequest;
  2361.       ev.parent = root;
  2362.       ev.window = window;
  2363.       ev.above = XtWindow (bottom_dialog);
  2364.       ev.value_mask = flags;
  2365.       XSendEvent (x_current_display, root, False,
  2366.               SubstructureRedirectMask|SubstructureNotifyMask,
  2367.               (XEvent *)&ev);
  2368.     }
  2369.     }
  2370.   UNBLOCK_INPUT;
  2371. }
  2372.  
  2373. /* Lower screen S.  */
  2374. void
  2375. x_lower_screen (s)
  2376.      struct screen *s;
  2377. {
  2378.   BLOCK_INPUT;
  2379.   if (s->visible)
  2380.     XLowerWindow (x_current_display, XtWindow(s->display.x->widget));
  2381.   UNBLOCK_INPUT;
  2382. }
  2383.  
  2384. /* Change from withdrawn state to mapped state. */
  2385. void
  2386. x_make_screen_visible (s)
  2387.      struct screen *s;
  2388. {
  2389.   BLOCK_INPUT;
  2390.   if (!s->visible)
  2391.     XMapRaised (x_current_display, XtWindow (s->display.x->widget));
  2392.   else
  2393.     x_raise_screen (s, 0);
  2394.   UNBLOCK_INPUT;
  2395. }
  2396.  
  2397. /* Change from mapped state to withdrawn state. */
  2398. void
  2399. x_make_screen_invisible (s)
  2400.      struct screen *s;
  2401. {
  2402.   if (! s->visible)
  2403.     return;
  2404.  
  2405.   /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
  2406.      that the current position of the window is user-specified, rather than
  2407.      program-specified, so that when the window is mapped again, it will be
  2408.      placed at the same location, without forcing the user to position it
  2409.      by hand again (they have already done that once for this window.)
  2410.    */
  2411.   x_update_wm_hints (s->display.x->widget);
  2412.  
  2413.   BLOCK_INPUT;
  2414.   /* New function available with R4 */
  2415.   if (!XWithdrawWindow (x_current_display,
  2416.             XtWindow(s->display.x->widget),
  2417.             DefaultScreen (x_current_display)))
  2418.     {
  2419.       UNBLOCK_INPUT;
  2420.       error ("Can't notify window manager of iconification.");
  2421.     }
  2422.   
  2423.   UNBLOCK_INPUT;
  2424. }
  2425.  
  2426. /* Change window state from mapped to iconified. */
  2427. void
  2428. x_iconify_screen (s)
  2429.      struct screen *s;
  2430. {
  2431.   int result;
  2432.   BLOCK_INPUT;
  2433.   result = XIconifyWindow (x_current_display,
  2434.                XtWindow(s->display.x->widget),
  2435.                DefaultScreen (x_current_display));
  2436.   UNBLOCK_INPUT;
  2437.  
  2438.   if (!result)
  2439.     error ("Can't notify window manager of iconification.");
  2440.  
  2441.   s->iconified = 1;
  2442. }
  2443.  
  2444.  
  2445. extern Time mouse_timestamp;
  2446. extern int any_screen_has_focus_p;
  2447.  
  2448. /* Sets the X focus to screen s.  Should only be called from
  2449.    select_screen.  Will only set focus if any screen was given the focus
  2450.    by the WM. */
  2451. void
  2452. x_focus_screen (s)
  2453.      struct screen *s;
  2454. {
  2455.   XWindowAttributes xwa;
  2456.   struct x_display* x;
  2457.  
  2458.   if (!SCREEN_IS_X (s))
  2459.     return;
  2460.  
  2461.   x = s->display.x;
  2462.  
  2463.   if (!XtWindow (x->widget))
  2464.     return;
  2465.  
  2466.   BLOCK_INPUT;
  2467.   /* Always set the Xt keyboard focus. */
  2468.   lw_set_keyboard_focus (x->widget, x->edit_widget);
  2469.  
  2470.   /* Do the ICCCM focus change if we don't have focus already and
  2471.      the window is still visible.  The s->visible flag might not be
  2472.      up-to-date, because we might not have processed magic events
  2473.      recently.  So make a server round-trip to find out whether it's
  2474.      really mapped right now.  We grab the server to do this, because
  2475.      that's the only way to eliminate the race condition.
  2476.    */
  2477.   if (!x->focus_p && any_screen_has_focus_p)
  2478.     {
  2479.       XGrabServer (XtDisplay (x->widget));
  2480.       if (XGetWindowAttributes (XtDisplay (x->widget), XtWindow (x->widget),
  2481.                 &xwa))
  2482.     s->visible = xwa.map_state == IsViewable;
  2483.       
  2484.       if (s->visible)
  2485.     {
  2486.       Window focus;
  2487.       int revert_to;
  2488.       XGetInputFocus (XtDisplay (x->widget), &focus, &revert_to);
  2489.       /* Don't explicitly set the focus on this window unless the focus
  2490.          was on some other window (not PointerRoot).  Note that, even when
  2491.          running a point-to-type window manager like *twm, there is always
  2492.          a focus window; the window manager maintains that based on the
  2493.          mouse position.  If you set the "NoTitleFocus" option in these
  2494.          window managers, then the server itself maintains the focus via
  2495.          PointerRoot, and changing that to focus on the window would make
  2496.          the window grab the focus.  Very bad.
  2497.        */
  2498.       if (focus != PointerRoot)
  2499.         {
  2500.           XSetInputFocus (XtDisplay (x->widget), XtWindow (x->widget),
  2501.                   RevertToParent, mouse_timestamp);
  2502.           XFlush (XtDisplay (x->widget));
  2503.         }
  2504.     }
  2505.       XUngrabServer (XtDisplay (x->widget));
  2506.       XFlush (XtDisplay (x->widget)); /* hey, I'd like to DEBUG this... */
  2507.     }
  2508.   UNBLOCK_INPUT;
  2509. }
  2510.  
  2511. extern Lisp_Object WM_COMMAND_screen; /* in xfns.c */
  2512. extern Lisp_Object Vcommand_line_args;
  2513.  
  2514. /* Called from xfns.c when screens are created */
  2515. void
  2516. maybe_store_wm_command (struct screen *s)
  2517. {
  2518.   if (NILP (WM_COMMAND_screen))
  2519.     {
  2520.       Widget w = s->display.x->widget;
  2521.       int argc;
  2522.       char **argv;
  2523.       make_argc_argv (Vcommand_line_args, &argc, &argv);
  2524.       BLOCK_INPUT;
  2525.       XSetCommand (XtDisplay (w), XtWindow (w), argv, argc);
  2526.       xfree (argv);
  2527.       XSET (WM_COMMAND_screen, Lisp_Screen, s);
  2528.       UNBLOCK_INPUT;
  2529.     }
  2530. }
  2531.  
  2532. /* If we're deleting the screen on which the WM_COMMAND property has been
  2533.    set, then move that property to another screen so that there is exactly
  2534.    one screen that has that property set.
  2535.  */
  2536. static void
  2537. maybe_move_wm_command (struct screen *s)
  2538. {
  2539.   if (s == XSCREEN (WM_COMMAND_screen))
  2540.     {
  2541.       Lisp_Object rest = Vscreen_list;
  2542.       /* find some random other X screen that is not this one, or give up */
  2543.       while (!NILP (rest) &&
  2544.          (s == XSCREEN (XCONS (rest)->car) ||
  2545.           !SCREEN_IS_X (XSCREEN (XCONS (rest)->car))))
  2546.     rest = XCONS (rest)->cdr;
  2547.       if (NILP (rest)) return;
  2548.       s = XSCREEN (XCONS (rest)->car);
  2549.       WM_COMMAND_screen = Qnil;
  2550.       maybe_store_wm_command (s);
  2551.     }
  2552. }
  2553.  
  2554.  
  2555. /* Destroy the X window of screen S.
  2556.    DISPL is the former s->display (since s->display
  2557.    has already been nulled out).  */
  2558. void
  2559. x_destroy_window (s)
  2560.      struct screen *s;
  2561. {
  2562.   maybe_move_wm_command (s);
  2563.   BLOCK_INPUT;
  2564.   XtDestroyWidget(s->display.x->widget);
  2565.   UNBLOCK_INPUT;
  2566.   
  2567.   xfree (s->display.x);
  2568. #if 0
  2569.   * Punt on this for a while
  2570.  *  /* If we don't own this window (we didn't create it) then we can't destroy
  2571.  *     it.
  2572.  *     We set the window to be the external_window, so that XtDestroyWidget
  2573.  *     won't call XDestroyWindow.  Had we just set the window to 0,
  2574.  *     XtDestroyWidget would only have done half the job. 
  2575.  *     We also have to check if the parent window belongs to a noteWidget
  2576.  *     and then remove us from this note. 
  2577.  *     This is among the worse code I ever wrote. --Matthieu.*/
  2578.  *  {int destroyed_p = False;
  2579.  *   if (displ.x->own_window != True) 
  2580.  *     {
  2581.  *       Window root;
  2582.  *       Window parent;
  2583.  *       Window* children;
  2584.  *       unsigned int n_children;
  2585.  *       Widget parent_widget;
  2586.  *       
  2587.  */*       displ.x->window_desc = 0; */
  2588.  *       displ.x->widget->core.window =
  2589.  *     ((EmacsShellWidget)displ.x->widget)->emacsShell.external_window;
  2590.  *       
  2591.  *       if (XQueryTree (XtDisplay (displ.x->widget),
  2592.  *               XtWindow (displ.x->widget), 
  2593.  *               &root, &parent, &children, &n_children)){
  2594.  *     parent_widget = XtWindowToWidget (x_current_display, parent);
  2595.  *     if (parent_widget){
  2596.  *       destroyed_p = True;
  2597.  *       set_text_widget ((NoteWidget)parent_widget, 0);
  2598.  *     }
  2599.  *       }
  2600.  *     }else
  2601.  *       /* this will tell the emacs shell to destroy its window */
  2602.  *       ((EmacsShellWidget)displ.x->widget)->emacsShell.external_window = 0;
  2603.  * }
  2604. #endif
  2605. }
  2606.  
  2607. #endif /* HAVE_X_WINDOWS */
  2608.