home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / e20313sr.zip / emacs / 20.3.1 / src / pmterm.c < prev    next >
C/C++ Source or Header  |  1999-07-31  |  48KB  |  1,788 lines

  1. /* pmterm.c -- xterm.c for the OS/2 Presentation Manager
  2.    Copyright (C) 1993-1996 Eberhard Mattes.
  3.    Copyright (C) 1995 Patrick Nadeau (scroll bar code).
  4.    Copyright (C) 1989-1995 Free Software Foundation, Inc. (code from xterm.c).
  5.  
  6. This file is part of GNU Emacs.
  7.  
  8. GNU Emacs is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2, or (at your option)
  11. any later version.
  12.  
  13. GNU Emacs is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with GNU Emacs; see the file COPYING.  If not, write to
  20. the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  21. Boston, MA 02111-1307, USA.  */
  22.  
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <fcntl.h>
  27. #include <signal.h>
  28. #include <errno.h>
  29. #include <sys/process.h>
  30. #include <sys/ioctl.h>
  31.  
  32. #include "config.h"
  33. #include "lisp.h"
  34. #include "blockinput.h"
  35. #include "keyboard.h"
  36. #include "window.h"
  37. #include "frame.h"
  38. #include "disptab.h"
  39. #include "termhooks.h"
  40. #include "termopts.h"
  41. #include "termchar.h"
  42. #include "dispextern.h"
  43. #include "pmterm.h"
  44. #include "pmemacs.h"
  45. #include "charset.h"
  46.  
  47.  
  48. pmd_config pm_config;
  49.  
  50. struct pm_queue
  51. {
  52.   struct pm_queue *next;
  53.   pm_event event;
  54. };
  55.  
  56. static struct pm_queue *pm_queue_first;
  57. static struct pm_queue **pm_queue_add = &pm_queue_first;
  58.  
  59. int pm_pid = -1;
  60.  
  61. /* The current serial number for requests which return an answer. */
  62. int pm_serial;
  63.  
  64. extern struct face *intern_face (struct frame *f, struct face *face);
  65.  
  66. void x_make_frame_visible (struct frame *f);
  67. static void dump_rectangle (FRAME_PTR f, int left, int top, int right,
  68.     int bottom);
  69. static Lisp_Object find_scroll_bar_window (FRAME_PTR f, unsigned id);
  70.  
  71.  
  72. /* The current code page, defined in emxdep.c. */
  73. extern int cur_code_page;
  74.  
  75. /* This is the quit character, which is defined in keyboard.c.  It is
  76.    used by the PM_set_terminal_modes function, which is assigned to
  77.    set_terminal_modes_hook. */
  78. extern int quit_char;
  79.  
  80. /* Dummy variable for simplifying changes to xfaces.c. */
  81. Display *x_current_display;
  82.  
  83. /* cf. x_display_list */
  84. struct x_display_info *pm_display;
  85.  
  86. int pm_session_started = 0;
  87.  
  88. int curs_x;
  89. int curs_y;
  90.  
  91. extern struct frame *updating_frame;
  92.  
  93. static int outbound_pipe;
  94.  
  95. static char pm_send_buffer[4096];
  96. static int pm_send_buffered = 0;
  97.  
  98. /* During an update, nonzero if chars output now should be highlighted.  */
  99. static int highlight;
  100.  
  101. /* During an update, maximum vpos for ins/del line operations to affect.  */
  102. static int flexlines;
  103.  
  104. /* The mouse is on this frame.  */
  105. static FRAME_PTR mouse_frame;
  106.  
  107. /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
  108.    pmemacs pipe. */
  109.  
  110. static SIGTYPE
  111. pm_sigpipe (int sig)
  112. {
  113.   shut_down_emacs (sig, 1, Qnil);
  114.   fatal ("pmemacs died.");
  115. }
  116.  
  117.  
  118. /* Send a message to pmemacs. */
  119.  
  120. void pm_send (const void *src, unsigned size)
  121. {
  122.     const char *s;
  123.     int n;
  124.  
  125.     if (pm_send_buffered > 0)     /* Important! */
  126.         pm_send_flush ();
  127.     s = src;
  128.     while (size != 0)
  129.     {
  130.         n = write (outbound_pipe, s, size);
  131.         if (n == -1 || n == 0)
  132.         {
  133.             shut_down_emacs (0, 1, Qnil);
  134.             fatal ("Cannot send message to PM Emacs.");
  135.         }
  136.         size -= n;
  137.         s += n;
  138.     }
  139. }
  140.  
  141.  
  142. /* When sending many small requests, it's better to use this function.
  143.    If we want to receive data from pmemacs we have to call
  144.    pm_send_flush() before waiting for the answer. */
  145.  
  146. void pm_send_collect (const void *src, unsigned size)
  147. {
  148.   if (pm_send_buffered + size > sizeof (pm_send_buffer))
  149.     {
  150.       pm_send_flush ();
  151.       if (size > sizeof (pm_send_buffer))
  152.         {
  153.           pm_send (src, size);
  154.           return;
  155.         }
  156.     }
  157.   memcpy (pm_send_buffer + pm_send_buffered, src, size);
  158.   pm_send_buffered += size;
  159. }
  160.  
  161.  
  162. /* Flush buffer filled by pm_send_collect. */
  163.  
  164. void pm_send_flush (void)
  165. {
  166.   int size;
  167.  
  168.   if (pm_send_buffered > 0)
  169.     {
  170.       size = pm_send_buffered;
  171.       pm_send_buffered = 0;
  172.       pm_send (pm_send_buffer, size);
  173.     }
  174. }
  175.  
  176.  
  177. /* Receive data from pmemacs. */
  178.  
  179. static int receive (void *dst, size_t size, int return_error)
  180. {
  181.   char *d;
  182.   int n;
  183.  
  184.   d = dst;
  185.   while (size != 0)
  186.     {
  187.       n = read (0, d, size);
  188.       if (n == -1 && errno == EINTR)
  189.         continue;
  190.       if (n == -1 || n == 0)
  191.         {
  192.           if (return_error)
  193.             return 0;
  194.           else
  195.             {
  196.               shut_down_emacs (0, 1, Qnil);
  197.               fatal ("Failed to receive data from PM Emacs.");
  198.             }
  199.         }
  200.       size -= n;
  201.       d += n;
  202.     }
  203.   return 1;
  204. }
  205.  
  206.  
  207. /* Put an event into the queue, for processing it later. */
  208.  
  209. static void pm_put_queue (pm_event *event)
  210. {
  211.   struct pm_queue *pmq;
  212.  
  213.   pmq = (struct pm_queue *)xmalloc (sizeof (struct pm_queue));
  214.   pmq->next = NULL;
  215.   pmq->event = *event;
  216.   *pm_queue_add = pmq;
  217.   pm_queue_add = &pmq->next;
  218.   interrupt_input_pending = 1;
  219. }
  220.  
  221.  
  222. /* Get an event from the queue. */
  223.  
  224. static void pm_get_queue (pm_event *event)
  225. {
  226.   struct pm_queue *next;
  227.  
  228.   *event = pm_queue_first->event;
  229.   next = pm_queue_first->next;
  230.   xfree (pm_queue_first);
  231.   pm_queue_first = next;
  232.   if (pm_queue_first == NULL)
  233.     pm_queue_add = &pm_queue_first;
  234.   else
  235.     interrupt_input_pending = 1;
  236. }
  237.  
  238.  
  239. /* Discard the data following an PME_ANSWER event. */
  240.  
  241. static void discard_answer (pm_event *p)
  242. {
  243.   char *tem;
  244.  
  245.   if (p->answer.size > 0)
  246.     {
  247.       tem = (char *)xmalloc (p->answer.size);
  248.       receive (tem, p->answer.size, 0);
  249.       xfree (tem);
  250.     }
  251. }
  252.  
  253.  
  254. /* Receive an answer from pmemacs.  SERIAL is the serial number of the
  255.    request.  Store the received data to DST.  If DST is NULL, use
  256.    malloc() to allocate a suitable buffer (this is not done when
  257.    receiving a single int).  Store the number of bytes received to
  258.    *SIZE, unless SIZE is NULL.  Process PME_PAINT events if MAY_PAINT
  259.    is true.  Return a pointer to the buffer (DST or allocated).
  260.    Return NULL on failure.
  261.  
  262.    The pm_send() call and the associated pm_receive() call must be
  263.    enclosed in BLOCK_INPUT and UNBLOCK_INPUT. */
  264.  
  265. void *pm_receive (int serial, void *dst, int *size, int may_paint)
  266. {
  267.   pm_event pme;
  268.   FRAME_PTR f;
  269.  
  270.   /* TODO: Check queue for PME_PAINT events if MAY_PAINT is true? */
  271.   for (;;)
  272.     {
  273.       receive (&pme, sizeof (pme), 0);
  274.       switch (pme.header.type)
  275.         {
  276.         case PME_ANSWER:
  277.           if (pme.answer.serial != serial)
  278.             {
  279.               printf ("pm_receive: serial number mismatch: %d vs. %d\r\n",
  280.                       pme.answer.serial, serial);
  281.               discard_answer (&pme);
  282.               if (size != NULL)
  283.                 *size = 0;
  284.               return (NULL);
  285.             }
  286.           if (pme.answer.size == -1)
  287.             {
  288.               /* DST must be non-NULL. */
  289.               *(int *)dst = pme.answer.one_word;
  290.               if (size != NULL)
  291.                 *size = sizeof (int);
  292.             }
  293.           else
  294.             {
  295.               if (dst == NULL)
  296.                 dst = xmalloc (pme.answer.size);
  297.               receive (dst, pme.answer.size, 0);
  298.               if (size != NULL)
  299.                 *size = pme.answer.size;
  300.             }
  301.           return (dst);
  302.  
  303.         case PME_PAINT:
  304.           if (may_paint)
  305.             {
  306.               f = (FRAME_PTR)pme.header.frame;
  307.               if (pm_active_frame (f))
  308.                 dump_rectangle (f, pme.paint.x0, pme.paint.y0,
  309.                                 pme.paint.x1, pme.paint.y1);
  310.             }
  311.           else
  312.             pm_put_queue (&pme);
  313.           break;
  314.  
  315.         default:
  316.  
  317.           /* Warning: pm_put_queue() calls xmalloc(), which may call
  318.              PM_read_socket(), which does not know how to handle
  319.              PME_ANSWER.  Therefore the caller of pm_receive() must
  320.              use BLOCK_INPUT! */
  321.  
  322.           pm_put_queue (&pme);
  323.           break;
  324.         }
  325.     }
  326. }
  327.  
  328. /* Keeping a table of active frames.  This is used to avoid acting on
  329.    events for frames already deleted.  After deleting a frame, there
  330.    may still be events for that frame in the queue (pipe 0). */
  331.  
  332. #define HASH_SIZE 53
  333. #define FRAME_HASH(f) ((unsigned long)f % HASH_SIZE)
  334.  
  335. struct hash_frame
  336. {
  337.   struct hash_frame *next;
  338.   FRAME_PTR frame;
  339. };
  340.  
  341. static struct hash_frame *frame_table[HASH_SIZE];
  342.  
  343. /* Before sending PMR_CREATE, this function should be called to enable
  344.    receiving events from the new frame F. */
  345.  
  346. void pm_add_frame (FRAME_PTR f)
  347. {
  348.   struct hash_frame *p;
  349.   int hash;
  350.  
  351.   hash = FRAME_HASH (f);
  352.   for (p = frame_table[hash]; p != 0; p = p->next)
  353.     if (p->frame == f)
  354.       abort ();
  355.   p = (struct hash_frame *) xmalloc (sizeof (*p));
  356.   p->frame = f;
  357.   p->next = frame_table[hash];
  358.   frame_table[hash] = p;
  359. }
  360.  
  361.  
  362. /* When deleting a frame, this function should be called to disable
  363.    receiving events from the frame F. */
  364.  
  365. void pm_del_frame (FRAME_PTR f)
  366. {
  367.   struct hash_frame **p, *q;
  368.  
  369.   for (p = &frame_table[FRAME_HASH (f)]; *p != 0; p = &(*p)->next)
  370.     if ((*p)->frame == f)
  371.       {
  372.         q = (*p)->next;
  373.         xfree (*p);
  374.         *p = q;
  375.         return;
  376.       }
  377.   abort ();
  378. }
  379.  
  380.  
  381. /* Check whether we are allowed to receive events for frame F. */
  382.  
  383. int pm_active_frame (FRAME_PTR f)
  384. {
  385.   struct hash_frame *p;
  386.  
  387.   for (p = frame_table[FRAME_HASH (f)]; p != 0; p = p->next)
  388.     if (p->frame == f)
  389.       return 1;
  390.   return 0;
  391. }
  392.  
  393.  
  394.  
  395. /* Turn mouse tracking on or off.  Tell pmemacs to start or stop
  396.    sending PME_MOUSEMOVE events. */
  397.  
  398. void pm_mouse_tracking (int flag)
  399. {
  400. #if 0
  401.   /* As Emacs 19.23 uses mouse movement events for highlighting
  402.    mouse-sensitive areas, mouse movement events are always enabled and
  403.    pm_mouse_tracking does nothing.  Perhaps later versions of Emacs
  404.    want to turn off mouse movement events, therefore we keep this
  405.    code. */
  406.  
  407.   pm_request pmr;
  408.  
  409.   pmr.track.header.type = PMR_TRACKMOUSE;
  410.   pmr.track.header.frame = 0;
  411.   pmr.track.flag = flag;
  412.   pm_send (&pmr, sizeof (pmr));
  413. #endif
  414. }
  415.  
  416.  
  417. /* Turn the cursor on or off. */
  418.  
  419. static void pm_display_cursor (struct frame *f, int on)
  420. {
  421.   pm_request pmr;
  422.  
  423.   if (!FRAME_VISIBLE_P (f))
  424.     return;
  425.   if (!on && f->phys_cursor_x < 0)
  426.     return;
  427.   if (f != updating_frame)
  428.     {
  429.       curs_x = FRAME_CURSOR_X (f);
  430.       curs_y = FRAME_CURSOR_Y (f);
  431.     }
  432.   if (on && (f->phys_cursor_x != curs_x || f->phys_cursor_y != curs_y))
  433.     {
  434.       pmr.cursor.header.type = PMR_CURSOR;
  435.       pmr.cursor.header.frame = (unsigned long)f;
  436.       pmr.cursor.x = curs_x;
  437.       pmr.cursor.y = curs_y;
  438.       pmr.cursor.on = 1;
  439.       pm_send (&pmr, sizeof (pmr));
  440.       f->phys_cursor_x = curs_x;
  441.       f->phys_cursor_y = curs_y;
  442.     }
  443.   if (!on)
  444.     {
  445.       pmr.cursor.header.type = PMR_CURSOR;
  446.       pmr.cursor.header.frame = (unsigned long)f;
  447.       pmr.cursor.x = 0;
  448.       pmr.cursor.y = 0;
  449.       pmr.cursor.on = 0;
  450.       pm_send (&pmr, sizeof (pmr));
  451.       f->phys_cursor_x = -1;
  452.     }
  453. }
  454.  
  455.  
  456. /* TODO: avoid PMR_CLREOL */
  457.  
  458. void dump_glyphs (struct frame *f, GLYPH *gp, int enable, int used,
  459.                   int x, int y, int cols, int hl)
  460. {
  461.     pm_request pmr, *pmrp;
  462.     int n, clear;
  463.     char *buf;
  464.     int tlen = GLYPH_TABLE_LENGTH;
  465.     Lisp_Object *tbase = GLYPH_TABLE_BASE;
  466.  
  467.     buf = alloca (sizeof (pmr) + cols);
  468.     pmrp = (pm_request *)buf;
  469.     buf += sizeof (pmr);
  470.     if (enable)
  471.     {
  472.         n = used - x;
  473.         if (n < 0) n = 0;
  474.     }
  475.     else
  476.         n = 0;
  477.     if (n > cols)
  478.         n = cols;
  479.     clear = cols - n;
  480.  
  481.     while (n > 0)
  482.     {
  483.         /* Get the face-code of the next GLYPH.  */
  484.         int cf, len;
  485.         int g = *gp;
  486.         char *cp;
  487.  
  488.         GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
  489.         cf = FAST_GLYPH_FACE (g);
  490.         /* Find the run of consecutive glyphs with the same face-code.
  491.            Extract their character codes into BUF.  */
  492.         cp = buf;
  493.         while (n > 0)
  494.         {
  495.             g = *gp;
  496.             GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
  497.             if (FAST_GLYPH_FACE (g) != cf)
  498.                 break;
  499.  
  500.             *cp++ = FAST_GLYPH_CHAR (g);
  501.             --n;
  502.             ++gp;
  503.         }
  504.  
  505.         /* LEN gets the length of the run.  */
  506.         len = cp - buf;
  507.  
  508.         /* Now output this run of chars, with the font and pixel values
  509.            determined by the face code CF.  */
  510.         {
  511.             struct face *face = FRAME_DEFAULT_FACE (f);
  512.  
  513.             /* HL = 3 means use a mouse face previously chosen.  */
  514.             if (hl == 3)
  515.                 cf = FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id;
  516.  
  517.             if (cf != 0)
  518.             {
  519.                 /* It's possible for the display table to specify
  520.                    a face code that is out of range.  Use 0 in that case.  */
  521.                 if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f))
  522.                     cf = 0;
  523.  
  524.                 if (cf == 1)
  525.                     face = FRAME_MODE_LINE_FACE (f);
  526.                 else
  527.                     face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
  528.             }
  529.             else if (hl == 1)
  530.             {
  531.                 face = FRAME_MODE_LINE_FACE (f);
  532.             }
  533.             pmrp->glyphs.header.type = PMR_GLYPHS;
  534.             pmrp->glyphs.header.frame = (unsigned long)f;
  535.             pmrp->glyphs.count = len;
  536.             pmrp->glyphs.x = x;
  537.             pmrp->glyphs.y = y;
  538.             pmrp->glyphs.face = face->gc;
  539.             pm_send_collect (pmrp, sizeof (pmr) + len);
  540.         }
  541.  
  542.         x += len;
  543.     }
  544.  
  545.     if (clear > 0)
  546.     {
  547.         pmr.clreol.header.type = PMR_CLREOL;
  548.         pmr.clreol.header.frame = (unsigned long)f;
  549.         pmr.clreol.y = y;
  550.         pmr.clreol.x0 = x;
  551.         pmr.clreol.x1 = x + clear; /* -1 ? */
  552.         pm_send_collect (&pmr, sizeof (pmr));
  553.     }
  554.     pm_send_flush ();
  555. }
  556.  
  557.  
  558. static void dump_rectangle (FRAME_PTR f, int left, int top,
  559.                             int right, int bottom)
  560. {
  561.   struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
  562.   int cols, rows, y, cursor_flag;
  563.  
  564.   if (FRAME_GARBAGED_P (f))
  565.     return;
  566.  
  567.   /* Clip the rectangle to what can be visible.  */
  568.   if (left < 0)
  569.     left = 0;
  570.   if (top < 0)
  571.     top = 0;
  572.   if (right >= f->width)
  573.     right = f->width - 1;
  574.   if (bottom >= f->height)
  575.     bottom = f->height - 1;
  576.  
  577.   /* Get size in chars of the rectangle.  */
  578.   cols = 1 + right - left;
  579.   rows = 1 + bottom - top;
  580.  
  581.   /* If rectangle has zero area, return.  */
  582.   if (rows <= 0) return;
  583.   if (cols <= 0) return;
  584.  
  585.   cursor_flag = (f->phys_cursor_x >= 0);
  586.   pm_display_cursor (f, 0);
  587.  
  588.   /* Display the text in the rectangle, one text line at a time.  */
  589.  
  590.   for (y = top; y <= bottom; y++)
  591.     dump_glyphs (f, &active_frame->glyphs[y][left],
  592.                  active_frame->enable[y], active_frame->used[y],
  593.                  left, y, cols, active_frame->highlight[y]);
  594.   if (cursor_flag)
  595.     pm_display_cursor (f, 1);
  596. }
  597.  
  598.  
  599. char *x_get_keysym_name (int keysym)
  600. {
  601.   return NULL;
  602. }
  603.  
  604.  
  605. /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
  606.    glyph co-ordinates in (*X, *Y).  Set *BOUNDS to the rectangle
  607.    that the glyph at X, Y occupies, if BOUNDS != 0.
  608.    If NOCLIP is nonzero, do not force the value into range.  */
  609.  
  610. void
  611. pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
  612.      FRAME_PTR f;
  613.      register int pix_x, pix_y;
  614.      register int *x, *y;
  615.      XRectangle *bounds;
  616.      int noclip;
  617. {
  618.   /*TODO*/
  619.   *x = pix_x;
  620.   *y = pix_y;
  621.   if (bounds)
  622.     {
  623.       bounds->x = pix_x;
  624.       bounds->y = pix_y;
  625.       bounds->width = 1;
  626.       bounds->height = 1;
  627.     }
  628. }
  629.  
  630. void
  631. glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
  632.      FRAME_PTR f;
  633.      register int x, y;
  634.      register int *pix_x, *pix_y;
  635. {
  636.   /*TODO*/
  637.   *pix_x = x;
  638.   *pix_y = y;
  639. }
  640.  
  641.  
  642. /* This function can be called at quite inconvenient times; therefore
  643.    it must not do anything which may result in a call to `message2' or
  644.    `update_frame'.  */
  645.  
  646. int PM_read_socket (int sd, struct input_event *bufp, int numchars,
  647.                     /* int waitp, */ int expected)
  648. {
  649.   int count = 0;
  650.   pm_event pme;
  651.   int nread;
  652.   FRAME_PTR f;
  653.  
  654.   if (interrupt_input_blocked)
  655.     {
  656.       interrupt_input_pending = 1;
  657.       return -1;
  658.     }
  659.   interrupt_input_pending = 0;
  660.   if (numchars <= 0)
  661.     abort ();
  662.  
  663.   if (pm_queue_first != NULL)
  664.     pm_get_queue (&pme);
  665.   else
  666.     {
  667.       if (ioctl (0, FIONREAD, &nread) < 0 || nread < sizeof (pme))
  668.         return 0;
  669.       receive (&pme, sizeof (pme), 0);
  670.     }
  671.   f = (FRAME_PTR)pme.header.frame;
  672.   if (!pm_active_frame (f) && pme.header.type != PME_ANSWER)
  673.     return 0;
  674.   switch (pme.header.type)
  675.     {
  676.     case PME_PAINT:
  677.  
  678.       /* A frame needs repainting. */
  679.  
  680.       dump_rectangle (f, pme.paint.x0, pme.paint.y0,
  681.                       pme.paint.x1, pme.paint.y1);
  682.       break;
  683.  
  684.     case PME_KEY:
  685.  
  686.       /* A key has been pressed. */
  687.  
  688.       switch (pme.key.type)
  689.         {
  690.         case PMK_ASCII:
  691.           bufp->kind = ascii_keystroke;
  692.           bufp->code = pme.key.code;
  693.           break;
  694.         case PMK_VIRTUAL:
  695.           bufp->kind = non_ascii_keystroke;
  696.           bufp->code = pme.key.code | (1 << 28);
  697.           break;
  698.         default:
  699.           abort ();
  700.         }
  701.       bufp->modifiers = pme.key.modifiers;
  702.       bufp->timestamp = 0;
  703.       XSETFRAME (bufp->frame_or_window, f);
  704.       ++count; ++bufp;
  705.       break;
  706.  
  707.     case PME_BUTTON:
  708.  
  709.       /* A mouse button has been pressed or released. */
  710.  
  711.       bufp->kind = mouse_click;
  712.       bufp->code = pme.button.button;
  713.       XSETFRAME (bufp->frame_or_window, f);
  714.       XSETFASTINT (bufp->x, pme.button.x);
  715.       XSETFASTINT (bufp->y, pme.button.y);
  716.       bufp->modifiers = pme.button.modifiers;
  717.       bufp->timestamp = pme.button.timestamp;
  718.       ++count; ++bufp;
  719.       break;
  720.  
  721.     case PME_SCROLLBAR:
  722.  
  723.       /* Some event has occured on the scroll bar. */
  724.  
  725.       bufp->kind = scroll_bar_click;
  726.       bufp->code = pme.scrollbar.button;
  727.       bufp->part = pme.scrollbar.part;
  728.       bufp->frame_or_window = find_scroll_bar_window (f, pme.scrollbar.id);
  729.       XSETFASTINT (bufp->x, pme.scrollbar.x);
  730.       XSETFASTINT (bufp->y, pme.scrollbar.y);
  731.       bufp->modifiers = pme.button.modifiers;
  732.       bufp->timestamp = pme.button.timestamp;
  733.       ++count; ++bufp;
  734.       break;
  735.  
  736.     case PME_SIZE:
  737.  
  738.       /* The size of the frame has been changed by the user.  Adjust
  739.          frame and set new size. */
  740.  
  741.       if (pme.size.width != FRAME_WIDTH (f)
  742.           || pme.size.height != FRAME_HEIGHT (f))
  743.         {
  744.           change_frame_size (f, pme.size.height, pme.size.width, 0, 1);
  745.           f->output_data.x->pixel_height = pme.size.pix_height;
  746.           f->output_data.x->pixel_width = pme.size.pix_width;
  747.           SET_FRAME_GARBAGED (f);
  748.         }
  749.       break;
  750.  
  751.     case PME_RESTORE:
  752.  
  753.       /* A frame window is being restored. */
  754.  
  755.       if (f->async_visible == 0)
  756.         {
  757.           f->async_visible = 1;
  758.           f->async_iconified = 0;
  759.           SET_FRAME_GARBAGED (f);
  760.         }
  761.       bufp->kind = deiconify_event;
  762.       XSETFRAME (bufp->frame_or_window, f);
  763.       bufp++; count++; numchars--;
  764.       break;
  765.  
  766.     case PME_MINIMIZE:
  767.  
  768.       /* A frame window is being minimized. */
  769.  
  770.       f->async_visible = 0;
  771.       f->async_iconified = 1;
  772.       bufp->kind = iconify_event;
  773.       XSETFRAME (bufp->frame_or_window, f);
  774.       bufp++; count++; numchars--;
  775.       break;
  776.  
  777.     case PME_WINDOWDELETE:
  778.  
  779.       /* Close a window. */
  780.  
  781.       bufp->kind = delete_window_event;
  782.       XSETFRAME (bufp->frame_or_window, f);
  783.       bufp++; count++; numchars--;
  784.       break;
  785.  
  786.     case PME_MENUBAR:
  787.  
  788.       /* An item of a submenu of the menu bar has been selected. */
  789.       pm_menubar_selection ((FRAME_PTR)pme.menubar.header.frame,
  790.                             pme.menubar.number);
  791.       break;
  792.  
  793.     case PME_MOUSEMOVE:
  794.  
  795.       /* The mouse has been moved. */
  796.  
  797.       mouse_frame = f;
  798.       f->output_data.x->mouse_x = pme.mouse.x;
  799.       f->output_data.x->mouse_y = pme.mouse.y;
  800.       f->mouse_moved = 1;
  801.       note_mouse_highlight (f, pme.mouse.x, pme.mouse.y);
  802.       break;
  803.  
  804.     case PME_FRAMEMOVE:
  805.  
  806.       /* A frame has been moved. */
  807.  
  808.       f->output_data.x->left_pos = pme.framemove.left;
  809.       f->output_data.x->top_pos = pme.framemove.top;
  810.       break;
  811.  
  812.     case PME_ANSWER:
  813.  
  814.       /* A synchronous answer.  Ignore it. */
  815.  
  816.       discard_answer (&pme);
  817.       break;
  818.  
  819.     default:
  820.       fatal ("Bad event type %d from PM Emacs.", pme.header.type);
  821.     }
  822.   return count;
  823. }
  824.  
  825.  
  826. static void PM_set_terminal_modes (void)
  827. {
  828.   pm_request pmr;
  829.  
  830.   pmr.quitchar.header.type = PMR_QUITCHAR;
  831.   pmr.quitchar.header.frame = 0;
  832.   pmr.quitchar.quitchar = quit_char;
  833.   pm_send (&pmr, sizeof (pmr));
  834. }
  835.  
  836.  
  837. static void PM_cursor_to (int row, int col)
  838. {
  839.   curs_x = col;
  840.   curs_y = row;
  841.   if (updating_frame == 0)
  842.     pm_display_cursor (selected_frame, 1);
  843. }
  844.  
  845.  
  846. static void PM_write_glyphs (GLYPH *start, int len)
  847. {
  848.   pm_request pmr;
  849.   struct frame *f;
  850.  
  851.   f = updating_frame;
  852.   if (f == 0)
  853.     {
  854.       f = selected_frame;
  855.       curs_x = f->cursor_x;
  856.       curs_y = f->cursor_y;
  857.     }
  858.   dump_glyphs (f, start, 1, curs_x + len, curs_x, curs_y, len, highlight);
  859.   if (updating_frame == 0)
  860.     {
  861.       f->cursor_x += len;
  862.       pm_display_cursor (f, 1);
  863.       f->cursor_x -= len;
  864.     }
  865.   else
  866.     curs_x += len;
  867. }
  868.  
  869.  
  870. static void PM_set_terminal_window (int n)
  871. {
  872.   if (updating_frame == 0)
  873.     abort ();
  874.   if (n <= 0 || n > updating_frame->height)
  875.     flexlines = updating_frame->height;
  876.   else
  877.     flexlines = n;
  878. }
  879.  
  880.  
  881. static void PM_ins_del_lines (int vpos, int n)
  882. {
  883.   pm_request pmr;
  884.  
  885.   if (updating_frame == 0)
  886.     abort ();
  887.   if (vpos >= flexlines)
  888.     return;
  889.   pmr.lines.header.type = PMR_LINES;
  890.   pmr.lines.header.frame = (unsigned long)updating_frame;
  891.   pmr.lines.y = vpos;
  892.   pmr.lines.max_y = flexlines;
  893.   pmr.lines.count = n;
  894.   pm_send (&pmr, sizeof (pmr));
  895. }
  896.  
  897.  
  898. static void PM_update_begin (FRAME_PTR f)
  899. {
  900.   if (f == 0)
  901.     abort ();
  902.   flexlines = f->height;
  903.   highlight = 0;
  904.   pm_display_cursor (f, 0);
  905.  
  906.   /* Borrowed from xterm.c. */
  907.  
  908.   if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
  909.     {
  910.       /* Don't do highlighting for mouse motion during the update.  */
  911.       FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 1;
  912.  
  913.       /* If the frame needs to be redrawn,
  914.      simply forget about any prior mouse highlighting.  */
  915.       if (FRAME_GARBAGED_P (f))
  916.     FRAME_X_DISPLAY_INFO (f)->mouse_face_window = Qnil;
  917.  
  918.       if (!NILP (FRAME_X_DISPLAY_INFO (f)->mouse_face_window))
  919.     {
  920.       int firstline, lastline, i;
  921.       struct window *w = XWINDOW (FRAME_X_DISPLAY_INFO (f)->mouse_face_window);
  922.  
  923.       /* Find the first, and the last+1, lines affected by redisplay.  */
  924.       for (firstline = 0; firstline < f->height; firstline++)
  925.         if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
  926.           break;
  927.  
  928.       lastline = f->height;
  929.       for (i = f->height - 1; i >= 0; i--)
  930.         {
  931.           if (FRAME_DESIRED_GLYPHS (f)->enable[i])
  932.         break;
  933.           else
  934.         lastline = i;
  935.         }
  936.  
  937.       /* Can we tell that this update does not affect the window
  938.          where the mouse highlight is?  If so, no need to turn off.
  939.          Likewise, don't do anything if the frame is garbaged;
  940.          in that case, the FRAME_CURRENT_GLYPHS that we would use
  941.          are all wrong, and we will redisplay that line anyway.  */
  942.       if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
  943.          || lastline < XFASTINT (w->top)))
  944.         clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
  945.     }
  946.     }
  947. }
  948.  
  949.  
  950. static void PM_update_end (struct frame *f)
  951. {
  952.   pm_display_cursor (f, 1);
  953.   if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
  954.     FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
  955.   updating_frame = 0;
  956. }
  957.  
  958.  
  959. static void PM_clear_frame ()
  960. {
  961.   pm_request pmr;
  962.   struct frame *f;
  963.  
  964.   f = updating_frame;
  965.   if (f == 0)
  966.     f = selected_frame;
  967.   f->phys_cursor_x = -1;
  968.   curs_x = 0;
  969.   curs_y = 0;
  970.   pmr.header.type = PMR_CLEAR;
  971.   pmr.header.frame = (unsigned long)f;
  972.   pm_send (&pmr, sizeof (pmr));
  973. }
  974.  
  975. static void PM_clear_end_of_line (int first_unused)
  976. {
  977.   pm_request pmr;
  978.   struct frame *f = updating_frame;
  979.  
  980.   if (f == 0)
  981.     abort ();
  982.  
  983.   if (curs_y < 0 || curs_y >= f->height)
  984.     return;
  985.   if (first_unused <= 0)
  986.     return;
  987.   if (first_unused >= f->width)
  988.     first_unused = f->width;
  989.  
  990.   pmr.clreol.header.type = PMR_CLREOL;
  991.   pmr.clreol.header.frame = (unsigned long)f;
  992.   pmr.clreol.y = curs_y;
  993.   pmr.clreol.x0 = curs_x;
  994.   pmr.clreol.x1 = first_unused;
  995.   pm_send (&pmr, sizeof (pmr));
  996. }
  997.  
  998.  
  999. /* This is called after a redisplay on frame F.  */
  1000.  
  1001. static void 
  1002. PM_frame_up_to_date (FRAME_PTR f)
  1003. {
  1004.   if (FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc
  1005.       || f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
  1006.     {
  1007.       note_mouse_highlight (FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame,
  1008.                 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x,
  1009.                 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y);
  1010.       FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
  1011.     }
  1012. }
  1013.  
  1014.  
  1015. static void PM_reassert_line_highlight (int new, int vpos)
  1016. {
  1017.   highlight = new;
  1018. }
  1019.  
  1020.  
  1021. static void PM_change_line_highlight (int new_highlight, int vpos,
  1022.                                  int first_unused_hpos)
  1023. {
  1024.   highlight = new_highlight;
  1025.   PM_cursor_to (vpos, 0);
  1026.   PM_clear_end_of_line (updating_frame->width);
  1027. }
  1028.  
  1029.  
  1030. /* Let pmemacs ring the bell. */
  1031.  
  1032. void PM_ring_bell ()
  1033. {
  1034.   pm_request pmr;
  1035.  
  1036.   pmr.bell.header.type = PMR_BELL;
  1037.   pmr.bell.header.frame = (unsigned long)selected_frame;
  1038.   pmr.bell.visible = visible_bell;
  1039.   pm_send (&pmr, sizeof (pmr));
  1040. }
  1041.  
  1042.  
  1043. /* Return the current mouse position. */
  1044.  
  1045. static void PM_mouse_position (FRAME_PTR *f, int insist,
  1046.                                Lisp_Object *bar_window,
  1047.                                enum scroll_bar_part *part,
  1048.                                Lisp_Object *x, Lisp_Object *y,
  1049.                                unsigned long *time)
  1050. {
  1051.   Lisp_Object tail, frame;
  1052.  
  1053.   if (mouse_frame && mouse_frame->mouse_moved)
  1054.     {
  1055.       *f = mouse_frame;
  1056.       XSETINT (*x, mouse_frame->output_data.x->mouse_x);
  1057.       XSETINT (*y, mouse_frame->output_data.x->mouse_y);
  1058.       *bar_window = Qnil;
  1059.       *time = 0;
  1060.     }
  1061.   else
  1062.     {
  1063.       /* Probably we don't need this -- is PM_mouse_position ever
  1064.          called when mouse_moved is zero? */
  1065.       pmd_mousepos result;
  1066.       pm_request pmr;
  1067.       void *buf;
  1068.  
  1069.       BLOCK_INPUT;
  1070.       pmr.mousepos.header.type = PMR_MOUSEPOS;
  1071.       pmr.mousepos.header.frame = -1;
  1072.       pmr.mousepos.serial = pm_serial++;
  1073.       pm_send (&pmr, sizeof (pmr));
  1074.       buf = pm_receive (pmr.mousepos.serial, &result, NULL, 0);
  1075.       UNBLOCK_INPUT;
  1076.       if (buf != NULL && result.frame != 0)
  1077.         {
  1078.           *f = (FRAME_PTR)result.frame;
  1079.           XSETINT (*x, result.x);
  1080.           XSETINT (*y, result.y);
  1081.           *bar_window = Qnil;
  1082.           *time = 0;
  1083.         }
  1084.     }
  1085.   FOR_EACH_FRAME (tail, frame)
  1086.     XFRAME (frame)->mouse_moved = 0;
  1087.   mouse_frame = 0;
  1088. }
  1089.  
  1090.  
  1091. static Lisp_Object find_scroll_bar_window (FRAME_PTR f, unsigned id)
  1092. {
  1093.   Lisp_Object bar;
  1094.  
  1095.   for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = XSCROLL_BAR (bar)->next)
  1096.     if (XSCROLL_BAR (bar)->id == id)
  1097.       return XSCROLL_BAR (bar)->window;
  1098.   for (bar = FRAME_CONDEMNED_SCROLL_BARS (f); !NILP (bar);
  1099.        bar = XSCROLL_BAR (bar)->next)
  1100.     if (XSCROLL_BAR (bar)->id == id)
  1101.       return XSCROLL_BAR (bar)->window;
  1102.   return Qnil;
  1103. }
  1104.  
  1105.  
  1106. /* Scale scrollbar values to a range accepted by the PM (0 through
  1107.    32767).  Return 1 if changed.  */
  1108.  
  1109. static int pm_scroll_bar_scale (slider *s, struct scroll_bar *bar,
  1110.                                 int portion, int whole, int position)
  1111. {
  1112.   int scaled_portion, scaled_whole, scaled_position;
  1113.   double scale;
  1114.  
  1115.   if (XINT (bar->portion) == portion && XINT (bar->whole) == whole
  1116.       && XINT (bar->position) == position)
  1117.     {
  1118.       s->portion = s->whole = s->position = -1;
  1119.       return 0;
  1120.     }
  1121.  
  1122.   XSETINT (bar->portion, portion);
  1123.   XSETINT (bar->whole, whole);
  1124.   XSETINT (bar->position, position);
  1125.  
  1126.   if (whole == 0)
  1127.     scaled_portion = scaled_whole = scaled_position = 0;
  1128.   else
  1129.     {
  1130.       scale = 32767.0 / whole;
  1131.       scaled_portion = (long)(scale * portion + 0.001);
  1132.       scaled_whole = 32767;
  1133.       scaled_position = (long)(scale * position + 0.001);
  1134.  
  1135.       /* Attempt to work around a bug in the PM: If `scaled_portion'
  1136.          is close to `scaled_portion', the slider becomes one pixel
  1137.          high.  The constant (35 below) depends on `scaled_whole'. */
  1138.  
  1139.       if (scaled_portion > scaled_whole - 35 && scaled_portion < scaled_whole)
  1140.         scaled_portion = scaled_whole - 35;
  1141.     }
  1142.  
  1143.   if (XINT (bar->scaled_portion) == scaled_portion
  1144.       && XINT (bar->scaled_whole) == scaled_whole
  1145.       && XINT (bar->scaled_position) == scaled_position)
  1146.     {
  1147.       s->portion = s->whole = s->position = -1;
  1148.       return 0;
  1149.     }
  1150.  
  1151.   XSETINT (bar->scaled_portion, scaled_portion);
  1152.   XSETINT (bar->scaled_whole, scaled_whole);
  1153.   XSETINT (bar->scaled_position, scaled_position);
  1154.  
  1155.   s->portion = scaled_portion;
  1156.   s->whole = scaled_whole;
  1157.   s->position = scaled_position;
  1158.   return 1;
  1159. }
  1160.  
  1161.  
  1162. /* Ask pmemacs to create a new scroll bar and return the scroll bar
  1163.    vector for it.  Originally written by Patrick Nadeau, modified by
  1164.    Eberhard Mattes.  */
  1165.  
  1166. static struct scroll_bar *
  1167. pm_scroll_bar_create (struct window *w, int portion, int whole, int position,
  1168.                       int top, int left, int width, int height)
  1169. {
  1170.   FRAME_PTR f;
  1171.   struct scroll_bar *bar;
  1172.   pm_request pmr;
  1173.   pm_create_scrollbar more;
  1174.   pmd_create_scrollbar answer;
  1175.   unsigned sb_id;
  1176.  
  1177.   if (!w) abort();
  1178.   f = XFRAME (WINDOW_FRAME (w));
  1179.   if (!f) abort();
  1180.  
  1181.   bar = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
  1182.  
  1183.   /* Initialize cached values.  */
  1184.  
  1185.   XSETINT (bar->top, top);
  1186.   XSETINT (bar->left, left);
  1187.   XSETINT (bar->width, width);
  1188.   XSETINT (bar->height, height);
  1189.   XSETINT (bar->whole, -1);
  1190.   XSETINT (bar->portion, -1);
  1191.   XSETINT (bar->position, -1);
  1192.   XSETINT (bar->scaled_whole, -1);
  1193.   XSETINT (bar->scaled_portion, -1);
  1194.   XSETINT (bar->scaled_position, -1);
  1195.  
  1196.   pm_scroll_bar_scale (&more.s, bar, portion, whole, position);
  1197.  
  1198.   more.top = top;
  1199.   more.left = left;
  1200.   more.width = width;
  1201.   more.height = height;
  1202.   more.serial = pm_serial++;
  1203.  
  1204.   BLOCK_INPUT;
  1205.   pmr.header.type = PMR_CREATE_SCROLLBAR;
  1206.   pmr.header.frame = (unsigned)f;
  1207.   pm_send_collect (&pmr, sizeof (pmr));
  1208.   pm_send_collect (&more, sizeof (more));
  1209.   pm_send_flush ();
  1210.   if (pm_receive (more.serial, &answer, NULL, 0) != NULL)
  1211.     sb_id = answer.id;
  1212.   else
  1213.     sb_id = SB_INVALID_ID;
  1214.   UNBLOCK_INPUT;
  1215.  
  1216.   if (sb_id != SB_INVALID_ID)
  1217.     {
  1218.       XSETINT (bar->id, sb_id);
  1219.       XSETWINDOW (bar->window, w);
  1220.  
  1221.       /* Add scroll bar to its frame's list of scroll bars.  */
  1222.  
  1223.       bar->next = FRAME_SCROLL_BARS (f);
  1224.       bar->prev = Qnil;
  1225.  
  1226.       XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
  1227.       if (!NILP (bar->next))
  1228.     XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
  1229.     }
  1230.   else
  1231.     {
  1232.       fprintf (stderr, "Could not create the scroll bar\n");
  1233.       abort();
  1234.     }
  1235.   return bar;
  1236. }
  1237.  
  1238.  
  1239. /* Destroy the PM window for BAR, and set its Emacs window's scroll
  1240.    bar to nil.  Originally written by Patrick Nadeau, modified by
  1241.    Eberhard Mattes.  */
  1242.  
  1243. static void pm_scroll_bar_close (struct scroll_bar *bar)
  1244. {
  1245.   pm_request pmr;
  1246.   FRAME_PTR f;
  1247.  
  1248.   f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
  1249.   pmr.destroy_scrollbar.header.type = PMR_DESTROY_SCROLLBAR;
  1250.   pmr.destroy_scrollbar.header.frame = (unsigned)f;
  1251.   pmr.destroy_scrollbar.id = XINT (bar->id);
  1252.   pm_send (&pmr, sizeof (pmr));
  1253.  
  1254.   /* Disassociate this scroll bar from its window.  */
  1255.  
  1256.   XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
  1257. }
  1258.  
  1259.  
  1260. /* Refresh scrollbar.  Originally written by Patrick Nadeau, modified
  1261.    by Eberhard Mattes.  */
  1262.  
  1263. pm_scroll_bar_move (struct scroll_bar *bar, int portion, int whole,
  1264.                     int position, int top, int left, int width, int height)
  1265. {
  1266.   pm_request pmr;
  1267.   FRAME_PTR f;
  1268.  
  1269.   f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
  1270.  
  1271.   if (XINT (bar->top) != top || XINT (bar->left) != left
  1272.       || XINT (bar->width) != width || XINT (bar->height) != height)
  1273.     {
  1274.       pmr.move_scrollbar.header.type = PMR_MOVE_SCROLLBAR;
  1275.       pmr.move_scrollbar.header.frame = (unsigned)f;
  1276.       pmr.move_scrollbar.id = XINT (bar->id);
  1277.       pmr.move_scrollbar.top = top;
  1278.       pmr.move_scrollbar.left = left;
  1279.       pmr.move_scrollbar.width = width;
  1280.       pmr.move_scrollbar.height = height;
  1281.       pm_send_collect (&pmr, sizeof (pmr));
  1282.       XSETINT (bar->top, top);
  1283.       XSETINT (bar->left, left);
  1284.       XSETINT (bar->width, width);
  1285.       XSETINT (bar->height, height);
  1286.     }
  1287.   if (pm_scroll_bar_scale (&pmr.update_scrollbar.s, bar,
  1288.                            portion, whole, position))
  1289.     {
  1290.       pmr.update_scrollbar.header.type = PMR_UPDATE_SCROLLBAR;
  1291.       pmr.update_scrollbar.header.frame = (unsigned)f;
  1292.       pmr.update_scrollbar.id = XINT (bar->id);
  1293.       pm_send_collect (&pmr, sizeof (pmr));
  1294.     }
  1295.   pm_send_flush ();
  1296. }
  1297.  
  1298.  
  1299. /* Set the vertical scroll bar for WINDOW to have its upper left
  1300.    corner at (TOP, LEFT), and be LENGTH rows high.  Set its handle to
  1301.    indicate that we are displaying PORTION characters out of a total
  1302.    of WHOLE characters, starting at POSITION.  If WINDOW doesn't yet
  1303.    have a scroll bar, create one for it.  Originally written by
  1304.    Patrick Nadeau, modified by Eberhard Mattes.  */
  1305.  
  1306. static void PM_set_vertical_scroll_bar (struct window *w, int portion,
  1307.                                         int whole, int position)
  1308. {
  1309.   FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
  1310.   int top = XINT (w->top);
  1311.   int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (w);
  1312.   int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (w);
  1313.   int width = FRAME_SCROLL_BAR_COLS (f);
  1314.   struct scroll_bar *bar;
  1315.  
  1316.   /* Does the scroll bar exist yet?  */
  1317.  
  1318.   if (NILP (w->vertical_scroll_bar))
  1319.     {
  1320.       bar = pm_scroll_bar_create (w, portion, whole, position,
  1321.                                   top, left, width, height);
  1322.       XSETVECTOR (w->vertical_scroll_bar, bar);
  1323.     }
  1324.   else
  1325.     {
  1326.       /* It may just need to be moved and resized.  */
  1327.  
  1328.       bar = XSCROLL_BAR (w->vertical_scroll_bar);
  1329.       pm_scroll_bar_move (bar, portion, whole, position,
  1330.                           top, left, width, height);
  1331.     }
  1332. }
  1333.  
  1334.  
  1335. /* [Code and comments borrowed from xterm.c] */
  1336.  
  1337. /* The following three hooks are used when we're doing a thorough
  1338.    redisplay of the frame.  We don't explicitly know which scroll bars
  1339.    are going to be deleted, because keeping track of when windows go
  1340.    away is a real pain - "Can you say set-window-configuration, boys
  1341.    and girls?"  Instead, we just assert at the beginning of redisplay
  1342.    that *all* scroll bars are to be removed, and then save a scroll bar
  1343.    from the fiery pit when we actually redisplay its window.  */
  1344.  
  1345. /* Arrange for all scroll bars on FRAME to be removed at the next call
  1346.    to `*judge_scroll_bars_hook'.  A scroll bar may be spared if
  1347.    `*redeem_scroll_bar_hook' is applied to its window before the judgement.  */
  1348.  
  1349. static void PM_condemn_scroll_bars (FRAME_PTR frame)
  1350. {
  1351.   /* The condemned list should be empty at this point; if it's not,
  1352.      then the rest of Emacs isn't using the condemn/redeem/judge
  1353.      protocol correctly.  */
  1354.  
  1355.   if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
  1356.     abort ();
  1357.  
  1358.   /* Move them all to the "condemned" list.  */
  1359.   FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
  1360.   FRAME_SCROLL_BARS (frame) = Qnil;
  1361. }
  1362.  
  1363.  
  1364. /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
  1365.    Note that WINDOW isn't necessarily condemned at all.  */
  1366.  
  1367. static void PM_redeem_scroll_bar (struct window *window)
  1368. {
  1369.   struct scroll_bar *bar;
  1370.  
  1371.   /* We can't redeem this window's scroll bar if it doesn't have one.  */
  1372.   if (NILP (window->vertical_scroll_bar))
  1373.     abort ();
  1374.  
  1375.   bar = XSCROLL_BAR (window->vertical_scroll_bar);
  1376.  
  1377.   /* Unlink it from the condemned list.  */
  1378.   {
  1379.     FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
  1380.  
  1381.     if (NILP (bar->prev))
  1382.       {
  1383.     /* If the prev pointer is nil, it must be the first in one of
  1384.            the lists.  */
  1385.     if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
  1386.       /* It's not condemned.  Everything's fine.  */
  1387.       return;
  1388.     else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
  1389.              window->vertical_scroll_bar))
  1390.       FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
  1391.     else
  1392.       /* If its prev pointer is nil, it must be at the front of
  1393.              one or the other!  */
  1394.       abort ();
  1395.       }
  1396.     else
  1397.       XSCROLL_BAR (bar->prev)->next = bar->next;
  1398.  
  1399.     if (! NILP (bar->next))
  1400.       XSCROLL_BAR (bar->next)->prev = bar->prev;
  1401.  
  1402.     bar->next = FRAME_SCROLL_BARS (f);
  1403.     bar->prev = Qnil;
  1404.     XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
  1405.     if (! NILP (bar->next))
  1406.       XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
  1407.   }
  1408. }
  1409.  
  1410. /* Remove all scroll bars on FRAME that haven't been saved since the
  1411.    last call to `*condemn_scroll_bars_hook'.  */
  1412.  
  1413. static void PM_judge_scroll_bars (FRAME_PTR f)
  1414. {
  1415.   Lisp_Object bar, next;
  1416.  
  1417.   bar = FRAME_CONDEMNED_SCROLL_BARS (f);
  1418.  
  1419.   /* Clear out the condemned list now so we won't try to process any
  1420.      more events on the hapless scroll bars.  */
  1421.   FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
  1422.  
  1423.   for (; ! NILP (bar); bar = next)
  1424.     {
  1425.       struct scroll_bar *b = XSCROLL_BAR (bar);
  1426.  
  1427.       pm_scroll_bar_close (b);
  1428.  
  1429.       next = b->next;
  1430.       b->next = b->prev = Qnil;
  1431.     }
  1432.  
  1433.   /* Now there should be no references to the condemned scroll bars,
  1434.      and they should get garbage-collected.  */
  1435. }
  1436.  
  1437.  
  1438. void x_destroy_window (struct frame *f)
  1439. {
  1440.   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
  1441.   pm_request pmr;
  1442.  
  1443.   dpyinfo->reference_count--;
  1444.  
  1445.   if (f == dpyinfo->mouse_face_mouse_frame)
  1446.     {
  1447.       dpyinfo->mouse_face_beg_row
  1448.     = dpyinfo->mouse_face_beg_col = -1;
  1449.       dpyinfo->mouse_face_end_row
  1450.     = dpyinfo->mouse_face_end_col = -1;
  1451.       dpyinfo->mouse_face_window = Qnil;
  1452.     }
  1453.  
  1454. #if 0
  1455.   /* This is not required as no resources were allocated for the
  1456.      menubar in Emacs proper. */
  1457.   free_frame_menubar (f);
  1458. #endif
  1459.   pm_del_frame (f);
  1460.   pmr.header.type = PMR_DESTROY;
  1461.   pmr.header.frame = (unsigned long)f;
  1462.   pm_send (&pmr, sizeof (pmr));
  1463.   free_frame_faces (f);
  1464. }
  1465.  
  1466.  
  1467. void x_set_mouse_position (struct frame *f, int x, int y)
  1468. {
  1469.   /*TODO*/
  1470. }
  1471.  
  1472.  
  1473. /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F.  */
  1474.  
  1475. void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
  1476. {
  1477.   /*TODO*/
  1478. }
  1479.  
  1480.  
  1481. static void PM_frame_raise_lower (struct frame *f, int raise_flag)
  1482. {
  1483.   pm_request pmr;
  1484.  
  1485.   pmr.header.type = (raise_flag ? PMR_RAISE : PMR_LOWER);
  1486.   pmr.header.frame = (unsigned long)f;
  1487.   pm_send (&pmr, sizeof (pmr));
  1488. }
  1489.  
  1490.  
  1491. void x_make_frame_visible (struct frame *f)
  1492. {
  1493.   pm_request pmr;
  1494.  
  1495.   if (!FRAME_VISIBLE_P (f))
  1496.     {
  1497.       pmr.visible.header.type = PMR_VISIBLE;
  1498.       pmr.visible.header.frame = (unsigned long)f;
  1499.       pmr.visible.visible = 1;
  1500.       pm_send (&pmr, sizeof (pmr));
  1501.       f->async_visible = 1;
  1502.       f->async_iconified = 0;
  1503.     }
  1504. }
  1505.  
  1506.  
  1507. void x_make_frame_invisible (struct frame *f)
  1508. {
  1509.   pm_request pmr;
  1510.  
  1511.   if (!f->async_visible)
  1512.     return;
  1513.   f->async_visible = 0;
  1514.   pmr.visible.header.type = PMR_VISIBLE;
  1515.   pmr.visible.header.frame = (unsigned long)f;
  1516.   pmr.visible.visible = 0;
  1517.   pm_send (&pmr, sizeof (pmr));
  1518. }
  1519.  
  1520.  
  1521. void x_iconify_frame (struct frame *f)
  1522. {
  1523.   pm_request pmr;
  1524.  
  1525.   f->async_visible = 0;
  1526.   f->async_iconified = 1;
  1527.   pmr.header.type = PMR_ICONIFY;
  1528.   pmr.header.frame = (unsigned long)f;
  1529.   pm_send (&pmr, sizeof (pmr));
  1530. }
  1531.  
  1532.  
  1533. void x_set_window_size (struct frame *f, int change_gravity,
  1534.                         int cols, int rows)
  1535. {
  1536.   pm_request pmr;
  1537.  
  1538.   check_frame_size (f, &rows, &cols);
  1539.   change_frame_size (f, rows, cols, 0, 0);
  1540.   pmr.size.header.type = PMR_SIZE;
  1541.   pmr.size.header.frame = (unsigned long)f;
  1542.   pmr.size.width = cols;
  1543.   pmr.size.height = rows;
  1544.   pm_send (&pmr, sizeof (pmr));
  1545.  
  1546.   /* If cursor was outside the new size, mark it as off.  */
  1547.   if (f->phys_cursor_y >= rows
  1548.       || f->phys_cursor_x >= cols)
  1549.     {
  1550.       f->phys_cursor_x = -1;
  1551.       f->phys_cursor_y = -1;
  1552.     }
  1553.   SET_FRAME_GARBAGED (f);
  1554. }
  1555.  
  1556.  
  1557. void x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity)
  1558. {
  1559.   pm_request pmr;
  1560.  
  1561.   pmr.setpos.header.type = PMR_SETPOS;
  1562.   pmr.setpos.header.frame = (unsigned long)f;
  1563.   if (xoff >= 0)
  1564.     {
  1565.       pmr.setpos.left = xoff;
  1566.       pmr.setpos.left_base = 1;
  1567.     }
  1568.   else
  1569.     {
  1570.       pmr.setpos.left = -xoff;
  1571.       pmr.setpos.left_base = -1;
  1572.     }
  1573.   if (yoff >= 0)
  1574.     {
  1575.       pmr.setpos.top = yoff;
  1576.       pmr.setpos.top_base = 1;
  1577.     }
  1578.   else
  1579.     {
  1580.       pmr.setpos.top = -yoff;
  1581.       pmr.setpos.top_base = -1;
  1582.     }
  1583.   pm_send (&pmr, sizeof (pmr));
  1584. }
  1585.  
  1586.  
  1587. void x_focus_on_frame (struct frame *f)
  1588. {
  1589.   pm_request pmr;
  1590.  
  1591.   pmr.header.type = PMR_FOCUS;
  1592.   pmr.header.frame = (unsigned long)f;
  1593.   pm_send (&pmr, sizeof (pmr));
  1594. }
  1595.  
  1596.  
  1597. void pm_init (void)
  1598. {
  1599.     int i, pipe_in[2], pipe_out[2];
  1600.     char arg1[12], arg2[12], arg3[12], *debugger;
  1601.     pm_request pmr;
  1602.     struct x_display_info *dpyinfo;
  1603.     Lisp_Object prog;
  1604.  
  1605.     mouse_frame = 0;
  1606.  
  1607.     for (i = 0; i < 64; i++)
  1608.         fcntl (i, F_SETFD, 1);
  1609.  
  1610.     sprintf (arg1, "%d", getpid ());
  1611.  
  1612.     if (pipe (pipe_out) != 0)
  1613.         fatal ("Cannot open pipe for PM Emacs.");
  1614.     fcntl (pipe_out[1], F_SETFD, 1); /* Don't pass write end to child */
  1615.     outbound_pipe = pipe_out[1];
  1616.     setmode (outbound_pipe, O_BINARY);
  1617.     sprintf (arg2, "%d", pipe_out[0]);
  1618.  
  1619.     if (pipe (pipe_in) != 0)
  1620.         fatal ("Cannot open pipe for PM Emacs.");
  1621.     dup2 (pipe_in[0], 0);         /* Replace stdin with pipe */
  1622.     close (pipe_in[0]);
  1623.     fcntl (0, F_SETFD, 1);        /* Don't pass read end to child */
  1624.     setmode (0, O_BINARY);
  1625.     sprintf (arg3, "%d", pipe_in[1]);
  1626.  
  1627.     prog = concat2 (Vinvocation_directory, build_string ("pmemacs.exe"));
  1628.     debugger = getenv ("PMEMACS_DEBUGGER");
  1629.     if (debugger != NULL)
  1630.         pm_pid = spawnl (P_PM, debugger, debugger,
  1631.                          XSTRING (prog)->data, arg1, arg2, arg3, 0);
  1632.     else
  1633.         pm_pid = spawnl (P_PM, XSTRING (prog)->data, "pmemacs.exe",
  1634.                          arg1, arg2, arg3, 0);
  1635.     if (pm_pid == -1)
  1636.         fatal ("Cannot start PM Emacs.");
  1637.  
  1638.     close (pipe_out[0]);
  1639.     close (pipe_in[1]);
  1640.     pm_session_started = 1;
  1641.  
  1642.     pmr.initialize.header.type = PMR_INITIALIZE;
  1643.     pmr.initialize.header.frame = 0;
  1644.     pmr.initialize.codepage = cur_code_page != 0 ? cur_code_page : 850;
  1645.     pm_send (&pmr, sizeof (pmr));
  1646.  
  1647.     clear_frame_hook = PM_clear_frame;
  1648.     clear_end_of_line_hook = PM_clear_end_of_line;
  1649.     ins_del_lines_hook = PM_ins_del_lines;
  1650.     set_terminal_window_hook = PM_set_terminal_window;
  1651. #if 0
  1652.     insert_glyphs_hook = PM_insert_glyphs;
  1653.     delete_glyphs_hook = PM_delete_glyphs;
  1654. #endif
  1655.     frame_raise_lower_hook = PM_frame_raise_lower;
  1656.     change_line_highlight_hook = PM_change_line_highlight;
  1657.     reassert_line_highlight_hook = PM_reassert_line_highlight;
  1658.     mouse_position_hook = PM_mouse_position;
  1659.     write_glyphs_hook = PM_write_glyphs;
  1660.     ring_bell_hook = PM_ring_bell;
  1661.     set_terminal_modes_hook = PM_set_terminal_modes;
  1662.     update_begin_hook = PM_update_begin;
  1663.     update_end_hook = PM_update_end;
  1664.     read_socket_hook = PM_read_socket;
  1665.     cursor_to_hook = PM_cursor_to;
  1666.     frame_up_to_date_hook = PM_frame_up_to_date;
  1667.  
  1668.     set_vertical_scroll_bar_hook  = PM_set_vertical_scroll_bar;
  1669.     judge_scroll_bars_hook = PM_judge_scroll_bars;
  1670.     redeem_scroll_bar_hook = PM_redeem_scroll_bar;
  1671.     condemn_scroll_bars_hook = PM_condemn_scroll_bars;
  1672.  
  1673.     scroll_region_ok = 1;        /* we'll scroll partial frames */
  1674.     char_ins_del_ok = 0;        /* just as fast to write the line */
  1675.     line_ins_del_ok = 1;        /* use GpiBitBlt */
  1676.     fast_clear_end_of_line = 1;    /* PM does this well */
  1677.     memory_below_frame = 0;    /* we don't remember what scrolls
  1678.                                off the bottom */
  1679.     baud_rate = 19200;
  1680.  
  1681.     /* Get the number of planes. */
  1682.     BLOCK_INPUT;
  1683.     pmr.config.header.type = PMR_CONFIG;
  1684.     pmr.config.header.frame = 0;
  1685.     pmr.config.serial = pm_serial++;
  1686.     pm_send (&pmr, sizeof (pmr));
  1687.     if (pm_receive (pmr.config.serial, &pm_config, NULL, 0) == NULL)
  1688.     {
  1689.         pm_config.planes = 1;
  1690.         pm_config.color_cells = 2;
  1691.         pm_config.width_mm = 1;
  1692.         pm_config.height_mm = 1;
  1693.     }
  1694.     UNBLOCK_INPUT;
  1695.  
  1696.     signal (SIGPIPE, pm_sigpipe);
  1697.  
  1698.     dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
  1699.     dpyinfo->reference_count = 0;
  1700.     dpyinfo->grabbed = 0;
  1701.     dpyinfo->mouse_face_mouse_frame = 0;
  1702.     dpyinfo->mouse_face_deferred_gc = 0;
  1703.     dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
  1704.     dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
  1705.     dpyinfo->mouse_face_face_id = 0;
  1706.     dpyinfo->mouse_face_window = Qnil;
  1707.     dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
  1708.     dpyinfo->mouse_face_defer = 0;
  1709.  
  1710.     pm_display = dpyinfo;
  1711. }
  1712.  
  1713.  
  1714. void pm_exit (void)
  1715. {
  1716.   pm_request pmr;
  1717.   pm_event pme;
  1718.  
  1719.   pmr.header.type = PMR_CLOSE;
  1720.   pmr.header.frame = 0;
  1721.   pm_send (&pmr, sizeof (pmr));
  1722.  
  1723.   /* Wait until the pipe is closed, that is, until pmemacs.exe is
  1724.      dead.  Why use waitpid() if we can do without? :-) */
  1725.  
  1726.   while (receive (&pme, sizeof (pme), 1))
  1727.     if (pme.header.type == PME_ANSWER && pme.answer.size > 0)
  1728.       {
  1729.         char *tem = (char *)xmalloc (pme.answer.size);
  1730.         if (!receive (tem, pme.answer.size, 1))
  1731.           break;
  1732.         xfree (tem);
  1733.       }
  1734.  
  1735.   pm_session_started = 0;
  1736.   close (outbound_pipe);
  1737.   close (0);
  1738. }
  1739.  
  1740.  
  1741. void pm_shutdown (void)
  1742. {
  1743.   if (pm_session_started)
  1744.     pm_exit ();
  1745. }
  1746.  
  1747.  
  1748. void syms_of_xterm ()
  1749. {
  1750. }
  1751.  
  1752.  
  1753. void x_handle_selection_request (struct input_event *event)
  1754. {
  1755. }
  1756.  
  1757. void x_handle_selection_clear (struct input_event *event)
  1758. {
  1759. }
  1760.  
  1761.  
  1762. static XFontStruct *pm_fonts = 0;
  1763.  
  1764.  
  1765. XFontStruct *XLoadQueryFont (Display *dpy, char *name)
  1766. {
  1767.   XFontStruct *p;
  1768.  
  1769.   for (p = pm_fonts; p != 0; p = p->next)
  1770.     if (strcmp (p->name, name) == 0)
  1771.       return p;
  1772.   p = (XFontStruct *)xmalloc (sizeof (*p));
  1773.   bzero (p, sizeof (XFontStruct));
  1774.   p->max_bounds.width = 1;      /* TODO */
  1775.   p->ascent = 1;                /* TODO */
  1776.   p->descent = 0;               /* TODO */
  1777.   _strncpy (p->name, name, sizeof (p->name));
  1778.   p->next = pm_fonts;
  1779.   pm_fonts = p;
  1780.   return p;
  1781. }
  1782.  
  1783.  
  1784. int XParseColor (Display *dpy, Colormap cmap, char *name, XColor *color)
  1785. {
  1786.   return defined_color (NULL, name, color, 0);
  1787. }
  1788.