home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / emacs / src / xterm.c < prev    next >
C/C++ Source or Header  |  1991-12-03  |  47KB  |  1,934 lines

  1. /* X Communication module for terminals which understand the X protocol.
  2.    Copyright (C) 1985, 1986, 1987, 1988 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 1, 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. /* Written by Yakim Martillo, mods and things by Robert Krawitz  */
  21.  
  22. /*
  23.  *    $Source: /u2/third_party/gnuemacs.chow/src/RCS/xterm.c,v $
  24.  *    $Author: rlk $
  25.  *    $Locker:  $
  26.  *    $Header: xterm.c,v 1.28 86/08/27 13:30:57 rlk Exp $
  27.  */
  28.  
  29. #ifndef lint
  30. static char *rcsid_TrmXTERM_c = "$Header: xterm.c,v 1.28 86/08/27 13:30:57 rlk Exp $";
  31. #endif    lint
  32.  
  33. /* On 4.3 this loses if it comes after xterm.h.  */
  34. #include <signal.h>
  35. #include "config.h"
  36.  
  37. #ifdef HAVE_X_WINDOWS
  38.  
  39. #include "lisp.h"
  40. #undef NULL
  41.  
  42. /* This may include sys/types.h, and that somehow loses
  43.    if this is not done before the other system files.  */
  44. #include "xterm.h"
  45.  
  46. /* Load sys/types.h if not already loaded.
  47.    In some systems loading it twice is suicidal.  */
  48. #ifndef makedev
  49. #include <sys/types.h>
  50. #endif
  51.  
  52. #if !defined(USG) || defined(IBMRTAIX)
  53. #include <sys/time.h>
  54. #else
  55. #include <time.h>
  56. #endif /* USG and not IBMRTAIX */
  57.  
  58. #include <sys/ioctl.h>
  59. #include <fcntl.h>
  60. #include <stdio.h>
  61. #include <ctype.h>
  62. #include <errno.h>
  63. #ifdef BSD
  64. #include <strings.h>
  65. #endif
  66. #include <sys/stat.h>
  67.  
  68. #include "dispextern.h"
  69. #include "termhooks.h"
  70. #include "termopts.h"
  71. #include "termchar.h"
  72. #include "sink.h"
  73. #include "sinkmask.h"
  74. #include <X/Xkeyboard.h>
  75. /*#include <X/Xproto.h>    */
  76.  
  77. /* Allow m- file to inhibit use of FIONREAD.  */
  78. #ifdef BROKEN_FIONREAD
  79. #undef FIONREAD
  80. #endif
  81.  
  82. /* We are unable to use interrupts if FIONREAD is not available,
  83.    so flush SIGIO so we won't try. */
  84. #ifndef FIONREAD
  85. #ifdef SIGIO
  86. #undef SIGIO
  87. #endif
  88. #endif
  89.  
  90. /* Allow config to specify default font.  */
  91. #ifndef X_DEFAULT_FONT
  92. #define X_DEFAULT_FONT "vtsingle"
  93. #endif
  94.  
  95. #define min(a,b) ((a)<(b) ? (a) : (b))
  96. #define max(a,b) ((a)>(b) ? (a) : (b))
  97. #define sigunblockx(sig) sigblock (0)
  98. #define sigblockx(sig) sigblock (1 << ((sig) - 1))
  99. XREPBUFFER Xxrepbuffer;
  100. int pixelwidth;
  101. int pixelheight;
  102. int PendingExposure;
  103. int PendingIconExposure;
  104. #define MAXICID 80
  105. char iconidentity[MAXICID];
  106. #define ICONTAG "emacs@"
  107. #define METABIT 0x80
  108. Window XXIconWindow;
  109. Bitmap XXIconMask;
  110.  
  111. char *XXcurrentfont;
  112. char *default_window;
  113. int informflag;
  114. extern int initialized;
  115.  
  116. extern char *alternate_display;
  117.  
  118. int XXdebug;
  119. int XXpid;
  120. extern int screen_garbaged;
  121. int XXxoffset, XXyoffset;
  122. int IconWindow;
  123.  
  124. int WindowMapped;
  125. int CurHL;
  126.  
  127. static int flexlines;        /* last line affect by dellines or */
  128.                 /* inslines functions */
  129. extern int errno;
  130. int VisibleX, VisibleY;    /* genuine location of cursor on screen */
  131.                 /* if it is there */
  132. static int SavedX, SavedY;    /* Where the cursor was before update */
  133.                 /* started */
  134.  
  135. int bitblt;        /* Used to track bit blt events */
  136. int CursorExists;    /* during updates cursor is turned off */
  137. static int InUpdate;        /* many of functions here may be invoked */
  138.                 /* even if no update in progress, when */
  139.                 /* no update is in progress the action */
  140.                 /* can be slightly different */
  141.  
  142. short MouseCursor[] = {
  143.   0x0000, 0x0008, 0x0018, 0x0038,
  144.   0x0078, 0x00f8, 0x01f8, 0x03f8,
  145.   0x07f8, 0x00f8, 0x00d8, 0x0188,
  146.   0x0180, 0x0300, 0x0300, 0x0000};
  147.  
  148. short MouseMask[] = {
  149.   0x000c, 0x001c, 0x003c, 0x007c,
  150.   0x00fc, 0x01fc, 0x03fc, 0x07fc,
  151.   0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
  152.   0x03cc, 0x0780, 0x0780, 0x0300};
  153.  
  154. Display *XXdisplay;
  155. FontInfo *fontinfo;
  156. Window XXwindow;
  157. Cursor EmacsCursor;
  158.  
  159. char *fore_color;    /* Variables to store colors */
  160. char *back_color;
  161. char *brdr_color;
  162. char *curs_color;
  163. char *mous_color;
  164.  
  165. int fore;
  166. int back;
  167. int brdr;
  168. int curs;
  169. int mous;
  170.  
  171. static WindowInfo windowinfo;
  172. WindowInfo rootwindowinfo;
  173.  
  174.  
  175.  
  176. static XKeyPressedEvent XXEvent; /* as X messages are read in they are */
  177.                                 /* stored here */
  178. static XREPBUFFER XXqueue;/* Used for storing up ExposeRegion */
  179.                 /* replies, so that the SIGIO inter- */
  180.                 /* rupt serving routines do almost */
  181.                 /* no writes to the X socket */
  182. /*int CurHL;            /* Current Highlighting actually being */
  183.                 /* being used for bold font right now*/
  184.  
  185. int XXborder;
  186. int XXInternalBorder;
  187.  
  188. int (*handler)();
  189.  
  190. extern Display *XOpenDisplay ();
  191. extern Window XCreateWindow ();
  192. extern Cursor XDefineCursor ();
  193. extern Cursor XCreateCursor ();
  194. extern FontInfo *XOpenFont ();
  195.  
  196. static int flashback ();
  197.  
  198.  
  199. /* HLmode -- Changes the GX function for output strings.  Could be used to
  200.  * change font.  Check an XText library function call. 
  201.  */
  202.  
  203. static
  204. HLmode (new)
  205.      int new;
  206. {
  207.   CurHL =  new;
  208. }
  209.  
  210.  
  211. /* External interface to control of standout mode.
  212.    Call this when about to modify line at position VPOS
  213.    and not change whether it is highlighted.  */
  214.  
  215. XTreassert_line_highlight (highlight, vpos)
  216.      int highlight, vpos;
  217. {
  218.   HLmode (highlight);
  219. }
  220.  
  221. /* Call this when about to modify line at position VPOS
  222.    and change whether it is highlighted.  */
  223.  
  224. static
  225. XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
  226.      int new_highlight, vpos, first_unused_hpos;
  227. {
  228.   HLmode (new_highlight);
  229.   XTmove_cursor (vpos, 0);
  230.   x_clear_end_of_line (0);
  231. }
  232.  
  233.  
  234. /* Used for starting or restarting (after suspension) the X window.  Puts the
  235.  * cursor in a known place, update does not begin with this routine but only
  236.  * with a call to redisplay.  The mouse cursor is warped into the window and
  237.  * then the cursor is turned on.
  238.  */
  239.  
  240.  
  241.  
  242. static
  243. XTset_terminal_modes ()
  244. {
  245.   int stuffpending;
  246. #ifdef XDEBUG
  247.   fprintf (stderr, "XTset_terminal_modes\n");
  248. #endif
  249.   InUpdate = 0;
  250.   stuffpending = 0;
  251.   if (!initialized)
  252.     {
  253.       CursorExists = 0;
  254.       VisibleX = 0;
  255.       VisibleY = 0;
  256.     }
  257.   XTclear_screen ();
  258. #ifdef FIONREAD
  259.   ioctl (0, FIONREAD, &stuffpending);
  260.   if (stuffpending)
  261.     SIGNAL_INPUT ();
  262. #endif
  263. }
  264.  
  265. /* XTmove_cursor moves the cursor to the correct location and checks whether an update
  266.  * is in progress in order to toggle it on.
  267.  */
  268.  
  269. static
  270. XTmove_cursor (row, col)
  271.      register int row, col;
  272. {
  273.   BLOCK_INPUT_DECLARE ()
  274.  
  275.   BLOCK_INPUT ();
  276. #ifdef XDEBUG
  277.   fprintf (stderr, "XTmove_cursor\n");
  278. #endif
  279.   cursor_hpos = col;
  280.   cursor_vpos = row;
  281.   if (InUpdate)
  282.     {
  283.       if (CursorExists)
  284.     {
  285.       CursorToggle ();
  286.     }
  287.       UNBLOCK_INPUT ();
  288.       return;        /* Generally, XTmove_cursor will be invoked */
  289.       /* when InUpdate with !CursorExists */
  290.       /* so that wasteful XFlush is not called */
  291.     }
  292.   if ((row == VisibleY) && (col == VisibleX))
  293.     {
  294.       if (!CursorExists)
  295.     {
  296.       CursorToggle ();
  297.     }
  298.       XFlush ();
  299.       UNBLOCK_INPUT ();
  300.       return;
  301.     }
  302.   if (CursorExists) CursorToggle ();
  303.   VisibleX = col;
  304.   VisibleY = row;
  305.   if (!CursorExists) CursorToggle ();
  306.   XFlush ();
  307.   UNBLOCK_INPUT ();
  308. }
  309.  
  310. /* Used to get the terminal back to a known state after resets.  Usually
  311.  * used when restarting suspended or waiting emacs
  312.  */
  313.  
  314. static
  315. cleanup ()
  316. {
  317.   inverse_video = 0;
  318.   HLmode (0);
  319. }
  320.  
  321. /* Erase current line from column cursor_hpos to column END.
  322.    Leave cursor at END.  */
  323.  
  324. static
  325. XTclear_end_of_line (end)
  326.      register int end;
  327. {
  328.   register int numcols;
  329.  
  330. #ifdef XDEBUG
  331.   fprintf (stderr, "XTclear_end_of_line\n");
  332.  
  333. #endif
  334.   if (cursor_vpos < 0 || cursor_vpos >= screen_height)
  335.     {
  336.       return;
  337.     }
  338.  
  339.   if (end >= screen_width)
  340.     end = screen_width;
  341.   if (end <= cursor_hpos)
  342.     return;
  343.  
  344.   numcols = end - cursor_hpos;
  345.   {
  346.     BLOCK_INPUT_DECLARE ()
  347.  
  348.     BLOCK_INPUT ();
  349.     if (cursor_vpos == VisibleY && VisibleX >= cursor_hpos && VisibleX < end)
  350.       {
  351.     if (CursorExists) CursorToggle ();
  352.       }
  353.     XPixSet (XXwindow,
  354.          cursor_hpos * fontinfo->width + XXInternalBorder,
  355.          cursor_vpos * fontinfo->height+XXInternalBorder,
  356.          fontinfo->width * numcols,
  357.          fontinfo->height,
  358.          back);
  359.     XTmove_cursor (cursor_vpos, end);
  360.     UNBLOCK_INPUT ();
  361.   }
  362. }
  363.  
  364. /* Erase current line from column START to right margin.
  365.    Leave cursor at START.  */
  366.  
  367. static
  368. x_clear_end_of_line (start)
  369.      register int start;
  370. {
  371.   register int numcols;
  372.  
  373. #ifdef XDEBUG
  374.   fprintf (stderr, "x_clear_end_of_line\n");
  375.  
  376. #endif
  377.   if (cursor_vpos < 0 || cursor_vpos >= screen_height)
  378.     {
  379.       return;
  380.     }
  381.  
  382.   if (start < 0)
  383.     start = 0;
  384.   if (start >= screen_width)
  385.     return;
  386.  
  387.   numcols = screen_width - start;
  388.   {
  389.     BLOCK_INPUT_DECLARE ()
  390.  
  391.     BLOCK_INPUT ();
  392.     if (cursor_vpos == VisibleY && VisibleX >= start)
  393.       {
  394.     if (CursorExists) CursorToggle ();
  395.       }
  396.     XPixSet (XXwindow,
  397.          start * fontinfo->width + XXInternalBorder,
  398.          cursor_vpos * fontinfo->height+XXInternalBorder,
  399.          fontinfo->width * numcols,
  400.          fontinfo->height,
  401.          back);
  402.     XTmove_cursor (cursor_vpos, start);
  403.     UNBLOCK_INPUT ();
  404.   }
  405. }
  406.  
  407. static
  408. XTreset_terminal_modes ()
  409. {
  410. #ifdef XDEBUG
  411.   fprintf (stderr, "XTreset_terminal_modes\n");
  412. #endif
  413.   XTclear_screen ();
  414. }
  415.  
  416. static
  417. XTclear_screen ()
  418. {
  419. #ifdef XDEBUG
  420.   fprintf (stderr, "XTclear_screen\n");
  421. #endif
  422.   HLmode (0);
  423.   CursorExists = 0;
  424.  
  425.   cursor_hpos = 0;
  426.   cursor_vpos = 0;
  427.   SavedX = 0;
  428.   SavedY = 0;
  429.   VisibleX = 0;
  430.   VisibleY = 0;
  431.   {
  432.     BLOCK_INPUT_DECLARE ()
  433.  
  434.     BLOCK_INPUT ();
  435.     XClear (XXwindow);
  436.     CursorToggle ();
  437.     if (!InUpdate)
  438.       XFlush ();
  439.     UNBLOCK_INPUT ();
  440.   }
  441. }
  442.  
  443. /* used by dumprectangle which is usually invoked upon ExposeRegion
  444.  * events which come from bit blt's or moving an obscuring opaque window
  445.  */
  446.  
  447. static
  448. dumpchars (current_screen, numcols, tempX, tempY, tempHL)
  449.      register struct matrix *current_screen;
  450.      register int numcols;
  451.      register int tempX, tempY, tempHL;
  452. {
  453.   if (numcols <= 0) return;
  454.   if (((numcols - 1) + tempX) > screen_width)
  455.     {
  456.       numcols = (screen_width - tempX) + 1;
  457.     }
  458.   if ((tempX < 0) || (tempX >= screen_width) ||
  459.       (tempY < 0) || (tempY >= screen_height))
  460.     {
  461.       return;
  462.     }
  463.   XText (XXwindow,
  464.      (tempX * fontinfo->width+XXInternalBorder),
  465.      (tempY * fontinfo->height+XXInternalBorder),
  466.      ¤t_screen->contents[tempY][tempX],
  467.      numcols,
  468.      fontinfo->id,
  469.      (tempHL ? back : fore),
  470.      (tempHL ? fore : back));
  471. }
  472.  
  473. /* When a line has been changed this function is called.  X is so fast
  474.  * that the actual sequence is ignore.  Rather, the new version of the
  475.  * line is simply output if this function is invoked while in UpDate.
  476.  * Sometimes writechars can be invoked when not in update if text is to
  477.  * be output at the end of the line.  In this case the whole line is not
  478.  * output.  Simply the new text at the current cursor position given
  479.  * by VisibleX,Y.  The cursor is moved to the end of the new text.
  480.  */
  481. static
  482. writechars (start, end)
  483.      register char *start, *end;
  484. {
  485.   register int temp_length;
  486.   BLOCK_INPUT_DECLARE ()
  487.  
  488.   BLOCK_INPUT ();
  489.  
  490.   if ((cursor_vpos < 0) || (cursor_vpos >= screen_height))
  491.     {
  492.       UNBLOCK_INPUT ();
  493.       return;
  494.     }
  495.   if (CursorExists)
  496.     {
  497.       CursorToggle ();
  498.     }
  499.   if (InUpdate)
  500.     {
  501.       if (end != start - 1)
  502.     {
  503.       XText (XXwindow,
  504.          (cursor_hpos * fontinfo->width+XXInternalBorder),
  505.          (cursor_vpos * fontinfo->height+XXInternalBorder),
  506.          start,
  507.          end + 1 - start,
  508.          fontinfo->id,
  509.          (CurHL ? back : fore),
  510.          (CurHL ? fore : back));
  511.       XTmove_cursor (cursor_vpos, cursor_hpos + end - start + 1);
  512.     }
  513.     }
  514.   else
  515.     {
  516.       if ((VisibleX < 0) || (VisibleX >= screen_width))
  517.     {
  518.       UNBLOCK_INPUT ();
  519.       return;
  520.     }
  521.       if ((VisibleY < 0) || (VisibleY >= screen_height))
  522.     {
  523.       UNBLOCK_INPUT ();
  524.       return;
  525.     }
  526.       if (((end - start) + VisibleX) >= screen_width)
  527.     {
  528.       end = start + (screen_width - (VisibleX + 1));
  529.     }
  530.       if (end >= start)
  531.     {
  532.        XText (XXwindow,
  533.          (VisibleX * fontinfo->width+XXInternalBorder),
  534.          (VisibleY * fontinfo->height+XXInternalBorder),
  535.          start,
  536.          ((end - start) + 1),
  537.          fontinfo->id,
  538.          (CurHL ? back : fore),
  539.          (CurHL ? fore : back));
  540.       VisibleX = VisibleX + (end - start) + 1;
  541.     }
  542.       if (!CursorExists) CursorToggle ();
  543.     }
  544.   UNBLOCK_INPUT ();
  545. }
  546.  
  547.  
  548. static
  549. XToutput_chars (start, len)
  550.      register char *start;
  551.      register int len;
  552. {
  553. #ifdef XDEBUG
  554.   fprintf (stderr, "XToutput_chars\n");
  555. #endif
  556.   writechars (start, start + len - 1);
  557. }
  558.  
  559. /* The following routine is for the deaf or for the pervert who prefers
  560.  * that his terminal flash at him rather than beep at him.
  561.  */
  562.  
  563. static int flashedback;
  564.  
  565. static
  566. XTflash ()
  567. {
  568. #ifdef ITIMER_REAL
  569.   struct itimerval itimer;
  570.  
  571. #ifdef XDEBUG
  572.   fprintf (stderr, "XTflash\n");
  573. #endif
  574.  
  575.   stop_polling ();
  576.   signal (SIGALRM, flashback);
  577.   getitimer (ITIMER_REAL, &itimer);
  578.   itimer.it_value.tv_usec += 250000;
  579.   itimer.it_interval.tv_sec = 0;
  580.   itimer.it_interval.tv_usec = 0;
  581.   flashedback = 0;
  582.   setitimer (ITIMER_REAL, &itimer, 0);
  583.   {
  584.     BLOCK_INPUT_DECLARE ()
  585.  
  586.     BLOCK_INPUT ();
  587.     XPixFill (XXwindow, 0, 0, screen_width*fontinfo->width+2*XXInternalBorder,
  588.           screen_height * fontinfo->height+2*XXInternalBorder, WhitePixel,
  589.           ClipModeClipped, GXinvert, AllPlanes);
  590.     XFlush ();
  591.     UNBLOCK_INPUT ();
  592.   }
  593.   while (!flashedback) pause ();
  594. #endif /* have ITIMER_REAL */
  595. }
  596.  
  597. static
  598. flashback ()
  599. {
  600. #ifdef ITIMER_REAL
  601. #ifdef SIGIO
  602.   int mask = sigblock (sigmask (SIGIO) | sigmask (SIGALRM));
  603. #else
  604.   int mask = sigblock (sigmask (SIGALRM));
  605. #endif
  606.   XPixFill (XXwindow, 0, 0, screen_width * fontinfo->width+2*XXInternalBorder,
  607.         screen_height * fontinfo->height+2*XXInternalBorder, WhitePixel,
  608.         ClipModeClipped, GXinvert, AllPlanes);
  609.   XFlush ();
  610.   flashedback = 1;
  611.   sigsetmask (mask);
  612.   start_polling ();
  613. #endif /* have ITIMER_REAL */
  614. }
  615.  
  616. /* A kludge to get a bell */
  617.  
  618. static
  619. XTfeep ()
  620. {
  621.   BLOCK_INPUT_DECLARE ()
  622.  
  623.   BLOCK_INPUT ();
  624. #ifdef XDEBUG
  625.   fprintf (stderr, "XTfeep\n");
  626. #endif
  627.   XFeep (0);
  628.   UNBLOCK_INPUT ();
  629. }
  630.  
  631. /* Artificially creating a cursor is hard, the actual position on the
  632.  * screen (either where it is or last was) is tracked with VisibleX,Y.
  633.  * Gnu Emacs code tends to assume a cursor exists in hardward at cursor_hpos,Y
  634.  * and that output text will appear there.  During updates, the cursor is
  635.  * supposed to be blinked out and will only reappear after the update
  636.  * finishes.
  637.  */
  638.  
  639. CursorToggle ()
  640. {
  641.   if (!WindowMapped)
  642.     {
  643.       CursorExists = 0;
  644.       return 0;
  645.     }
  646.   if ((VisibleX < 0) || (VisibleX >= screen_width) ||
  647.       (VisibleY < 0) || (VisibleY >= screen_height))
  648.     {            /* Current Cursor position trash */
  649.       /* Not much can be done */
  650.       XFlush ();
  651.       CursorExists = 0;
  652.       return 0;
  653.       /* Currently the return values are not */
  654.       /* used, but I could anticipate using */
  655.       /* them in the future. */
  656.     }
  657.  
  658.   if (current_screen->enable[VisibleY] &&
  659.       (VisibleX < current_screen->used[VisibleY]))
  660.     {
  661.       if (CursorExists)
  662.     {
  663.       XText (XXwindow,
  664.          VisibleX * fontinfo->width+XXInternalBorder,
  665.          VisibleY * fontinfo->height+XXInternalBorder,
  666.          ¤t_screen->contents[VisibleY][VisibleX], 1,
  667.          fontinfo->id,
  668.          fore, back);
  669.     }
  670.       else
  671.     {
  672.       XText (XXwindow,
  673.          VisibleX * fontinfo->width+XXInternalBorder,
  674.          VisibleY * fontinfo->height+XXInternalBorder,
  675.          ¤t_screen->contents[VisibleY][VisibleX], 1,
  676.          fontinfo->id,
  677.          back, curs);
  678.     }
  679.     }
  680.   else if (CursorExists)
  681.     {
  682.       XPixSet (XXwindow,
  683.            VisibleX * fontinfo->width+XXInternalBorder,
  684.            VisibleY * fontinfo->height+XXInternalBorder,
  685.            fontinfo->width, fontinfo->height, back);
  686.     }
  687.   else
  688.     {
  689.       XPixSet (XXwindow,
  690.            VisibleX * fontinfo->width+XXInternalBorder,
  691.            VisibleY * fontinfo->height+XXInternalBorder,
  692.            fontinfo->width, fontinfo->height, curs);
  693.     }
  694.   CursorExists = !CursorExists;
  695.   /* Cursor has either been blinked in */
  696.   /* or out */
  697.   if (!InUpdate)
  698.     {
  699.       XFlush ();
  700.     }
  701.   return 1;
  702. }
  703.  
  704. /* This routine is used by routines which are called to paint regions */
  705. /* designated by ExposeRegion events.  If the cursor may be in the exposed */
  706. /* region, this routine makes sure it is gone so that dumprectangle can */
  707. /* toggle it back into existance if dumprectangle is invoked when not in */
  708. /* the midst of a screen update. */
  709. static
  710. ClearCursor ()
  711. {
  712.   BLOCK_INPUT_DECLARE ()
  713.  
  714.   BLOCK_INPUT ();
  715.   if (!WindowMapped)
  716.     {
  717.       CursorExists = 0;
  718.       UNBLOCK_INPUT ();
  719.       return;
  720.     }
  721.   if ((VisibleX < 0) || (VisibleX >= screen_width)
  722.       || (VisibleY < 0) || (VisibleY >= screen_height))
  723.     {            /* Current Cursor position trash */
  724.       /* Not much can be done */
  725.       CursorExists = 0;
  726.       UNBLOCK_INPUT ();
  727.       return;
  728.     }
  729.   XPixSet (XXwindow,
  730.       VisibleX * fontinfo->width+XXInternalBorder,
  731.       VisibleY * fontinfo->height+XXInternalBorder,
  732.       fontinfo->width, fontinfo->height,
  733.       back);
  734.   CursorExists = 0;
  735.   UNBLOCK_INPUT ();
  736. }
  737.  
  738. static
  739. XTupdate_begin ()
  740. {
  741.   BLOCK_INPUT_DECLARE ()
  742.  
  743.   BLOCK_INPUT ();
  744. #ifdef XDEBUG
  745.   fprintf (stderr, "XTupdate_begin\n");
  746. #endif
  747.  
  748.   InUpdate = 1;
  749.   if (CursorExists)
  750.     {
  751.       CursorToggle ();
  752.     }
  753.   SavedX = cursor_hpos;        /* The initial"hardware" cursor position is */
  754.   /*  saved because that is where gnu emacs */
  755.   /*  expects the cursor to be at the end of*/
  756.   /* the update */
  757.   SavedY = cursor_vpos;
  758.   dumpqueue ();
  759.   UNBLOCK_INPUT ();
  760. }
  761.  
  762.  
  763. static
  764. XTupdate_end ()
  765. {
  766.   BLOCK_INPUT_DECLARE ()
  767.  
  768.   BLOCK_INPUT ();
  769. #ifdef XDEBUG
  770.   fprintf (stderr, "XTupdate_end\n");
  771. #endif
  772.   if (CursorExists)
  773.     CursorToggle ();
  774.   InUpdate = 0;
  775.   dumpqueue ();
  776.   XTmove_cursor (SavedY, SavedX);    /* XTmove_cursor invokes cursor toggle */
  777.   UNBLOCK_INPUT ();
  778. }
  779.  
  780. /* Used for expose region and expose copy events.  Have to get the text
  781.  * back into the newly blank areas.
  782.  */
  783.  
  784. dumprectangle (top, left, rows, cols)
  785.      register int top, left, rows, cols;
  786. {
  787.   register int index;
  788.   int localX, localY, localHL;
  789.   rows += top;
  790.   cols += left;
  791.   top /= fontinfo->height;
  792.   /* Get row and col containing up and */
  793.   /* left borders of exposed region -- */
  794.   /* round down here*/
  795.   left /= fontinfo->width;
  796.   rows += (fontinfo->height - 1);
  797.   cols += (fontinfo->width - 1);
  798.   rows /= fontinfo->height;
  799.   /* Get row and col containing bottom and */
  800.   /* right borders -- round up here */
  801.   rows -= top;
  802.   cols /= fontinfo->width;
  803.   cols -= left;
  804.   if (rows < 0) return;
  805.   if (cols < 0) return;
  806.   if (top > (screen_height - 1)) return;
  807.   if (left > (screen_width - 1)) return;
  808.   if ((VisibleX >= left) && (VisibleX < (left + cols)) &&
  809.       (VisibleY >= top) && (VisibleY < (top + rows)))
  810.     {
  811.       ClearCursor ();
  812.     }
  813.  
  814.   /* should perhaps be DesiredScreen */
  815.   /* but PhysScreen is guaranteed to contain*/
  816.   /* date which was good for every line on */
  817.   /* screen. For desired screen only for */
  818.   /* lines which are changing.  Emacs does */
  819.   /* not consider a line within a newly */
  820.   /* exposed region necessarily to have */
  821.   /* been changed.  Emacs knows nothing */
  822.   /* about ExposeRegion events.*/
  823.   for (localY = top, index = 0;
  824.        (index < rows) && (localY < screen_height);
  825.        ++index, ++localY)
  826.     {
  827.       if ((localY < 0) || (localY >= screen_height)) continue;
  828.       if (!current_screen->enable[localY]) continue;
  829.       if ((left + 1) > current_screen->used[localY]) continue;
  830.       localX = left;
  831.       localHL = current_screen->highlight[localY];
  832.       dumpchars (current_screen,
  833.          min (cols,
  834.               current_screen->used[localY]
  835.             - localX),
  836.          localX, localY, localHL);
  837.     }
  838.   if (!InUpdate && !CursorExists) CursorToggle ();
  839.   /* Routine usually called */
  840.   /* when not in update */
  841. }
  842.  
  843. /* What sections of the window will be modified from the UpdateDisplay
  844.  * routine is totally under software control.  Any line with Y coordinate
  845.  * greater than flexlines will not change during an update.  This is really
  846.  * used only during dellines and inslines routines (scraplines and stufflines)
  847.  */
  848. static
  849. XTset_terminal_window (n)
  850.      register int n;
  851. {
  852. #ifdef XDEBUG
  853.   fprintf (stderr, "XTset_terminal_window\n");
  854. #endif
  855.   if ((n <= 0) || (n > screen_height))
  856.     flexlines = screen_height;
  857.   else
  858.     flexlines = n;
  859. }
  860.  
  861. XTins_del_lines (vpos, n)
  862.      int vpos, n;
  863. {
  864. #ifdef XDEBUG
  865.   fprintf (stderr, "XTins_del_lines\n");
  866. #endif
  867.   XTmove_cursor (vpos, 0);
  868.   if (n >= 0) stufflines (n);
  869.   else scraplines (-n);
  870. }
  871.  
  872. static
  873. XTinsert_chars (start, len)
  874.      register char *start;
  875.      register int len;
  876. {
  877. #ifdef XDEBUG
  878.   fprintf (stderr, "XTinsert_chars\n");
  879. #endif
  880.   writechars (start, start + len - 1);
  881. }
  882.  
  883. static
  884. XTdelete_chars (n)
  885.      register int n;
  886. {
  887.   char *msg = "***Delete Chars Called Outside of Update!!!***";
  888. #ifdef XDEBUG
  889.   fprintf (stderr, "XTdelete_chars\n");
  890. #endif
  891.   writechars (msg, msg + strlen (msg) - 1);
  892. }
  893.  
  894. static
  895. stufflines (n)
  896.      register int n;
  897. {
  898.   register int topregion, bottomregion;
  899.   register int length, newtop;
  900.   BLOCK_INPUT_DECLARE ()
  901.  
  902.   if (cursor_vpos >= flexlines)
  903.     return;
  904.  
  905.   if (!WindowMapped)
  906.     {
  907.       bitblt = 0;
  908.       return;
  909.     }
  910.   BLOCK_INPUT ();
  911.   if (CursorExists) CursorToggle ();
  912.   dumpqueue ();
  913.   UNBLOCK_INPUT ();
  914.   topregion = cursor_vpos;
  915.   bottomregion = flexlines - (n + 1);
  916.   newtop = cursor_vpos + n;
  917.   length = (bottomregion - topregion) + 1;
  918.   if ((length > 0) && (newtop <= flexlines))
  919.     {
  920.       BLOCK_INPUT ();
  921.       /* Should already have cleared */
  922.       /* queue of events associated */
  923.       /* with old bitblts */
  924.       XMoveArea (XXwindow, XXInternalBorder,
  925.          topregion * fontinfo->height+XXInternalBorder,
  926.          XXInternalBorder, newtop * fontinfo->height+XXInternalBorder,
  927.          screen_width * fontinfo->width,
  928.          length * fontinfo->height);
  929.       if (WindowMapped)
  930.     bitblt = 1;
  931.       XFlush ();
  932.       UNBLOCK_INPUT ();
  933.       SIGNAL_INPUT_WHILE (bitblt);
  934.       XFlush ();
  935.     }
  936.   newtop = min (newtop, (flexlines - 1));
  937.   length = newtop - topregion;
  938.   if (length > 0)
  939.     {
  940.       XPixSet (XXwindow,
  941.            XXInternalBorder,
  942.            topregion * fontinfo->height+XXInternalBorder,
  943.            screen_width * fontinfo->width,
  944.            n * fontinfo->height,
  945.            back);
  946.     }
  947.   /*  if (!InUpdate) CursorToggle (); */
  948. }
  949.  
  950. static
  951. scraplines (n)
  952.      register int n;
  953. {
  954.   BLOCK_INPUT_DECLARE ()
  955.   if (!WindowMapped)
  956.     {
  957.       bitblt = 0;
  958.       return;
  959.     }
  960.  
  961.   if (cursor_vpos >= flexlines)
  962.     return;
  963.   BLOCK_INPUT ();
  964.   if (CursorExists) CursorToggle ();
  965.   dumpqueue ();
  966.   if ((cursor_vpos + n) >= flexlines)
  967.     {
  968.       if (flexlines >= (cursor_vpos + 1))
  969.     {
  970.       XPixSet (XXwindow,
  971.            XXInternalBorder, cursor_vpos * fontinfo->height+XXInternalBorder,
  972.            screen_width * fontinfo->width,
  973.            (flexlines - cursor_vpos) * fontinfo->height,
  974.            back);
  975.     }
  976.       UNBLOCK_INPUT ();
  977.     }
  978.   else
  979.     {
  980.       XMoveArea (XXwindow,
  981.          XXInternalBorder,
  982.          (cursor_vpos + n) * fontinfo->height+XXInternalBorder,
  983.          XXInternalBorder, cursor_vpos * fontinfo->height+XXInternalBorder,
  984.          screen_width * fontinfo->width,
  985.          (flexlines - (cursor_vpos + n)) * fontinfo->height);
  986.       if (WindowMapped)
  987.     bitblt = 1;
  988.       XFlush ();
  989.       UNBLOCK_INPUT ();
  990.       SIGNAL_INPUT_WHILE (bitblt);
  991.       BLOCK_INPUT ();
  992.       XFlush ();
  993.       XPixSet (XXwindow, XXInternalBorder,
  994.            (flexlines - n) * fontinfo->height+XXInternalBorder,
  995.            screen_width * fontinfo->width,
  996.            n * fontinfo->height, back);
  997.       UNBLOCK_INPUT ();
  998.     }
  999.   /* if (!InUpdate) CursorToggle (); */
  1000. }
  1001.  
  1002. /* Substitutes for standard read routine.  Under X not interested in individual
  1003.  * bytes but rather individual packets.
  1004.  */
  1005.  
  1006. XTread_socket (sd, bufp, numchars)
  1007.      register int sd;
  1008.      register char *bufp;
  1009.      register int numchars;
  1010. {
  1011.  
  1012.   int count;
  1013.   char *where_mapping;
  1014.   int nbytes;
  1015.   int stuffpending;
  1016.   int temp_width, temp_height;
  1017.   BLOCK_INPUT_DECLARE ()
  1018.   /* XKeyPressedEvent event; */
  1019.   /*  typedef struct reply {XEvent event; struct reply *next} Reply;
  1020.       Reply *replies = NULL;*/
  1021.  
  1022.   BLOCK_INPUT ();
  1023.   count = 0;
  1024.   if (numchars <= 0)
  1025.     {    /* To keep from overflowing read buffer */
  1026.       numchars = 1;
  1027.       --bufp;
  1028.     }
  1029. #ifdef SIGIO
  1030.   while (bitblt || XPending () != 0)
  1031. #else
  1032. #ifndef HAVE_SELECT
  1033.   if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
  1034.     {
  1035.       extern int read_alarm_should_throw;
  1036.       if (CursorExists)
  1037.     xfixscreen ();
  1038.       read_alarm_should_throw = 1;
  1039.       XPeekEvent (&XXEvent);
  1040.       read_alarm_should_throw = 0;
  1041.     }
  1042. #endif
  1043.   while (XPending () != 0)
  1044. #endif
  1045.     {
  1046.       /* while there are more events*/
  1047.       XNextEvent (&XXEvent);
  1048.       switch (XXEvent.type)
  1049.     {
  1050. /*    case X_Reply:
  1051.     {
  1052.     extern char *malloc ();
  1053.     Reply *reply = (Reply *) malloc (sizeof (Reply));
  1054.     reply->next = replies;
  1055.     reply->event = XXEvent;
  1056.     replies = reply;
  1057.     break;
  1058.     }*/
  1059.     default:
  1060.       break;
  1061.     case ExposeWindow:
  1062.       if (((XExposeEvent *)&XXEvent)->window == XXIconWindow)
  1063.         {
  1064.           PendingIconExposure = 1;
  1065.         }
  1066.       else
  1067.         PendingExposure = 1;/* No reason to repeat */
  1068.       /* this if several */
  1069.       /* ExposeWindow events */
  1070.       /* come in quick succes-*/
  1071.       /* ion */
  1072.       break;
  1073.     case ExposeRegion:
  1074.       if (PendingExposure)
  1075.         {    /* Don't bother with */
  1076.           /* region events when */
  1077.           /* full window event */
  1078.           /* is pending */
  1079.           break;
  1080.         }
  1081.       loadxrepbuffer (&XXEvent, &XXqueue);
  1082.       if (XXqueue.rindex == XXqueue.windex)
  1083.         {
  1084.           PendingExposure = 1;
  1085.         }
  1086.       if ((XXqueue.rindex > XXqueue.mindex) ||
  1087.           (XXqueue.windex > XXqueue.mindex) ||
  1088.         (XXqueue.rindex < 0) ||
  1089.           (XXqueue.windex < 0))
  1090.         {
  1091.           PendingExposure = 1;
  1092.         }
  1093.       break;
  1094.     case ExposeCopy:    /* For ExposeCopy sync */
  1095.       /* will block all outgoing */
  1096.       /* requests until this is */
  1097.       /* decremented */
  1098.       if (WindowMapped) bitblt = 0;
  1099.       break;
  1100.     case KeyPressed:
  1101.       /* bcopy (XXEvent, event, sizeof (XKeyPressedEvent)); */
  1102.       where_mapping = XLookupMapping (&XXEvent, &nbytes);
  1103.       /* Nasty fix for arrow keys */
  1104.       if (!nbytes && IsCursorKey (XXEvent.detail & 0xff))
  1105.         {
  1106.           switch (XXEvent.detail & 0xff)
  1107.         {
  1108.         case KC_CURSOR_LEFT:
  1109.           where_mapping = "\002";
  1110.           break;
  1111.         case KC_CURSOR_RIGHT:
  1112.           where_mapping = "\006";
  1113.           break;
  1114.         case KC_CURSOR_UP:
  1115.           where_mapping = "\020";
  1116.           break;
  1117.         case KC_CURSOR_DOWN:
  1118.           where_mapping = "\016";
  1119.           break;
  1120.         }
  1121.           nbytes = 1;
  1122.         }
  1123.       if (numchars - nbytes > 0)
  1124.         {
  1125.           bcopy (where_mapping, bufp, nbytes);
  1126.           bufp += nbytes;
  1127.           count += nbytes;
  1128.           numchars -= nbytes;
  1129.         }
  1130. /*      else
  1131.         {
  1132.           bcopy (where_mapping, bufp, numchars);
  1133.           bufp += numchars;
  1134.           count += numchars;
  1135.           numchars = 0;
  1136.           *(bufp-1) = *(where_mapping + nbytes - 1);
  1137.         }*/
  1138.       break;
  1139.     case ButtonPressed:
  1140.     case ButtonReleased:
  1141.       switch (spacecheck (Xxrepbuffer.mindex,
  1142.                   Xxrepbuffer.rindex,
  1143.                   Xxrepbuffer.windex, 0))
  1144.         {
  1145.         case 0:
  1146.           loadxrepbuffer (&XXEvent,
  1147.                   &Xxrepbuffer);
  1148.           if (informflag && (numchars > 1))
  1149.         {
  1150.           *bufp++ = (char) 'X' & 037; /* C-x */
  1151.           ++count;
  1152.           --numchars;
  1153.           *bufp++ = (char) 0;  /* C-@ */
  1154.           ++count;
  1155.           --numchars;
  1156.         }
  1157.           break;
  1158.         case -1:
  1159.           break;
  1160.         case -2:
  1161.         default:
  1162.           fixxrepbuffer ();
  1163.           break;
  1164.         }
  1165.       break;
  1166.     }
  1167.     }
  1168. /*  while (replies) {
  1169.     Reply *reply = replies;
  1170.     XPutBackEvent (&reply->event);
  1171.     replies = reply->next;
  1172.     free (reply);
  1173.     }*/
  1174.   if (count < 0)
  1175.     count = 0;
  1176. #ifdef HAVE_SELECT
  1177.   if (CursorExists
  1178. #ifdef O_NDELAY
  1179. #ifdef F_GETFL
  1180.       && (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
  1181. #endif
  1182. #endif
  1183.       )
  1184.     xfixscreen ();
  1185. #endif
  1186.   UNBLOCK_INPUT ();
  1187.   return count;
  1188. }
  1189.  
  1190. /* refresh bitmap kitchen sink icon */
  1191. refreshicon ()
  1192. {
  1193.   BLOCK_INPUT_DECLARE ()
  1194.  
  1195.   BLOCK_INPUT ();
  1196.   if (XXIconWindow)
  1197.     XBitmapBitsPut (XXIconWindow, 0,  0, sink_width, sink_height,
  1198.             sink_bits, BlackPixel, WhitePixel,
  1199.             XXIconMask, GXcopy, AllPlanes);
  1200.   XFlush ();
  1201.   UNBLOCK_INPUT ();
  1202. }
  1203.  
  1204. XBitmapIcon ()
  1205. {
  1206.   BLOCK_INPUT_DECLARE ()
  1207.  
  1208.   BLOCK_INPUT ();
  1209.   if (!IconWindow)
  1210.     {
  1211.       XSetIconWindow (XXwindow,XXIconWindow);
  1212.       XSelectInput (XXIconWindow, ExposeWindow);
  1213.       IconWindow = !IconWindow;
  1214.     }
  1215.   UNBLOCK_INPUT ();
  1216. }
  1217.  
  1218. XTextIcon ()
  1219. {
  1220.   BLOCK_INPUT_DECLARE ()
  1221.  
  1222.   BLOCK_INPUT ();
  1223.   if (IconWindow)
  1224.     {
  1225.       XClearIconWindow (XXwindow);
  1226.       XSelectInput (XXIconWindow, NoEvent);
  1227.       IconWindow = !IconWindow;
  1228.     }
  1229.   UNBLOCK_INPUT ();
  1230. }
  1231.  
  1232. /* Interpreting incoming keycodes. Should have table modifiable as needed
  1233.  * from elisp.
  1234.  */
  1235.  
  1236. /* Exit gracefully from gnuemacs, doing an autosave and giving a status.
  1237.  */
  1238.  
  1239. XExitGracefully (disp, event)
  1240.      Display *disp;
  1241.      XErrorEvent *event;
  1242. {
  1243.   XCleanUp ();
  1244.   exit (70);
  1245. }
  1246.  
  1247. x_io_error (disp)
  1248.      Display *disp;
  1249. {
  1250.   XCleanUp ();
  1251.   exit (71);
  1252. }
  1253.  
  1254. #if 0
  1255. /* This kludge overcomes the failure to handle EAGAIN and EINTR
  1256.    in a certain version of X for 386 running system V.  */
  1257.  
  1258. x_io_error (disp, a, b, c, nwrite)
  1259.      Display *disp;
  1260. {
  1261.   extern _XSend ();
  1262.   unsigned int pc = ((unsigned int *)&disp)[-1];
  1263.   if (pc - (unsigned int)&_XSend - 100 < 100
  1264.        && (errno == EAGAIN || errno == EINTR))
  1265.     {
  1266.       /* We were called by `writedata' erroneously.
  1267.      Modify a local variable which `writedata'
  1268.      will subtract from the number of bytes to be written.  */
  1269.       nwrite = 0;
  1270.       return;
  1271.     }
  1272.   abort ();
  1273. }
  1274. #endif
  1275.  
  1276. xfixscreen ()
  1277. {
  1278.   register int temp_width, temp_height;
  1279.   BLOCK_INPUT_DECLARE ()
  1280.   /* register int temp_x, temp_y; */
  1281.  
  1282.   BLOCK_INPUT ();
  1283.   dumpqueue ();
  1284.   /* Check that the connection is in fact open.  This works by doing a nop */
  1285.   /* (well, almost) write operation.  If there is an XIOerror or a */
  1286.   /* SIGPIPE, exit gracefully.  This fixes the loop-on-logout bug.*/
  1287.   /* XIOErrorHandler (XExitGracefully); */
  1288.   XPixFill (XXwindow, 0, 0, 1, 1, back, ClipModeClipped, GXnoop, AllPlanes);
  1289.   XFlush ();
  1290.   /* XIOErrorHandler (0); */
  1291.   if (PendingIconExposure)
  1292.     {
  1293.       refreshicon ();
  1294.       PendingIconExposure = 0;
  1295.     }
  1296.   if (PendingExposure)
  1297.     {
  1298.       PendingExposure = 0;
  1299.       ClearCursor ();
  1300.       XXqueue.rindex = 0;
  1301.       XXqueue.windex = 0;
  1302.       XQueryWindow (XXwindow, &windowinfo); /* Dangerous to do */
  1303.       /* writes here but */
  1304.       /* otherwise would */
  1305.       /* have to alter */
  1306.       /* gnu emacs display */
  1307.       /* routines to query */
  1308.       /* when screen garbaged */
  1309.       temp_width = (windowinfo.width - 2 * XXInternalBorder) / fontinfo->width;
  1310.       temp_height = (windowinfo.height- 2*XXInternalBorder) / fontinfo->height;
  1311.       if (temp_width != screen_width || temp_height != screen_height)
  1312.     change_screen_size (max (5, temp_height), max (10, temp_width),
  1313.                 0, 0, 0);
  1314.       XXxoffset= windowinfo.x;
  1315.       XXyoffset = windowinfo.y;
  1316.       /*if (temp_x != XXxoffset || temp_y != XXyoffset)
  1317.     XSetOffset (temp_x, temp_y);*/
  1318.       dumprectangle (0, 0,
  1319.              screen_height * fontinfo->height + 2 * XXInternalBorder,
  1320.              screen_width * fontinfo->width + 2 * XXInternalBorder);
  1321.     }
  1322.   if (!InUpdate)
  1323.     if (!CursorExists)
  1324.       CursorToggle ();
  1325.   XFlush ();
  1326.   UNBLOCK_INPUT ();
  1327.   SIGNAL_INPUT ();
  1328. }
  1329.  
  1330. x_term_init ()
  1331. {
  1332.   char *vardisplay;
  1333.   char *temp_font;
  1334.   register char *option;
  1335.   extern XTinterrupt_signal ();
  1336.   int reversevideo;
  1337.   Color cdef;
  1338.   char *progname;
  1339.  
  1340.   Fset (intern ("window-system-version"), make_number (10));
  1341.  
  1342.   vardisplay = (alternate_display ? alternate_display
  1343.         : (char *) egetenv ("DISPLAY"));
  1344.   if (!vardisplay || *vardisplay == '\0')
  1345.     {
  1346.       fprintf (stderr, "DISPLAY environment variable must be set\n");
  1347.       exit (-200);
  1348.     }
  1349.  
  1350.   XXdisplay = XOpenDisplay (vardisplay);
  1351.   if (XXdisplay == (Display *) 0)
  1352.     {
  1353.       fprintf (stderr, "X server not responding.  Check your DISPLAY environment variable.\n");
  1354.       exit (-200);
  1355.     }
  1356.   x_init_1 (1);
  1357.   Xxrepbuffer.mindex = XREPBUFSIZE - 1;
  1358.   Xxrepbuffer.windex = 0;
  1359.   Xxrepbuffer.rindex = 0;
  1360.   XXqueue.mindex = XREPBUFSIZE - 1;
  1361.   XXqueue.windex = 0;
  1362.   XXqueue.rindex = 0;
  1363.   WindowMapped = 0;
  1364.   baud_rate = 9600;
  1365.   min_padding_speed = 10000;
  1366.   must_write_spaces = 1;
  1367.   informflag = 1;
  1368.   meta_key = 1;
  1369.   visible_bell = 1;
  1370. #ifdef SIGIO
  1371.   interrupt_input = 1;
  1372. #endif
  1373.   inverse_video = 1;
  1374.   bitblt = 0;
  1375.   PendingExposure = 0;
  1376.  
  1377.   fix_screen_hook = xfixscreen;
  1378.   clear_screen_hook = XTclear_screen;
  1379.   clear_end_of_line_hook = XTclear_end_of_line;
  1380.   ins_del_lines_hook = XTins_del_lines;
  1381.   change_line_highlight_hook = XTchange_line_highlight;
  1382.   insert_chars_hook = XTinsert_chars;
  1383.   output_chars_hook = XToutput_chars;
  1384.   delete_chars_hook = XTdelete_chars;
  1385.   ring_bell_hook = XTfeep;
  1386.   reset_terminal_modes_hook = XTreset_terminal_modes;
  1387.   set_terminal_modes_hook = XTset_terminal_modes;
  1388.   update_begin_hook = XTupdate_begin;
  1389.   update_end_hook = XTupdate_end;
  1390.   set_terminal_window_hook = XTset_terminal_window;
  1391.   read_socket_hook = XTread_socket;
  1392.   move_cursor_hook = XTmove_cursor;
  1393.   /* raw_move_cursor_hook = XTraw_move_cursor;  */
  1394.   reassert_line_highlight_hook = XTreassert_line_highlight;
  1395.   scroll_region_ok = 1;        /* we'll scroll partial screens */
  1396.   char_ins_del_ok = 0;         /* just as fast to write the line */
  1397.   line_ins_del_ok = 1;         /* we'll just blt 'em */
  1398.   fast_clear_end_of_line = 1;  /* X does this well */
  1399.   memory_below_screen = 0;    /* we don't remember what scrolls
  1400.                    off the bottom */
  1401.   dont_calculate_costs = 1;
  1402.  
  1403.   /* New options section */
  1404.   IconWindow = 0;
  1405.   XXborder = 1;
  1406.   XXInternalBorder = 1;
  1407.   screen_width = 80;
  1408.   screen_height = 66;
  1409.   reversevideo = 0;
  1410.   XXxoffset = 0;
  1411.   XXyoffset = 0;
  1412.   XXdebug = 0;
  1413.  
  1414.   XErrorHandler (XExitGracefully);
  1415.   XIOErrorHandler (x_io_error);
  1416.  
  1417.   progname = "emacs";
  1418.   if (option = XGetDefault (progname,"ReverseVideo"))
  1419.     if (strcmp (option,"on") == 0) reversevideo = 1;
  1420.   if (option = XGetDefault (progname, "BitmapIcon"))
  1421.     if (strcmp (option, "on") == 0) IconWindow = 1;
  1422.  
  1423.   if (option = XGetDefault (progname,"BorderWidth"))
  1424.     XXborder = atoi (option);
  1425.   if (option = XGetDefault (progname,"InternalBorder"))
  1426.     XXInternalBorder = atoi (option);
  1427.  
  1428.   brdr_color = XGetDefault (progname,"Border");
  1429.   if (!brdr_color) brdr_color = XGetDefault (progname, "BorderColor");
  1430.   back_color = XGetDefault (progname,"Background");
  1431.   fore_color = XGetDefault (progname,"Foreground");
  1432.   mous_color = XGetDefault (progname,"Mouse");
  1433.   curs_color = XGetDefault (progname,"Cursor");
  1434.  
  1435.   temp_font  = XGetDefault (progname,"BodyFont");
  1436.   if (temp_font == 0) temp_font = X_DEFAULT_FONT;
  1437.   XXcurrentfont = (char *) xmalloc (strlen (temp_font) + 1);
  1438.   strcpy (XXcurrentfont, temp_font);
  1439.  
  1440.   /* If user has specified a special keymap for use with Emacs, use it. */
  1441.   {
  1442.     char *temp = XGetDefault (progname, "KeyMap");
  1443.     if (temp) XUseKeymap (temp);
  1444.   }
  1445.  
  1446.   if (DisplayCells () > 2)
  1447.     {
  1448.  
  1449.       if (fore_color && XParseColor (fore_color, &cdef) &&
  1450.       XGetHardwareColor (&cdef))
  1451.     fore = cdef.pixel;
  1452.       else
  1453.     {
  1454.       fore_color = "black";
  1455.       fore = BlackPixel;
  1456.     }
  1457.  
  1458.       if (back_color && XParseColor (back_color, &cdef) &&
  1459.       XGetHardwareColor (&cdef))
  1460.     back = cdef.pixel;
  1461.       else
  1462.     {
  1463.       back_color = "white";
  1464.       back = WhitePixel;
  1465.     }
  1466.  
  1467.       if (curs_color && XParseColor (curs_color, &cdef) &&
  1468.       XGetHardwareColor (&cdef))
  1469.     curs = cdef.pixel;
  1470.       else
  1471.     {
  1472.       curs_color = "black";
  1473.       curs = BlackPixel;
  1474.     }
  1475.  
  1476.       if (mous_color && XParseColor (mous_color, &cdef) &&
  1477.       XGetHardwareColor (&cdef))
  1478.     mous = cdef.pixel;
  1479.       else
  1480.     {
  1481.       mous_color = "black";
  1482.       mous = BlackPixel;
  1483.     }
  1484.  
  1485.       if (brdr_color && XParseColor (brdr_color, &cdef) &&
  1486.       XGetHardwareColor (&cdef))
  1487.     brdr = cdef.pixel;
  1488.       else
  1489.     {
  1490.       brdr_color = "black";
  1491.       brdr = BlackPixel;
  1492.     }
  1493.     }
  1494.   else
  1495.     {
  1496.       fore_color  = curs_color = mous_color = brdr_color = "black";
  1497.       fore = curs = mous = brdr = BlackPixel;
  1498.       back_color = "white";
  1499.       back = WhitePixel;
  1500.     }
  1501.  
  1502.   /*
  1503.   if (fore_color && DisplayCells () > 2 &&
  1504.       XParseColor (fore_color, &cdef) && XGetHardwareColor (&cdef))
  1505.     fore = cdef.pixel;
  1506.   else if (fore_color && strcmp (fore_color, "black") == 0)
  1507.     fore = BlackPixel;
  1508.   else if (fore_color && strcmp (fore_color, "white") == 0)
  1509.     fore = WhitePixel;
  1510.   else
  1511.     {
  1512.       fore_color = "black";
  1513.       fore = BlackPixel;
  1514.     }
  1515.  
  1516.   if (back_color && DisplayCells () > 2 &&
  1517.       XParseColor (back_color, &cdef) && XGetHardwareColor (&cdef))
  1518.     back = cdef.pixel;
  1519.   else if (back_color && strcmp (back_color, "white") == 0)
  1520.     back = WhitePixel;
  1521.   else if (back_color && strcmp (back_color, "black") == 0)
  1522.     back = BlackPixel;
  1523.   else
  1524.     {
  1525.       back_color = "white";
  1526.       back = WhitePixel;
  1527.     }
  1528.  
  1529.   if (brdr_color && DisplayCells () > 2 &&
  1530.       XParseColor (brdr_color, &cdef) && XGetHardwareColor (&cdef))
  1531.     brdr = cdef.pixel;
  1532.   else if (brdr_color && (!strcmp (brdr_color, "gray") ||
  1533.               !strcmp (brdr_color, "grey") ||
  1534.               !strcmp (brdr_color, "Gray") ||
  1535.               !strcmp (brdr_color, "Grey")))
  1536.     brdr = BlackPixel;
  1537.   else if (brdr_color && strcmp (brdr_color, "white") == 0)
  1538.     brdr = WhitePixel;
  1539.   else
  1540.     {
  1541.       brdr_color = "black";
  1542.       brdr = BlackPixel;
  1543.     }
  1544.  
  1545.   if (curs_color && DisplayCells () > 2 &&
  1546.       XParseColor (curs_color, &cdef) && XGetHardwareColor (&cdef))
  1547.     curs = cdef.pixel;
  1548.   else if (curs_color && strcmp (curs_color, "black") == 0)
  1549.     curs = BlackPixel;
  1550.   else if (curs_color && strcmp (curs_color, "white") == 0)
  1551.     curs = WhitePixel;
  1552.   else
  1553.     {
  1554.       curs_color = "black";
  1555.       curs = BlackPixel;
  1556.     }
  1557.  
  1558.   if (mous_color && DisplayCells () > 2 &&
  1559.       XParseColor (mous_color, &cdef) && XGetHardwareColor (&cdef))
  1560.     mous = cdef.pixel;
  1561.   else if (mous_color && strcmp (mous_color, "black") == 0)
  1562.     mous = BlackPixel;
  1563.   else if (mous_color && strcmp (mous_color, "white") == 0)
  1564.     mous = WhitePixel;
  1565.   else
  1566.     {
  1567.       mous_color = "black";
  1568.       mous = BlackPixel;
  1569.     }
  1570.     */
  1571.  
  1572.   XXpid = getpid ();
  1573.   if (XXcurrentfont == (char *) 0)
  1574.     {
  1575.       fprintf (stderr, "Memory allocation failure.\n");
  1576.       exit (-150);
  1577.     }
  1578.   default_window = "=80x24+0+0";
  1579. /* RMS: XTread_socket does not have an interface suitable
  1580.    for being a signal handler.  In any case, the SIGIO handler is
  1581.    set up in init_keyboard and X uses the same one as usual.  */
  1582. /*  signal (SIGIO, XTread_socket); */
  1583.   signal (SIGPIPE, XExitGracefully);
  1584.   XQueryWindow (RootWindow, &rootwindowinfo);
  1585.   strncpy (iconidentity, ICONTAG, MAXICID);
  1586.   fontinfo = XOpenFont (XXcurrentfont);
  1587.   if (fontinfo == (FontInfo *) 0)
  1588.     {
  1589.       fprintf (stderr, "No font\n");
  1590.       exit (-98);
  1591.     }
  1592.   pixelwidth = screen_width * fontinfo->width + 2 * XXInternalBorder;
  1593.   pixelheight = screen_height * fontinfo->height + 2 * XXInternalBorder;
  1594.   XXwindow = XCreateWindow (RootWindow,
  1595.                 XXxoffset /* Absolute horizontal offset */,
  1596.                 XXyoffset /* Absolute Vertical offset */,
  1597.                 pixelwidth, pixelheight,
  1598.                 XXborder, BlackPixmap, WhitePixmap);
  1599.   if (!XXwindow)
  1600.     {
  1601.       fprintf (stderr, "Unable to create window.\n");
  1602.       exit (-97);
  1603.     }
  1604.  
  1605.   XXIconWindow = XCreateWindow (RootWindow, 0, 0, sink_width, sink_height,
  1606.                 2, WhitePixmap, (Pixmap) NULL);
  1607.  
  1608.   if (!XXIconWindow)
  1609.     {
  1610.       fprintf (stderr, "Unable to create icon window.\n");
  1611.       fflush (stderr);
  1612.       exit (-97);
  1613.     }
  1614.   XSelectInput (XXIconWindow, NoEvent);
  1615.   XXIconMask = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
  1616.  
  1617.   XSelectInput (XXwindow, NoEvent);
  1618.   XSetResizeHint (XXwindow, 2 * XXInternalBorder, 2 * XXInternalBorder,
  1619.           /* fontinfo->width * 1, fontinfo->height * 1, */
  1620.           fontinfo->width, fontinfo->height);
  1621.  
  1622. #if defined (BSD) || defined (HPUX) || defined (IBMRTAIX)
  1623.   if (gethostname (&iconidentity[sizeof (ICONTAG) - 1],
  1624.            (MAXICID - 1) - sizeof (ICONTAG)))
  1625. #endif
  1626.     {
  1627.       iconidentity[sizeof (ICONTAG) - 2] = '\0';
  1628.     }
  1629.   XStoreName (XXwindow, &iconidentity[0]);
  1630.  
  1631.   EmacsCursor = XCreateCursor (16, 16, MouseCursor, MouseMask,
  1632.                    0, 0, mous, back, GXcopy);
  1633.   XDefineCursor (XXwindow, EmacsCursor);
  1634.   flexlines = screen_height;
  1635. #if 0
  1636. /* Do not call XPopUpWindow here!  This is too early.
  1637.    It is supposed ot be called via the term-setup-hook
  1638.    and not until after lisp/term/x-win.el has had a chance
  1639.    to process the user's switches.
  1640.    I am not sure that there are any circumstances under which
  1641.    this should be done here  -- RMS.  */
  1642.   XPopUpWindow ();        /* This looks at Vxterm */
  1643. #endif /* 0 */
  1644.   if (reversevideo) XFlipColor ();
  1645. }
  1646.  
  1647. x_init_1 (unrequest)
  1648. {
  1649. #ifdef F_SETOWN
  1650.   extern int old_fcntl_owner;
  1651. #endif
  1652. #ifndef USG
  1653.   extern void init_sigio (), request_sigio (), unrequest_sigio ();
  1654. #endif
  1655.  
  1656.   dup2 (dpyno (), 0);
  1657.   close (dpyno ());
  1658.   dpyno () = 0;            /* Looks a little strange?
  1659.                    check the def of the macro;
  1660.                    it is a genuine lvalue */
  1661. #ifndef USG
  1662.   init_sigio ();
  1663.   request_sigio ();
  1664. #endif /* USG */
  1665. #ifdef F_SETOWN
  1666.   old_fcntl_owner = fcntl (0, F_GETOWN, 0);
  1667. #ifdef F_SETOWN_SOCK_NEG
  1668.   fcntl (0, F_SETOWN, -getpid ());    /* stdin is a socket here */
  1669. #else
  1670.   fcntl (0, F_SETOWN, getpid ());
  1671. #endif /* F_SETOWN_SOCK_NEG */
  1672. #endif /* F_SETOWN */
  1673. #ifndef USG
  1674.   if (unrequest) unrequest_sigio ();
  1675. #endif
  1676. }
  1677.  
  1678. /* Process all queued ExposeRegion events. */
  1679. static
  1680. dumpqueue ()
  1681. {
  1682.   register int i;
  1683.   XExposeRegionEvent r;
  1684.   if ((XXqueue.rindex > XXqueue.mindex) ||
  1685.       (XXqueue.windex > XXqueue.mindex) ||
  1686.       (XXqueue.rindex < 0) ||
  1687.       (XXqueue.windex < 0))
  1688.     {
  1689.       PendingExposure = 1;
  1690.     }
  1691.   else
  1692.     while (XXqueue.rindex != XXqueue.windex)
  1693.       {
  1694.     if (CursorExists)
  1695.       CursorToggle ();
  1696.     unloadxrepbuffer (&r, &XXqueue);
  1697.     dumprectangle (r.y - XXInternalBorder, r.x - XXInternalBorder,
  1698.                r.height, r.width);
  1699.       }
  1700. }
  1701.  
  1702. XSetFlash ()
  1703. {
  1704.   ring_bell_hook = XTflash;
  1705. }
  1706.  
  1707. XSetFeep ()
  1708. {
  1709.   ring_bell_hook = XTfeep;
  1710. }
  1711.  
  1712. XNewFont (newname)
  1713.      register char *newname;
  1714. {
  1715.   FontInfo *temp;
  1716.   BLOCK_INPUT_DECLARE ()
  1717.  
  1718.   BLOCK_INPUT ();
  1719.   XFlush ();
  1720.   if (XXdebug)
  1721.     fprintf (stderr, "Request id is %d\n", XXdisplay->request);
  1722.   temp = XOpenFont (newname);
  1723.   if (temp == (FontInfo *) 0)
  1724.     {
  1725.       UNBLOCK_INPUT_RESIGNAL ();
  1726.       return -1;
  1727.     }
  1728.   XCloseFont (fontinfo);
  1729.   fontinfo = temp;
  1730.   XSetResizeHint (XXwindow, 2*XXInternalBorder, 2*XXInternalBorder,
  1731.           /* fontinfo->width * 1, fontinfo->height * 1, */
  1732.           fontinfo->width, fontinfo->height);
  1733.   XSetWindowSize (screen_height, screen_width);
  1734.   UNBLOCK_INPUT_RESIGNAL ();
  1735.   return 0;
  1736. }
  1737.  
  1738. XFlipColor ()
  1739. {
  1740.   Pixmap temp;
  1741.   int tempcolor;
  1742.   char *tempname;
  1743.   Cursor temp_curs;
  1744.   BLOCK_INPUT_DECLARE ()
  1745.  
  1746.   BLOCK_INPUT ();
  1747.   CursorToggle ();
  1748.   temp = XMakeTile (fore);
  1749.   XChangeBackground (XXwindow, temp);
  1750.   XFreePixmap (temp);
  1751.   temp = XMakeTile (back);
  1752.   if (XXborder)
  1753.     XChangeBorder (XXwindow, temp);
  1754.   XFreePixmap (temp);
  1755.   brdr = back;
  1756.   brdr_color = back_color;
  1757.   tempcolor = fore;
  1758.   fore = back;
  1759.   back = tempcolor;
  1760.   tempname = fore_color ;
  1761.   fore_color = back_color;
  1762.   back_color = tempname;
  1763. /*  XPixFill (XXwindow, 0, 0, screen_width * fontinfo->width,
  1764.         screen_height * fontinfo->height, back, ClipModeClipped,
  1765.         GXcopy, AllPlanes);
  1766.   dumprectangle (0, 0, screen_height * fontinfo->height + 2 * XXInternalBorder,
  1767.   screen_width * fontinfo -> width + 2 * XXInternalBorder);*/
  1768.   XRedrawDisplay ();
  1769.   if (curs == WhitePixel)
  1770.     {
  1771.       curs = BlackPixel;
  1772.       curs_color = "black";
  1773.     }
  1774.   else if (curs == BlackPixel)
  1775.     {
  1776.       curs = WhitePixel;
  1777.       curs_color = "white";
  1778.     }
  1779.   if (mous == WhitePixel)
  1780.     {
  1781.       mous = BlackPixel;
  1782.       mous_color = "black";
  1783.     }
  1784.   else if (mous == BlackPixel)
  1785.     {
  1786.       mous = WhitePixel;
  1787.       mous_color = "white";
  1788.     }
  1789.   temp_curs = XCreateCursor (16, 16, MouseCursor, MouseMask, 0, 0,
  1790.                  mous, back, GXcopy);
  1791.   XUndefineCursor (XXwindow);
  1792.   XDefineCursor (XXwindow, temp_curs);
  1793.   XFreeCursor (EmacsCursor);
  1794.   bcopy (&temp_curs, &EmacsCursor, sizeof (Cursor));
  1795.   CursorToggle ();
  1796.   XFlush ();
  1797.   UNBLOCK_INPUT ();
  1798. }
  1799.  
  1800. XSetOffset (xoff, yoff)
  1801.      register int xoff, yoff;
  1802. {
  1803.   BLOCK_INPUT_DECLARE ()
  1804.  
  1805.   BLOCK_INPUT ();
  1806.   if (xoff < 0)
  1807.     {
  1808.       XXxoffset = rootwindowinfo.width + (++xoff) - pixelwidth - 4;
  1809.     }
  1810.   else
  1811.     {
  1812.       XXxoffset = xoff;
  1813.     }
  1814.   if (yoff < 0)
  1815.     {
  1816.       XXyoffset
  1817.     = rootwindowinfo.height + (++yoff) - pixelheight - 4;
  1818.     }
  1819.   else
  1820.     {
  1821.       XXyoffset = yoff;
  1822.     }
  1823.   XMoveWindow (XXwindow, XXxoffset, XXyoffset);
  1824.   UNBLOCK_INPUT ();
  1825.   /* XWarpMouse (XXwindow, pixelwidth >> 1, pixelheight >> 1); */
  1826. }
  1827.  
  1828. XSetWindowSize (rows, cols)
  1829.      register int rows, cols;
  1830. {
  1831.   /* if (rows < 3) rows = 24;
  1832.      if (cols < 1) cols = 80; */
  1833.   pixelwidth = cols * fontinfo->width + 2 * XXInternalBorder;
  1834.   pixelheight = rows * fontinfo->height + 2 * XXInternalBorder;
  1835.   XChangeWindow (XXwindow, pixelwidth, pixelheight);
  1836.   XFlush ();
  1837.   change_screen_size (rows, cols, 0, 0, 0);
  1838.   PendingExposure = 0;
  1839. }
  1840.  
  1841. XPopUpWindow ()
  1842. {
  1843.   BLOCK_INPUT_DECLARE ()
  1844.   if (WindowMapped)
  1845.     return;
  1846.   BLOCK_INPUT ();
  1847.   if (!x_edges_specified)
  1848.     Fx_rubber_band ();
  1849.   bitblt = 0;
  1850.   CursorExists = 0;
  1851.   VisibleX = 0;
  1852.   VisibleY = 0;
  1853.   WindowMapped = 1;
  1854.   XMapWindow (XXwindow);
  1855.   dumprectangle (0, 0,
  1856.          screen_height * fontinfo->height + 2 * XXInternalBorder,
  1857.          screen_width * fontinfo->width + 2 * XXInternalBorder);
  1858.   XSelectInput (XXwindow, KeyPressed | ExposeWindow | ButtonPressed
  1859.         | ButtonReleased
  1860.         | ExposeRegion | ExposeCopy);
  1861.   /*    XWarpMouse (XXwindow, pixelwidth >> 1, pixelheight >> 1);*/
  1862.   XTmove_cursor (0, 0);
  1863.   if (IconWindow)
  1864.     {
  1865.       XSetIconWindow (XXwindow,XXIconWindow);
  1866.       XSelectInput (XXIconWindow, ExposeWindow);
  1867.     }
  1868.   else
  1869.     {
  1870.       XClearIconWindow (XXwindow);
  1871.       XSelectInput (XXIconWindow, NoEvent);
  1872.     }
  1873.   /*  XRedrawDisplay ();*/
  1874.   XFlush ();
  1875.   UNBLOCK_INPUT ();
  1876. }
  1877.  
  1878. spacecheck (mindex, rindex, windex, minfreespace)
  1879.      register int mindex, rindex, windex, minfreespace;
  1880. {
  1881.   if ((rindex > mindex) || (windex > mindex))
  1882.     {
  1883.       /* fprintf (stderr, "Fatal Mouse Buffer Error.\n");
  1884.      fprintf (stderr, "%d = mindex, %d = rindex, %d = windex\n",
  1885.      mindex, rindex, windex); */
  1886.       return -2;
  1887.     }
  1888.   if (windex >= rindex)
  1889.     {
  1890.       if ((mindex - (windex - rindex)) > minfreespace)
  1891.     return 0;
  1892.     }
  1893.   else
  1894.     {
  1895.       if (((rindex - windex) - 1) > minfreespace)
  1896.     return 0;
  1897.     }
  1898.   return -1;
  1899. }
  1900.  
  1901. loadxrepbuffer (p_xrep, p_buffer)
  1902.      register XEvent *p_xrep;
  1903.      register XREPBUFFER *p_buffer;
  1904. {
  1905.   p_buffer->xrep[p_buffer->windex] = *p_xrep;
  1906.   if (p_buffer->windex == p_buffer->mindex)
  1907.     p_buffer->windex = 0;
  1908.   else
  1909.     p_buffer->windex++;
  1910. }
  1911.  
  1912. unloadxrepbuffer (p_xrep, p_buffer)
  1913.      register XEvent *p_xrep;
  1914.      register XREPBUFFER *p_buffer;
  1915. {
  1916.   if (p_buffer->windex == p_buffer->rindex)
  1917.     return -1;
  1918.   *p_xrep = p_buffer->xrep[p_buffer->rindex];
  1919.   if (p_buffer->rindex == p_buffer->mindex)
  1920.     p_buffer->rindex = 0;
  1921.   else
  1922.     p_buffer->rindex++;
  1923.   return 0;
  1924. }
  1925.  
  1926. fixxrepbuffer ()
  1927. {
  1928.   Xxrepbuffer.mindex = XREPBUFSIZE - 1;
  1929.   Xxrepbuffer.windex = 0;
  1930.   Xxrepbuffer.rindex = 0;
  1931. }
  1932.  
  1933. #endif /* HAVE_X_WINDOWS */
  1934.