home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / lemacs-19.6 / src / xdisp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-13  |  108.9 KB  |  3,865 lines

  1. /* Display generation from window structure and buffer text.
  2.    Copyright (C) 1992, 1993 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Emacs.
  5.  
  6. GNU Emacs is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU Emacs is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. #include "config.h"
  22. #include <stdio.h>
  23.  
  24. #include "lisp.h"
  25. #include "window.h"
  26. #include "termchar.h"
  27. #include "buffer.h"
  28. #include "extents.h"
  29. #include "screen.h"
  30. #include "indent.h"
  31. #include "commands.h"
  32. #include "macros.h"
  33. #include "disptab.h"
  34. #ifdef HAVE_X_WINDOWS
  35. #include "xterm.h"
  36. #endif
  37.  
  38. extern int interrupt_input;
  39.  
  40. /* Nonzero means print newline before next minibuffer message.  */
  41.  
  42. int noninteractive_need_newline;
  43.  
  44. #define min(a, b) ((a) < (b) ? (a) : (b))
  45. #define max(a, b) ((a) > (b) ? (a) : (b))
  46.  
  47. /* The buffer position of the first character appearing
  48.  entirely or partially on the current screen line.
  49.  Or zero, which disables the optimization for the current screen line. */
  50. static int this_line_bufpos;
  51.  
  52. /* Number of characters past the end of this line,
  53.    including the terminating newline */
  54. static int this_line_endpos;
  55.  
  56. /* The vertical position of this screen line. */
  57. static int this_line_vpos;
  58.  
  59. /* Hpos value for start of display on this screen line.
  60.    Usually zero, but negative if first character really began
  61.    on previous line */
  62. static int this_line_start_hpos;
  63.  
  64. /* Buffer that this_line variables are describing. */
  65. static struct buffer *this_line_buffer;
  66.  
  67. /* Value of echo_area_glyphs when it was last acted on.
  68.   If this is nonzero, there is a message on the screen
  69.   in the minibuffer and it should be erased as soon
  70.   as it is no longer requested to appear. */
  71. static char *previous_echo_glyphs;
  72.  
  73. /* Nonzero means truncate lines in all windows less wide than the screen */
  74. int truncate_partial_width_windows;
  75.  
  76. Lisp_Object Vglobal_mode_string;
  77.  
  78. /* Marker for where to display an arrow on top of the buffer text.  */
  79. extern Lisp_Object Voverlay_arrow_position;
  80.  
  81. /* String to display for the arrow.  */
  82. extern Lisp_Object Voverlay_arrow_string;
  83.  
  84. /* Values of those variables at last redisplay.  */
  85. static Lisp_Object last_arrow_position, last_arrow_string;
  86.  
  87. /* Nonzero if overlay arrow has been displayed once in this window.  */
  88. static int overlay_arrow_seen;
  89.  
  90. /* The number of lines to try scrolling a
  91.   window by when point leaves the window; if
  92.   it is <=0 then point is centered in the window */
  93. int scroll_step;
  94.  
  95. /* Nonzero if try_window_id has made blank lines at window bottom
  96.  since the last redisplay that paused */
  97. static int blank_end_of_window;
  98.  
  99. /* Number of windows showing the buffer of the selected window.
  100.    keyboard.c refers to this.  */
  101. int buffer_shared;
  102.  
  103. /* display_text_line sets these to the screen position (origin 0) of point,
  104.    whether the window is selected or not.
  105.    Set one to -1 first to determine whether point was found afterwards.  */
  106.  
  107. static int cursor_vpos;
  108. static int cursor_hpos;
  109.  
  110. /*int debug_end_pos;*/
  111.  
  112. /* Nonzero means display mode line highlighted */
  113. int mode_line_inverse_video;
  114.  
  115. static void mark_window_display_accurate ();
  116. static void redisplay_windows ();
  117. static void redisplay_window ();
  118. static void try_window ();
  119. static int try_window_id ();
  120. static struct position *display_text_line ();
  121. static void display_mode_line ();
  122. static int display_mode_element ();
  123. static int display_string ();
  124. void x_format_screen_title ();
  125.  
  126. /* Prompt to display in front of the minibuffer contents */
  127. Lisp_Object Vminibuf_prompt;
  128.  
  129. /* Width in columns of current minibuffer prompt.  */
  130. int minibuf_prompt_width;
  131.  
  132. /* Width in pixels of current minibuffer prompt.  */
  133. int minibuf_prompt_pix_width;
  134.  
  135. /* Empty buffer made current in the minibuffer when echo display is on */
  136. Lisp_Object echo_area_buffer;
  137.  
  138. extern Lisp_Object Vminibuffer_list;
  139.  
  140. /* Message to display instead of minibuffer contents
  141.    This is what the functions error and message make,
  142.    and command echoing uses it as well.
  143.    It overrides the minibuf_prompt as well as the buffer.  */
  144. char *echo_area_glyphs;
  145.  
  146. /* true iff we should redraw the mode lines on the next redisplay */
  147. int redraw_mode_line;
  148.  
  149. /* Smallest number of characters before the gap
  150.    at any time since last redisplay that finished.
  151.    Valid for current buffer when try_window_id can be called.  */
  152. int beg_unchanged;
  153.  
  154. /* Smallest number of characters after the gap
  155.    at any time since last redisplay that finished.
  156.    Valid for current buffer when try_window_id can be called.  */
  157. int end_unchanged;
  158.  
  159. /* MODIFF as of last redisplay that finished;
  160.    if it matches MODIFF, beg_unchanged and end_unchanged
  161.    contain no useful information */
  162. int unchanged_modified;
  163.  
  164. /* Nonzero if head_clip or tail_clip of current buffer has changed
  165.    since last redisplay that finished */
  166. int clip_changed;
  167.  
  168. /* Nonzero if window sizes or contents have changed
  169.    since last redisplay that finished */
  170. int windows_or_buffers_changed;
  171.  
  172. /* Screen currently being updated, or 0 if not in an update. */
  173. extern SCREEN_PTR updating_screen;
  174.  
  175. /* This gets set to 1 when the user has changed fonts, colors, etc.,
  176.    meaning that our cached GCs need to be rebuilt.
  177.  */
  178. extern int face_cache_invalid;
  179.  
  180.  
  181. #ifdef MULTI_SCREEN
  182.  
  183. extern void clear_screen (void);
  184. extern void clear_screen_records (struct screen *);
  185.  
  186. static void
  187. redraw_screen (s)
  188.      SCREEN_PTR s;
  189. {
  190.   SCREEN_PTR s2 = 0;
  191.  
  192.   /* clear_screen doesn't take a screen argument, 
  193.      so swap s into selected_screen */
  194.   if (s != selected_screen)
  195.     s2 = selected_screen, selected_screen = s;
  196.   clear_screen ();
  197.   if (s2) selected_screen = s2;
  198.  
  199.   if (SCREEN_IS_TERMCAP (s))
  200.     fflush (stdout);
  201.  
  202.   clear_screen_records (s);
  203.   windows_or_buffers_changed++;
  204.  
  205.   /* Mark all windows as INaccurate,
  206.      so that every window will have its redisplay done.  */
  207.   mark_window_display_accurate (SCREEN_ROOT_WINDOW (s), 0);
  208.   s->garbaged = 1;  /* this was 0, that can't have been right, right? */
  209. }
  210.  
  211. DEFUN ("redraw-screen", Fredraw_screen, Sredraw_screen, 1, 1, 0,
  212.   "Clear screen SCREEN and output again what is supposed to appear on it.")
  213.   (screen)
  214.      Lisp_Object screen;
  215. {
  216.   SCREEN_PTR s;
  217.  
  218.   CHECK_SCREEN (screen, 0);
  219.   s = XSCREEN (screen);
  220.   redraw_screen (s);
  221.  
  222.   return Qnil;
  223. }
  224.  
  225. DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
  226.   "Redraw all screens marked as having their images garbled.")
  227.   ()
  228. {
  229.   Lisp_Object screen, tail;
  230.  
  231.   for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
  232.     {
  233.       screen = XCONS (tail)->car;
  234.       if (XSCREEN (screen)->garbaged && XSCREEN (screen)->visible)
  235.     Fredraw_screen (screen);
  236.     }
  237.   return Qnil;
  238. }
  239. #else  /* Not MULTI_SCREEN */
  240. DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
  241.   "Clear the screen and output again what is supposed to appear on it.")
  242.   ()
  243. {
  244.   clear_screen ();
  245.   fflush (stdout);
  246.   clear_screen_records (selected_screen);
  247.   windows_or_buffers_changed++;
  248.   /* Mark all windows as INaccurate,
  249.      so that every window will have its redisplay done.  */
  250.   mark_window_display_accurate (XWINDOW (minibuf_window)->prev, 0);
  251.   return Qnil;
  252. }
  253. #endif /* not MULTI_SCREEN */
  254.  
  255. extern void cancel_line (int, struct screen *);
  256.  
  257. static void
  258. echo_area_display (s)
  259.      SCREEN_PTR s;
  260. {
  261.   register int vpos;
  262.  
  263.   if (!s->visible)
  264.     return;
  265.  
  266. #if 0
  267. #ifdef MULTI_SCREEN
  268.   choose_minibuf_screen ();
  269.   s = XSCREEN (XWINDOW (minibuf_window)->screen);
  270. #endif
  271. #endif
  272.  
  273.   if (SCREEN_GARBAGED_P (s))
  274.     Fredraw_display ();
  275.  
  276.   if (echo_area_glyphs || minibuf_level == 0)
  277.     {
  278.       if (s != XSCREEN (XWINDOW (minibuf_window)->screen))
  279.     return;
  280.  
  281.       vpos = XFASTINT (XWINDOW (minibuf_window)->top);
  282.       cancel_line (vpos, s);    /* don't ask me why... */
  283.       get_display_line (s, vpos, 0);
  284.       display_string (XWINDOW (minibuf_window), vpos,
  285.               echo_area_glyphs ? echo_area_glyphs : "",
  286.               0, 0, 0, SCREEN_WIDTH (s), &SCREEN_NORMAL_FACE (s), 0);
  287.  
  288.       /* If desired cursor location is on this line, put it at end of text */
  289.       if (SCREEN_CURSOR_Y (s) == vpos)
  290.     SCREEN_CURSOR_X (s) = s->desired_glyphs->used[vpos];
  291.     }
  292.   else if (!EQ (minibuf_window, selected_window))
  293.     windows_or_buffers_changed++;
  294.  
  295.   if (EQ (minibuf_window, selected_window))
  296.     {
  297.       this_line_bufpos = 0;
  298.     }
  299.   if (echo_area_glyphs)
  300.     previous_echo_glyphs = echo_area_glyphs;
  301. }
  302.  
  303. char *message_buf;
  304.  
  305. /* dump an informative message to the minibuf */
  306. /* VARARGS 1 */
  307.  
  308. void
  309. message (m, a1, a2, a3)
  310.      char *m;
  311.      char *a1, *a2, *a3;
  312. {
  313.   SCREEN_PTR s;
  314.  
  315.   if (noninteractive || !NILP (Vpurify_flag))
  316.     {
  317.       if (noninteractive_need_newline)
  318.     putc ('\n', stderr);
  319.       if (m)                    /* m == 0 means clear echo-area msg */
  320.       {
  321.         fprintf (stderr, m, a1, a2, a3);
  322.         fprintf (stderr, "\n");
  323.       }
  324.       fflush (stderr);
  325.     }
  326.   else if (INTERACTIVE)
  327.     {
  328. #ifdef NO_ARG_ARRAY
  329.       char *a[3];
  330.       a[0] = a1;
  331.       a[1] = a2;
  332.       a[2] = a3;
  333. #endif /* NO_ARG_ARRAY */
  334.  
  335.       s = choose_minibuf_screen ();
  336.  
  337.       /* It is bad to print gc messages on stdout before the first X screen
  338.      has been created.
  339.        */
  340.       if (!NILP (Vwindow_system) && !SCREEN_IS_X (s))
  341.     return;
  342.  
  343.       if (!SCREEN_MESSAGE_BUF (s))
  344.         return;
  345.  
  346.       if (!m)
  347.       {
  348.         /* Clear minibuffer message */
  349.         echo_area_glyphs = 0;
  350.         previous_echo_glyphs = 0;
  351.       }
  352.       else
  353.       {
  354. #ifdef NO_ARG_ARRAY
  355.     doprnt (SCREEN_MESSAGE_BUF (s),
  356.         SCREEN_WIDTH (s), m, 0, 3, a);
  357. #else
  358.     doprnt (SCREEN_MESSAGE_BUF (s),
  359.         SCREEN_WIDTH (s), m, 0, 3, &a1);
  360. #endif /* NO_ARG_ARRAY */
  361.  
  362.     echo_area_glyphs = SCREEN_MESSAGE_BUF (s);
  363.       }
  364.       if (in_display > 0 || updating_screen != 0
  365.       || ! SCREEN_VISIBLE_P (s))
  366.     return;
  367.  
  368.       echo_area_display (s);
  369.       update_screen (s, 1, 1);
  370.     }
  371. }
  372.  
  373.  
  374. /* Do a screen update, taking possible shortcuts into account.
  375.    This is the main external entry point for redisplay.
  376.  
  377.    If the last redisplay displayed a minibuffer message and that
  378.    message is no longer requested, we usually redraw the contents
  379.    of the minibuffer, or clear the minibuffer if it is not in use.
  380.  
  381.    Everyone would like to have a hook here to call eval,
  382.    but that cannot be done safely without a lot of changes elsewhere.
  383.    This can be called from signal handlers; with alarms set up;
  384.    or with synchronous processes running.
  385.    See the echo functions in keyboard.c.
  386.    See Fcall_process; if you called it from here, it could be
  387.    entered recursively.  */
  388.  
  389. extern void update_psheets (void);
  390. extern int pos_tab_offset (struct window *, int); 
  391. extern void preserve_other_columns (struct window *); 
  392. extern void request_sigio (void);
  393. extern void unrequest_sigio (void);
  394. extern void update_screen_menubars (void);
  395. extern void flush_face_cache (void);
  396.  
  397. int
  398. shot_cut_taken_p (SCREEN_PTR s)
  399. {
  400.   return s->desired_glyphs->short_cut_taken == 1;
  401. }
  402.  
  403. void
  404. mark_short_cut_taken (SCREEN_PTR s)
  405. {
  406.   s->desired_glyphs->short_cut_taken = 1;
  407. }
  408.  
  409. void
  410. clear_short_cut_taken (SCREEN_PTR s)
  411. {
  412.   s->desired_glyphs->short_cut_taken = 0;
  413. }
  414.  
  415. /* This flag is set to 1 when we have to run a blank redisplay. */
  416. static int bogus_mouse_hat_trick;
  417. void
  418. recompute_glyphs_no_short_cut (SCREEN_PTR s)
  419. {
  420.   /* force the recomputation of the desired glyphs */
  421.   bogus_mouse_hat_trick = 1;
  422.   mark_window_display_accurate (SCREEN_ROOT_WINDOW (s), 0);
  423.   redisplay ();
  424.   bogus_mouse_hat_trick = 0;
  425. }
  426.  
  427. void
  428. redisplay ()
  429. {
  430.   register struct window *w = XWINDOW (selected_window);
  431.   register int pause = 0;
  432.   int must_finish = 0;
  433.   int all_windows;
  434.   register int tlbufpos, tlendpos;
  435.   struct position pos;
  436.  
  437.   extern int detect_input_pending ();
  438.   int input_pending = detect_input_pending ();
  439.  
  440.   Lisp_Object tail;
  441.   SCREEN_PTR s;
  442.  
  443.   if (bogus_mouse_hat_trick)
  444.     input_pending = 0;
  445.  
  446.   if (noninteractive || in_display || input_pending)
  447.     return;
  448.  
  449.   update_psheets ();
  450.  
  451.   in_display++;
  452.  
  453.   if (screen_garbaged)
  454.     Fredraw_display ();
  455.  
  456. #ifdef MULTI_SCREEN
  457.   for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr){
  458.     
  459.     if (!SCREENP (XCONS (tail)->car))
  460.       continue;
  461.     
  462.     s = XSCREEN (XCONS (tail)->car);
  463.     memset (SCREEN_DESIRED_GLYPHS (s)->enable, 0, SCREEN_HEIGHT (s));
  464.   }
  465. #else
  466.   memset (SCREEN_DESIRED_GLYPHS (selected_screen)->enable, 0,
  467.      SCREEN_HEIGHT (selected_screen));
  468. #endif
  469.  
  470.   if (echo_area_glyphs || previous_echo_glyphs)
  471.     {
  472.       /* #### I doubt this is right.  It used to always set
  473.      must_finish to 1 here, but that meant that every screen
  474.      got redisplayed evry time whenever there was a message in
  475.      the minibuffer... */
  476.       if (echo_area_glyphs != previous_echo_glyphs)
  477.     must_finish = 1;
  478.       echo_area_display (choose_minibuf_screen ());
  479.     }
  480.  
  481.   if (clip_changed || windows_or_buffers_changed)
  482.     redraw_mode_line++;
  483.  
  484.   /* Detect case that we need to write a star in the mode line.  */
  485.   if (XFASTINT (w->last_modified) < MODIFF
  486.       && XFASTINT (w->last_modified) <= current_buffer->save_modified)
  487.     {
  488.       w->redo_mode_line = Qt;
  489.       if (buffer_shared > 1)
  490.     redraw_mode_line++;
  491.     }
  492.  
  493.   all_windows = redraw_mode_line || buffer_shared > 1;
  494. #ifdef MULTI_SCREEN
  495. #if 0
  496.   all_windows |= (! NILP (Vglobal_minibuffer_screen)
  497.           && selected_screen != XSCREEN (Vglobal_minibuffer_screen));
  498. #endif
  499. #endif    /* MULTI_SCREEN */
  500.  
  501.   /* If specs for an arrow have changed, do thorough redisplay
  502.      to ensure we remove any arrow that should no longer exist.  */
  503.   if (Voverlay_arrow_position != last_arrow_position
  504.       || Voverlay_arrow_string != last_arrow_string)
  505.     all_windows = 1, clip_changed = 1;
  506.  
  507.   tlbufpos = this_line_bufpos;
  508.   tlendpos = this_line_endpos;
  509.   if (!all_windows && tlbufpos > 0 && NILP (w->redo_mode_line)
  510.       && SCREEN_VISIBLE_P (XSCREEN (w->screen))
  511.       /* Make sure recorded data applies to current buffer, etc */
  512.       && this_line_buffer == current_buffer
  513.       && current_buffer == XBUFFER (w->buffer)
  514.       && NILP (w->force_start)
  515.       /* Point must be on the line that we have info recorded about */
  516.       && point >= tlbufpos
  517.       && point <= Z - tlendpos
  518.  
  519.       /* All text outside that line, including its final newline,
  520.      must be unchanged */
  521.       && (XFASTINT (w->last_modified) >= MODIFF
  522.       || (beg_unchanged >= tlbufpos - 1
  523.           && GPT >= tlbufpos
  524.           && end_unchanged >= tlendpos
  525.           && Z - GPT >= tlendpos)))
  526.     {
  527.       if (tlbufpos > BEGV && CHAR_AT (tlbufpos - 1) != '\n'
  528.       && (tlbufpos == ZV
  529.           || CHAR_AT (tlbufpos) == '\n'))
  530.     /* Former continuation line has disappeared by becoming empty */
  531.     goto cancel;
  532.       if (XFASTINT (w->last_modified) < MODIFF
  533.       /* || (MINI_WINDOW_P (w) && 
  534.              (previous_echo_glyphs || echo_area_glyphs)) */
  535.       )
  536.     {
  537.       cursor_vpos = -1;
  538.       overlay_arrow_seen = 0;
  539.       display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos,
  540.                  pos_tab_offset (w, tlbufpos));
  541.       /* If line contains point, is not continued,
  542.          and ends at same distance from eob as before, we win */
  543.       if (cursor_vpos >= 0 && this_line_bufpos
  544.           && this_line_endpos == tlendpos)
  545.         {
  546.           if (XFASTINT (w->width) != 
  547.                   SCREEN_WIDTH (XSCREEN (WINDOW_SCREEN (w))))
  548.         {
  549.           preserve_other_columns (w);
  550.           mark_short_cut_taken (XSCREEN (w->screen));
  551.           goto update;
  552.         }
  553.         }
  554.       else
  555.         goto cancel;
  556.     }
  557.       else if (point == XFASTINT (w->last_point))
  558.     {
  559.       if (!must_finish)
  560.         {
  561.           in_display--;
  562.           return;
  563.         }
  564.       goto update;
  565.     }
  566.       else
  567.     {
  568.       int hscroll = XINT (w->hscroll);
  569.       pos = 
  570.             *compute_motion
  571.               (selected_window,
  572.                tlbufpos, 0,
  573.                (hscroll ? 1 - hscroll : 0) + 
  574.                ((MINI_WINDOW_P (w) && tlbufpos == 1) ? 
  575.                 minibuf_prompt_width : 0),
  576.                point, 2, - (1 << (SHORTBITS - 1)),
  577.                XFASTINT (w->width) - 1
  578.                - (XFASTINT (w->width) + XFASTINT (w->left)
  579.                   != SCREEN_WIDTH (selected_screen)),
  580.                hscroll, 0,
  581.                ((MINI_WINDOW_P (w) && tlbufpos == 1)
  582.                 ? minibuf_prompt_pix_width
  583.                 : 0),
  584.                0);
  585.       if (pos.vpos < 1)
  586.         {
  587.           SCREEN_CURSOR_X (selected_screen)
  588.         = XFASTINT (w->left) + max (pos.hpos, 0);
  589.           SCREEN_CURSOR_Y (selected_screen) = this_line_vpos;
  590.           goto update;
  591.         }
  592.       else
  593.         goto cancel;
  594.     }
  595.     cancel:
  596.       /* Text changed drastically or point moved off of line */
  597.       cancel_line (this_line_vpos, selected_screen);
  598.     }
  599.   this_line_bufpos = 0;
  600.  
  601.   if (all_windows)
  602.     {
  603. #ifdef MULTI_SCREEN
  604.       /* Recompute # windows showing selected buffer.
  605.      This will be incremented each time such a window is displayed.  */
  606.       buffer_shared = 0;
  607.  
  608.       for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
  609.     {
  610.       SCREEN_PTR s;
  611.  
  612.       if (!SCREENP (XCONS (tail)->car))
  613.         continue;
  614.  
  615.       s = XSCREEN (XCONS (tail)->car);
  616.       if (s->visible)
  617.         {
  618.           /* Clear the echo area on screens where the minibuffer isn't.  */
  619.           if (s != XSCREEN (XWINDOW (minibuf_window)->screen)
  620.           /* But only screens that have minibuffers.  */
  621.           && s->has_minibuffer)
  622.         {
  623.           int vpos = XFASTINT (XWINDOW (s->minibuffer_window)->top);
  624.  
  625.           cancel_line (vpos, s);
  626.           get_display_line (s, vpos, 0);
  627.           display_string 
  628.                     (XWINDOW (s->minibuffer_window), vpos, "",
  629.                      0, 0, 0, s->width, &SCREEN_NORMAL_FACE (s), 0);
  630.         }
  631.  
  632.           /* Redraw its windows.  */
  633.           clear_short_cut_taken (s);
  634.           redisplay_windows (SCREEN_ROOT_WINDOW (s));
  635.         }
  636.     }
  637. #else
  638.     redisplay_windows (SCREEN_ROOT_WINDOW (s));
  639. #endif /* not MULTI_SCREEN */
  640.     }
  641.   else if (SCREEN_VISIBLE_P (selected_screen))
  642.     {
  643.       redisplay_window (selected_window, 1);
  644.       if (XFASTINT (w->width) != SCREEN_WIDTH (selected_screen))
  645.     preserve_other_columns (w);
  646.     }
  647.  
  648. update: 
  649.   if (bogus_mouse_hat_trick)
  650.     {
  651.       in_display--;
  652.       return;
  653.     }
  654.  
  655.   if (interrupt_input)
  656.     unrequest_sigio ();
  657.  
  658. #ifdef MULTI_SCREEN
  659.   if (all_windows)
  660.     {
  661.       pause = 0;
  662.  
  663.       for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
  664.     {
  665.       SCREEN_PTR s;
  666.  
  667.       if (!SCREENP (XCONS (tail)->car))
  668.         continue;
  669.  
  670.       s = XSCREEN (XCONS (tail)->car);
  671.       if (s->visible)
  672.         {
  673.           pause |= update_screen (s, must_finish, 0);
  674.           if (must_finish && pause)
  675.         abort ();
  676.           if (!pause)
  677.         {
  678.           mark_window_display_accurate (s->root_window, 1);
  679.           s->garbaged = 0;
  680.         }
  681.         }
  682.     }
  683.     }
  684.   else
  685. #endif /* MULTI_SCREEN */
  686.     if (SCREEN_VISIBLE_P (selected_screen))
  687.       {
  688.     pause = update_screen (selected_screen, must_finish, 0);
  689.     if (must_finish && pause)
  690.       abort ();
  691.     if (!pause)
  692.       /* #### Should we do mark_window_display_accurate() here too? */
  693.       selected_screen->garbaged = 0;
  694.       }
  695.  
  696.   /* If screen does not match, prevent doing single-line-update next time.
  697.      Also, don't forget to check every line to update the arrow.  */
  698.   if (pause)
  699.     {
  700.       this_line_bufpos = 0;
  701.       if (!NILP (last_arrow_position))
  702.     {
  703.       last_arrow_position = Qt;
  704.       last_arrow_string = Qt;
  705.     }
  706.  
  707.       /* If we pause after scrolling, some lines in current_screen
  708.      may be null, so preserve_other_columns won't be able to
  709.      preserve all the vertical-bar separators.  So, avoid using it
  710.      in that case.  */
  711.       if (XFASTINT (w->width) != SCREEN_WIDTH (selected_screen))
  712.     redraw_mode_line = 1;
  713.     }
  714.  
  715.   /* Now text on screen agrees with windows, so
  716.      put info into the windows for partial redisplay to follow */
  717.  
  718.   if (!pause)
  719.     {
  720.       register struct buffer *b = XBUFFER (w->buffer);
  721.  
  722.       blank_end_of_window = 0;
  723.       clip_changed = 0;
  724.       unchanged_modified = BUF_MODIFF (b);
  725.       beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
  726.       end_unchanged = BUF_Z (b) - BUF_GPT (b);
  727.  
  728.       XFASTINT (w->last_point) = BUF_PT (b);
  729.       XFASTINT (w->last_point_x) = SCREEN_CURSOR_X (selected_screen);
  730.       XFASTINT (w->last_point_y) = SCREEN_CURSOR_Y (selected_screen);
  731.  
  732. #ifdef ENERGIZE
  733.       {
  734.         extern void free_zombie_bitmaps ();
  735.         free_zombie_bitmaps ();
  736.       }
  737. #endif
  738.       if (face_cache_invalid)
  739.     flush_face_cache ();
  740.  
  741.       if (all_windows)
  742.     mark_window_display_accurate (XWINDOW (minibuf_window)->prev, 1);
  743.       else
  744.     {
  745.       w->redo_mode_line = Qnil;
  746.       XFASTINT (w->last_modified) = BUF_MODIFF (b);
  747.       w->window_end_valid = Qt;
  748.       last_arrow_position = Voverlay_arrow_position;
  749.       last_arrow_string = Voverlay_arrow_string;
  750.     }
  751.  
  752.       if (redraw_mode_line)
  753.     {
  754.       for (tail = Vscreen_list; CONSP (tail); tail = XCONS (tail)->cdr)
  755.         {
  756.           SCREEN_PTR s;
  757.           if (!SCREENP (XCONS (tail)->car))
  758.         continue;
  759.           s = XSCREEN (XCONS (tail)->car);
  760.           x_format_screen_title (s);
  761.         }
  762.     }
  763.       redraw_mode_line = 0;
  764.       windows_or_buffers_changed = 0;
  765.     }
  766.  
  767.   /* Start SIGIO interrupts coming again.
  768.      Having them off during the code above
  769.      makes it less likely one will discard output,
  770.      but not impossible, since there might be stuff
  771.      in the system buffer here.
  772.      But it is much hairier to try to do anything about that.  */
  773.  
  774.   if (interrupt_input)
  775.     request_sigio ();
  776.  
  777.   in_display--;
  778.  
  779.   update_screen_menubars ();    /* do this when no longer "in_display" */
  780. }
  781.  
  782. /* Redisplay, but leave alone any recent echo area message
  783.    unless another message has been requested in its place.  */
  784.  
  785. void
  786. redisplay_preserving_echo_area ()
  787. {
  788.   if (echo_area_glyphs == 0 && previous_echo_glyphs != 0)
  789.     {
  790.       echo_area_glyphs = previous_echo_glyphs;
  791.       redisplay ();
  792.       echo_area_glyphs = 0;
  793.     }
  794.   else
  795.     redisplay ();
  796. }
  797.  
  798. static void
  799. mark_window_display_accurate (window, flag)
  800.      Lisp_Object window;
  801.      int flag;
  802. {
  803.   struct window *w;
  804.  
  805.   for (;!NILP (window); window = w->next)
  806.     {
  807.       w = XWINDOW (window);
  808.  
  809.       if (!NILP (w->buffer))
  810.     {
  811.       XFASTINT (w->last_modified) =
  812.         flag ? BUF_MODIFF (XBUFFER (w->buffer)) : 0;
  813.       XFASTINT (w->last_facechange) =
  814.         flag ? BUF_FACECHANGE (XBUFFER (w->buffer)) : 0;
  815.     }
  816.       w->window_end_valid = flag ? Qt : Qnil;
  817.       w->redo_mode_line = flag ? Qnil : Qt;
  818.  
  819.       if (!NILP (w->vchild))
  820.     mark_window_display_accurate (w->vchild, flag);
  821.       if (!NILP (w->hchild))
  822.     mark_window_display_accurate (w->hchild, flag);
  823.     }
  824.  
  825.   if (flag)
  826.     {
  827.       last_arrow_position = Voverlay_arrow_position;
  828.       last_arrow_string = Voverlay_arrow_string;
  829.     }
  830.   else
  831.     {
  832.       /* t is unequal to any useful value of Voverlay_arrow_... */
  833.       last_arrow_position = Qt;
  834.       last_arrow_string = Qt;
  835.     }
  836. }
  837.  
  838. static void
  839. redisplay_windows (window)
  840.      Lisp_Object window;
  841. {
  842.   for (; !NILP (window); window = XWINDOW (window)->next)
  843.     redisplay_window (window, 0);
  844. }
  845.  
  846. extern void cancel_my_columns (struct window *);
  847.  
  848. static void
  849. redisplay_window (window, just_this_one)
  850.      Lisp_Object window;
  851.      int just_this_one;
  852. {
  853.   register struct window *w = XWINDOW (window);
  854.   SCREEN_PTR s = XSCREEN (w->screen);
  855.   int height;
  856.   struct buffer *old_buffer;
  857.   register int width = XFASTINT (w->width) - 1
  858.     - (XFASTINT (w->width) + XFASTINT (w->left)
  859.        != SCREEN_WIDTH (XSCREEN (WINDOW_SCREEN (w))));
  860.   register int startp;
  861.   register int hscroll = XINT (w->hscroll);
  862.   struct position pos;
  863.   int opoint;
  864.   int tem;
  865.  
  866.   if (SCREEN_HEIGHT (s) == 0)
  867.     /* abort (); don't do this */
  868.     return;
  869.  
  870.   /* If this is a combination window, do its children; that's all.  */
  871.  
  872.   if (!NILP (w->vchild))
  873.     {
  874.       redisplay_windows (w->vchild);
  875.       return;
  876.     }
  877.   if (!NILP (w->hchild))
  878.     {
  879.       redisplay_windows (w->hchild);
  880.       return;
  881.     }
  882.   if (NILP (w->buffer))
  883.     /* abort ();   and don't do this */
  884.     return;
  885.  
  886.   if (redraw_mode_line)
  887.     w->redo_mode_line = Qt;
  888.  
  889.   /* Otherwise set up data on this window; select its buffer and point value */
  890.  
  891.   height = window_internal_height (w);
  892.  
  893.   if (MINI_WINDOW_P (w)
  894.       && (echo_area_glyphs
  895.       /* Don't display minibuffers except minibuf_window.  */
  896.       || w != XWINDOW (minibuf_window)))
  897.     return;
  898.  
  899.   old_buffer = current_buffer;
  900.   current_buffer = XBUFFER (w->buffer);
  901.  
  902.   /* Count number of windows showing the selected buffer.  */
  903.   if (!just_this_one
  904.       && current_buffer == XBUFFER (XWINDOW (selected_window)->buffer))
  905.     buffer_shared++;
  906.  
  907.   /* Go to window point for redisplay;  POINT will be restored afterwards. */
  908.   opoint = point;
  909.   if (!EQ (window, selected_window))
  910.     {
  911.       register int new_point = marker_position (w->pointm);
  912.  
  913.       /* If narrowing has changed, change the window min and max points
  914.          accordingly. */
  915.       if (new_point < BEGV)
  916.     {
  917.       SET_PT (BEGV);
  918.       Fset_marker (w->pointm, make_number (BEGV), Qnil);
  919.     }
  920.       else if (new_point > ZV)
  921.     {
  922.       SET_PT (ZV);
  923.       Fset_marker (w->pointm, make_number (ZV), Qnil);
  924.     }
  925.       else
  926.     SET_PT (new_point);
  927.     }
  928.  
  929.   /* If window-start is screwed up, choose a new one.  */
  930.   if (XMARKER (w->start)->buffer != current_buffer)
  931.     goto recenter;
  932.  
  933.   /* If window-start is pointing at point-max, that's bad.
  934.      Unless it's also pointing at point-min, that is.
  935.    */
  936.   if (XMARKER (w->start)->bufpos == BUF_ZV (XMARKER (w->start)->buffer) &&
  937.       XMARKER (w->start)->bufpos != BUF_BEG (XMARKER (w->start)->buffer))
  938.     goto recenter;
  939.  
  940.   if (MINI_WINDOW_P (w) && !echo_area_glyphs && previous_echo_glyphs)
  941.     {
  942.       previous_echo_glyphs = 0;
  943.       goto recenter;
  944.     }
  945.  
  946.   startp = marker_position (w->start);
  947.  
  948.   if (startp < BEGV)
  949.     startp = BEGV;
  950.   else if (startp > ZV)
  951.     startp = ZV;
  952.  
  953.   /* Handle case where place to start displaying has been specified */
  954.   if (!NILP (w->force_start))
  955.     {
  956.       w->redo_mode_line = Qt;
  957.       w->force_start = Qnil;
  958.       XFASTINT (w->last_modified) = 0;
  959.       try_window (window, startp);
  960.       if (cursor_vpos < 0)
  961.     {
  962.       /* If point does not appear, move point so it does appear */
  963.       pos = *compute_motion (window,
  964.                  startp, 0,
  965.                 ((EQ (window, minibuf_window) && startp == 1)
  966.                  ? minibuf_prompt_width : 0)
  967.                 +
  968.                 (hscroll ? 1 - hscroll : 0),
  969.                 ZV, height / 2,
  970.                 - (1 << (SHORTBITS - 1)),
  971.                 width, hscroll, pos_tab_offset (w, startp),
  972.                  ((EQ (window, minibuf_window) && startp == 1)
  973.                   ? minibuf_prompt_pix_width
  974.                   : 0),
  975.                  0);
  976.       SET_PT (pos.bufpos);
  977.       if (w != XWINDOW (SCREEN_SELECTED_WINDOW (s)))
  978.         Fset_marker (w->pointm, make_number (point), Qnil);
  979.       else
  980.         {
  981.           /* We want to change point permanently,
  982.          so don't restore the old value.  */
  983.           opoint = point;
  984.           SCREEN_CURSOR_X (s) = max (0, pos.hpos) + XFASTINT (w->left);
  985.           SCREEN_CURSOR_Y (s) = pos.vpos + XFASTINT (w->top);
  986.         }
  987.     }
  988.       goto done;
  989.     }
  990.  
  991.   /* Handle case where text has not changed, only point,
  992.      and it has not moved off the screen.
  993.  
  994.      This code is not used for minibuffer for the sake of
  995.      the case of redisplaying to replace an echo area message;
  996.      since in that case the minibuffer contents per se are usually unchanged.
  997.      This code is of no real use in the minibuffer since
  998.      the handling of tlbufpos, etc., in redisplay handles the same cases. */
  999.  
  1000.   if (XFASTINT (w->last_modified) >= MODIFF
  1001.       && XFASTINT (w->last_facechange) >= FACECHANGE
  1002.       && point >= startp && !clip_changed
  1003.       && (just_this_one || XFASTINT (w->width) == SCREEN_WIDTH (s))
  1004.       /* && !(EQ (window, minibuf_window) && 
  1005.          previous_echo_glyphs && !echo_area_glyphs) */
  1006.       )
  1007.     {
  1008.       pos = *compute_motion (window,
  1009.                  startp, 0,
  1010.                  (hscroll ? 1 - hscroll : 0)
  1011.                  + (MINI_WINDOW_P (w) && startp == 1 ? 
  1012.                                 minibuf_prompt_width : 0),
  1013.                  point, height + 1, 10000, width, hscroll,
  1014.                  pos_tab_offset (w, startp),
  1015.                  (MINI_WINDOW_P (w) && startp == 1
  1016.                   ? minibuf_prompt_pix_width
  1017.                   : 0),
  1018.                  0);
  1019.  
  1020.       if (pos.vpos < height)
  1021.     {
  1022.       /* Ok, point is still on screen */
  1023.       if (w == XWINDOW (SCREEN_SELECTED_WINDOW (s)))
  1024.         {
  1025.           /* These variables are supposed to be origin 1 */
  1026.           SCREEN_CURSOR_X (s) = max (0, pos.hpos) + XFASTINT (w->left);
  1027.           SCREEN_CURSOR_Y (s) = pos.vpos + XFASTINT (w->top);
  1028.         }
  1029.  
  1030. #if 0
  1031. /* This doesn't do the trick, because if a window to the right of
  1032.    this one must be redisplayed, this does nothing because there
  1033.    is nothing in DesiredScreen yet, and then the other window is
  1034.    redisplayed, making likes that are empty in this window's columns. */
  1035.  
  1036.       if (XFASTINT (w->width) != SCREEN_WIDTH (s))
  1037.         preserve_my_columns (w);
  1038. #endif
  1039.  
  1040.       goto done;
  1041.     }
  1042.       /* Don't bother trying redisplay with same start;
  1043.     we already know it will lose */
  1044.     }
  1045.   /* If current starting point was originally the beginning of a line
  1046.      but no longer is, find a new starting point.  */
  1047.   else if (!NILP (w->start_at_line_beg)
  1048.        && XFASTINT (w->last_facechange) >= FACECHANGE
  1049.        && !(startp == BEGV
  1050.         || CHAR_AT (startp - 1) == '\n'))
  1051.     {
  1052.       goto recenter;
  1053.     }
  1054.   else if (just_this_one
  1055.        /* && !(MINI_WINDOW_P (w) && 
  1056.               (echo_area_glyphs || previous_echo_glyphs)) */
  1057.        && point >= startp
  1058.        && XFASTINT (w->last_modified)
  1059.        && ! EQ (w->window_end_valid, Qnil)
  1060.        && !clip_changed
  1061.        && !blank_end_of_window
  1062.        && XFASTINT (w->width) == SCREEN_WIDTH (s)
  1063.        && EQ (last_arrow_position, Voverlay_arrow_position)
  1064.        && EQ (last_arrow_string, Voverlay_arrow_string)
  1065.        && XFASTINT (w->last_facechange) >= FACECHANGE
  1066.        && (tem = try_window_id (SCREEN_SELECTED_WINDOW (s)))
  1067.        && tem != -2)
  1068.     {
  1069.       /* tem > 0 means success.  tem == -1 means choose new start.
  1070.      tem == -2 means try again with same start,
  1071.       and nothing but whitespace follows the changed stuff.
  1072.      tem == 0 means try again with same start.  */
  1073.       if (tem > 0)
  1074.     {
  1075.       mark_short_cut_taken (XSCREEN (w->screen));
  1076.       goto done;
  1077.     }
  1078.     }
  1079.   else if (startp >= BEGV && startp <= ZV
  1080.        /* Avoid starting display at end of buffer! */
  1081.        && (startp <= ZV || startp == BEGV
  1082.            || XFASTINT (w->last_modified) >= MODIFF
  1083.            || XFASTINT (w->last_facechange) >= FACECHANGE))
  1084.     {
  1085.       /* Try to redisplay starting at same place as before */
  1086.       /* If point has not moved off screen, accept the results */
  1087.       try_window (window, startp);
  1088.       if (cursor_vpos >= 0)
  1089.     {
  1090.       goto done;
  1091.     }
  1092.       else
  1093.     cancel_my_columns (w);
  1094.     }
  1095.  
  1096.   XFASTINT (w->last_modified) = 0;
  1097.   w->redo_mode_line = Qt;
  1098.  
  1099.   /* Try to scroll by specified few lines */
  1100.  
  1101.   if (scroll_step && !clip_changed)
  1102.     {
  1103.       if (point > startp)
  1104.     {
  1105.       pos = *vmotion (Z - XFASTINT (w->window_end_pos),
  1106.               scroll_step, width, hscroll, window);
  1107.       if (pos.vpos >= height)
  1108.         goto scroll_fail;
  1109.     }
  1110.  
  1111.       pos = *vmotion (startp, point < startp ? - scroll_step : scroll_step,
  1112.               width, hscroll, window);
  1113.  
  1114.       if (point >= pos.bufpos)
  1115.     {
  1116.       try_window (window, pos.bufpos);
  1117.       if (cursor_vpos >= 0)
  1118.         {
  1119.           mark_short_cut_taken (XSCREEN (w->screen));
  1120.           goto done;
  1121.         }
  1122.       else
  1123.         cancel_my_columns (w);
  1124.     }
  1125.     scroll_fail: ;
  1126.     }
  1127.  
  1128.   /* Finally, just choose place to start which centers point */
  1129.  
  1130. recenter:
  1131.   pos = *vmotion (point, - height / 2, width, hscroll, window);
  1132.   try_window (window, pos.bufpos);
  1133.  
  1134.   startp = marker_position (w->start);
  1135.   w->start_at_line_beg = 
  1136.     (startp == BEGV || CHAR_AT (startp - 1) == '\n') ? Qt : Qnil;
  1137.  
  1138. done:
  1139.   /* If window not full width, must redo its mode line
  1140.      if the window to its side is being redone */
  1141.   if ((!NILP (w->redo_mode_line)
  1142.        || (!just_this_one && width < SCREEN_WIDTH (s) - 1))
  1143.       && height != XFASTINT (w->height))
  1144.     display_mode_line (w);
  1145.  
  1146.   SET_PT (opoint);
  1147.   current_buffer = old_buffer;
  1148. }
  1149.  
  1150. void initialize_first_screen ()
  1151. {
  1152.   if (noninteractive) return;
  1153.   selected_screen->visible = 1;
  1154.   redisplay_windows (selected_screen->root_window);
  1155.   redisplay();
  1156. }
  1157.  
  1158.  
  1159. /* Do full redisplay on one window, starting at position `pos'. */
  1160.  
  1161. static void
  1162. try_window (window, pos)
  1163.      Lisp_Object window;
  1164.      register int pos;
  1165. {
  1166.   register struct window *w = XWINDOW (window);
  1167.   register int height = window_internal_height (w);
  1168.   register int vpos = XFASTINT (w->top);
  1169.   register int last_text_vpos = vpos;
  1170.   int tab_offset = pos_tab_offset (w, pos);
  1171.   SCREEN_PTR s = XSCREEN (w->screen);
  1172.   int width = XFASTINT (w->width) - 1
  1173.     - (XFASTINT (w->width) + XFASTINT (w->left) != SCREEN_WIDTH (s));
  1174.   struct position val;
  1175.  
  1176.   Fset_marker (w->start, make_number (pos), Qnil);
  1177.   cursor_vpos = -1;
  1178.   overlay_arrow_seen = 0;
  1179.   val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
  1180.  
  1181.   while (--height >= 0)
  1182.     {
  1183.       val = *display_text_line (w, pos, vpos, val.hpos, tab_offset);
  1184.       tab_offset += width;
  1185.       if (val.vpos) tab_offset = 0;
  1186.       vpos++;
  1187.       if (pos != val.bufpos)
  1188.     last_text_vpos
  1189.       /* Next line, unless prev line ended in end of buffer with no cr */
  1190.       = vpos - (val.vpos && CHAR_AT (val.bufpos - 1) != '\n');
  1191.       pos = val.bufpos;
  1192.     }
  1193.  
  1194.   /* If last line is continued in middle of character,
  1195.      include the split character in the text considered on the screen */
  1196.   if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
  1197.     pos++;
  1198.  
  1199.   /* If bottom just moved off end of screen, change mode line percentage.  */
  1200.   if (XFASTINT (w->window_end_pos) == 0
  1201.       && Z != pos)
  1202.     w->redo_mode_line = Qt;
  1203.  
  1204.   /* Say where last char on screen will be, once redisplay is finished.  */
  1205.   if (pos > Z)
  1206.     abort ();
  1207.   XFASTINT (w->window_end_pos) = Z - pos;
  1208.   XFASTINT (w->window_end_vpos) = last_text_vpos - XFASTINT (w->top);
  1209.   /* But that is not valid info until redisplay finishes.  */
  1210.   w->window_end_valid = Qnil;
  1211. }
  1212.  
  1213. /* Try to redisplay when buffer is modified locally,
  1214.  computing insert/delete line to preserve text outside
  1215.  the bounds of the changes.
  1216.  Return 1 if successful, 0 if if cannot tell what to do,
  1217.  or -1 to tell caller to find a new window start,
  1218.  or -2 to tell caller to do normal redisplay with same window start.  */
  1219.  
  1220. extern int position_indentation (int);
  1221.  
  1222. static int
  1223. try_window_id (window)
  1224.      Lisp_Object window;
  1225. {
  1226.   int pos;
  1227.   register struct window *w = XWINDOW (window);
  1228.   register int height = window_internal_height (w);
  1229.   SCREEN_PTR s = XSCREEN (w->screen);
  1230.   int top = XFASTINT (w->top);
  1231.   int start = marker_position (w->start);
  1232.   int width = XFASTINT (w->width) - 1
  1233.     - (XFASTINT (w->width) + XFASTINT (w->left) != SCREEN_WIDTH (s));
  1234.   int hscroll = XINT (w->hscroll);
  1235.   int lmargin = hscroll > 0 ? 1 - hscroll : 0;
  1236.   register int vpos;
  1237.   register int i, tem;
  1238.   int last_text_vpos = 0;
  1239.   int stop_vpos;
  1240.  
  1241.   struct position val, bp, ep, xp, pp;
  1242.   int scroll_amount = 0;
  1243.   int delta;
  1244.   int tab_offset, epto;
  1245.  
  1246.   if (GPT - BEG < beg_unchanged)
  1247.     beg_unchanged = GPT - BEG;
  1248.   if (Z - GPT < end_unchanged)
  1249.     end_unchanged = Z - GPT;
  1250.  
  1251.   if (beg_unchanged + 1 < start)
  1252.     return 0;            /* Give up if changes go above top of window */
  1253.  
  1254.   /* Find position before which nothing is changed.  */
  1255.   bp = *compute_motion 
  1256.     (window,
  1257.      start, 0,
  1258.      lmargin + (MINI_WINDOW_P (w) ? minibuf_prompt_width : 0) ,
  1259.      beg_unchanged + 1, 10000, 10000, width, hscroll,
  1260.      pos_tab_offset (w, start),
  1261.      (MINI_WINDOW_P (w) ? minibuf_prompt_pix_width : 0),
  1262.      0);
  1263.   if (bp.vpos >= height)
  1264.     return point < bp.bufpos && !bp.contin;
  1265.  
  1266.   vpos = bp.vpos;
  1267.  
  1268.   /* Find beginning of that screen line.  Must display from there.  */
  1269.   bp = *vmotion (bp.bufpos, 0, width, hscroll, window);
  1270.  
  1271.   pos = bp.bufpos;
  1272.   val.hpos = lmargin;
  1273.   if (pos < start)
  1274.     return -1;
  1275.  
  1276.   /* If about to start displaying at the beginning of a continuation line,
  1277.      really start with previous screen line, in case it was not
  1278.      continued when last redisplayed */
  1279.   if (bp.contin && bp.contin <= beg_unchanged && vpos > 0)
  1280.     {
  1281.       bp = *vmotion (bp.bufpos, -1, width, hscroll, window);
  1282.       --vpos;
  1283.       pos = bp.bufpos;
  1284.     }
  1285.  
  1286.   if (bp.contin && bp.hpos != lmargin)
  1287.     {
  1288.       val.hpos = bp.prevhpos - width + lmargin;
  1289.       pos--;
  1290.     }
  1291.  
  1292.   bp.vpos = vpos;
  1293.  
  1294.   /* Find first visible newline after which no more is changed.  */
  1295.   tem = find_next_newline (Z - max (end_unchanged, Z - ZV), 1);
  1296.   if (FIXNUMP (current_buffer->selective_display)
  1297.       && XINT (current_buffer->selective_display) > 0)
  1298.     while (tem < ZV - 1
  1299.        && (position_indentation (tem)
  1300.            >= XINT (current_buffer->selective_display)))
  1301.       tem = find_next_newline (tem, 1);
  1302.  
  1303.   /* Compute the cursor position after that newline.  */
  1304.   ep = *compute_motion (window,
  1305.             pos, vpos, val.hpos, tem,
  1306.             height, - (1 << (SHORTBITS - 1)),
  1307.             width, hscroll, pos_tab_offset (w, bp.bufpos),
  1308.             0, 0);
  1309.  
  1310.   /* If changes reach past the text available on the screen,
  1311.      just display rest of screen.  */
  1312.   if (ep.bufpos > Z - XFASTINT (w->window_end_pos))
  1313.     stop_vpos = height;
  1314.   else
  1315.     stop_vpos = ep.vpos;
  1316.  
  1317.   /* If no newline before ep, the line ep is on includes some changes
  1318.      that must be displayed.  Make sure we don't stop before it.  */
  1319.   /* Also, if changes reach all the way until ep.bufpos,
  1320.      it is possible that something was deleted after the
  1321.      newline before it, so the following line must be redrawn. */
  1322.   if (stop_vpos == ep.vpos
  1323.       && (ep.bufpos == BEGV
  1324.       || CHAR_AT (ep.bufpos - 1) != '\n'
  1325.       || ep.bufpos == Z - end_unchanged))
  1326.     stop_vpos = ep.vpos + 1;
  1327.  
  1328.   cursor_vpos = -1;
  1329.   overlay_arrow_seen = 0;
  1330.  
  1331.   /* If changes do not reach to bottom of window,
  1332.      figure out how much to scroll the rest of the window */
  1333.   if (stop_vpos < height)
  1334.     {
  1335.       /* Now determine how far up or down the rest of the window has moved */
  1336.       epto = pos_tab_offset (w, ep.bufpos);
  1337.       xp = *compute_motion (window,
  1338.                 ep.bufpos, ep.vpos, ep.hpos,
  1339.                 Z - XFASTINT (w->window_end_pos),
  1340.                 10000, 0, width, hscroll, epto,
  1341.                 ep.pixpos, ep.column);
  1342.       scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
  1343.  
  1344.       /* Is everything on screen below the changes whitespace?
  1345.      If so, no scrolling is really necessary.  */
  1346.       for (i = ep.bufpos; i < xp.bufpos; i++)
  1347.     {
  1348.       tem = CHAR_AT (i);
  1349.       if (tem != ' ' && tem != '\n' && tem != '\t')
  1350.         break;
  1351.     }
  1352.       if (i == xp.bufpos)
  1353.     return -2;
  1354.  
  1355.       XFASTINT (w->window_end_vpos) += scroll_amount;
  1356.  
  1357.       /* Before doing any scrolling, verify that point will be on screen. */
  1358.       if (point > ep.bufpos && !(point <= xp.bufpos && xp.bufpos < height))
  1359.     {
  1360.       if (point <= xp.bufpos)
  1361.         {
  1362.           pp = *compute_motion (window,
  1363.                     ep.bufpos, ep.vpos, ep.hpos,
  1364.                     point, height, - (1 << (SHORTBITS - 1)),
  1365.                     width, hscroll, epto,
  1366.                     ep.pixpos, ep.column);
  1367.         }
  1368.       else
  1369.         {
  1370.           pp = 
  1371.                 *compute_motion 
  1372.                   (window,
  1373.                    xp.bufpos, xp.vpos, xp.hpos,
  1374.                    point, height, - (1 << (SHORTBITS - 1)),
  1375.                    width, hscroll, pos_tab_offset (w, xp.bufpos),
  1376.                    xp.pixpos, xp.column);
  1377.         }
  1378.       if (pp.bufpos < point || pp.vpos == height)
  1379.         return 0;
  1380.       cursor_vpos = pp.vpos + top;
  1381.       cursor_hpos = pp.hpos + XFASTINT (w->left);
  1382.     }
  1383.  
  1384.       if (stop_vpos - scroll_amount >= height
  1385.       || ep.bufpos == xp.bufpos)
  1386.     {
  1387.       if (scroll_amount < 0)
  1388.         stop_vpos -= scroll_amount;
  1389.       scroll_amount = 0;
  1390.       /* In this path, we have altered window_end_vpos
  1391.          and not left it negative.
  1392.          We must make sure that, in case display is preempted
  1393.          before the screen changes to reflect what we do here,
  1394.          further updates will not come to try_window_id
  1395.          and assume the screen and window_end_vpos match.  */
  1396.       blank_end_of_window = 1;
  1397.     }
  1398.       else if (!scroll_amount)
  1399.     {}
  1400.       else if (bp.bufpos == Z - end_unchanged)
  1401.     {
  1402.       /* If reprinting everything is nearly as fast as scrolling,
  1403.          don't bother scrolling.  Can happen if lines are short.  */
  1404.       if (scroll_cost (s, bp.vpos + top - scroll_amount,
  1405.                top + height - max (0, scroll_amount),
  1406.                scroll_amount)
  1407.           > xp.bufpos - bp.bufpos - 20)
  1408.         /* Return "try normal display with same window-start."
  1409.            Too bad we can't prevent further scroll-thinking.  */
  1410.         return -2;
  1411.       /* If pure deletion, scroll up as many lines as possible.
  1412.          In common case of killing a line, this can save the
  1413.          following line from being overwritten by scrolling
  1414.          and therefore having to be redrawn.  */
  1415.       tem = scroll_screen_lines (s, bp.vpos + top - scroll_amount,
  1416.                      top + height - max (0, scroll_amount),
  1417.                      scroll_amount);
  1418.       if (!tem) stop_vpos = height;
  1419.     }
  1420.       else if (scroll_amount)
  1421.     {
  1422.       /* If reprinting everything is nearly as fast as scrolling,
  1423.          don't bother scrolling.  Can happen if lines are short.  */
  1424.       /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
  1425.          overestimate of cost of reprinting, since xp.bufpos
  1426.          would end up below the bottom of the window.  */
  1427.       if (scroll_cost (s, ep.vpos + top - scroll_amount,
  1428.                top + height - max (0, scroll_amount),
  1429.                scroll_amount)
  1430.           > xp.bufpos - ep.bufpos - 20)
  1431.         /* Return "try normal display with same window-start."
  1432.            Too bad we can't prevent further scroll-thinking.  */
  1433.         return -2;
  1434.       tem = scroll_screen_lines (s, ep.vpos + top - scroll_amount,
  1435.                      top + height - max (0, scroll_amount),
  1436.                      scroll_amount);
  1437.       if (!tem) stop_vpos = height;
  1438.     }
  1439.     }
  1440.  
  1441.   /* In any case, do not display past bottom of window */
  1442.   if (stop_vpos >= height)
  1443.     {
  1444.       stop_vpos = height;
  1445.       scroll_amount = 0;
  1446.     }
  1447.  
  1448.   /* Handle case where pos is before w->start --
  1449.      can happen if part of line had been clipped and is not clipped now */
  1450.   if (vpos == 0 && pos < marker_position (w->start))
  1451.     Fset_marker (w->start, make_number (pos), Qnil);
  1452.  
  1453.   /* Redisplay the lines where the text was changed */
  1454.   last_text_vpos = vpos;
  1455.   tab_offset = pos_tab_offset (w, pos);
  1456.   /* If we are starting display in mid-character, correct tab_offset
  1457.      to account for passing the line that that character really starts in.  */
  1458.   if (val.hpos < lmargin)
  1459.     tab_offset += width;
  1460.   while (vpos < stop_vpos)
  1461.     {
  1462.       val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
  1463.       tab_offset += width;
  1464.       if (val.vpos) tab_offset = 0;
  1465.       if (pos != val.bufpos)
  1466.     last_text_vpos
  1467.       /* Next line, unless prev line ended in end of buffer with no cr */
  1468.         = vpos - (val.vpos && CHAR_AT (val.bufpos - 1) != '\n');
  1469.       pos = val.bufpos;
  1470.     }
  1471.  
  1472.   /* There are two cases:
  1473.      1) we have displayed down to the bottom of the window
  1474.      2) we have scrolled lines below stop_vpos by scroll_amount  */
  1475.  
  1476.   if (vpos == height)
  1477.     {
  1478.       /* If last line is continued in middle of character,
  1479.      include the split character in the text considered on the screen */
  1480.       if (val.hpos < lmargin)
  1481.     val.bufpos++;
  1482.       XFASTINT (w->window_end_vpos) = last_text_vpos;
  1483.       if (Z < val.bufpos)
  1484.     abort ();
  1485.       XFASTINT (w->window_end_pos) = Z - val.bufpos;
  1486.     }
  1487.  
  1488.   /* If scrolling made blank lines at window bottom,
  1489.      redisplay to fill those lines */
  1490.   if (scroll_amount < 0)
  1491.     {
  1492.       vpos = xp.vpos;
  1493.       pos = xp.bufpos;
  1494.       val.hpos = lmargin;
  1495.       if (pos == ZV)
  1496.     vpos = height + scroll_amount;
  1497.       else if (xp.contin && xp.hpos != lmargin)
  1498.     {
  1499.       val.hpos = xp.prevhpos - width + lmargin;
  1500.       pos--;
  1501.     }
  1502.  
  1503.       blank_end_of_window = 1;
  1504.       tab_offset = pos_tab_offset (w, pos);
  1505.       /* If we are starting display in mid-character, correct tab_offset
  1506.      to account for passing the line that that character starts in.  */
  1507.       if (val.hpos < lmargin)
  1508.     tab_offset += width;
  1509.  
  1510.       while (vpos < height)
  1511.     {
  1512.       val = 
  1513.             *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
  1514.       tab_offset += width;
  1515.       if (val.vpos) tab_offset = 0;
  1516.       pos = val.bufpos;
  1517.     }
  1518.  
  1519.       /* Here is a case where display_line_text sets cursor_vpos wrong.
  1520.      Make it be fixed up, below.  */
  1521.       if (xp.bufpos == ZV
  1522.       && xp.bufpos == point)
  1523.     cursor_vpos = -1;
  1524.     }
  1525.  
  1526.   /* If bottom just moved off end of screen, change mode line percentage.  */
  1527.   if (XFASTINT (w->window_end_pos) == 0
  1528.       && Z != val.bufpos)
  1529.     w->redo_mode_line = Qt;
  1530.  
  1531.   /* Attempt to adjust end-of-text positions to new bottom line */
  1532.   if (scroll_amount)
  1533.     {
  1534.       delta = height - xp.vpos;
  1535.       if (delta < 0
  1536.       || (delta > 0 && xp.bufpos <= ZV)
  1537.       || (delta == 0 && xp.hpos))
  1538.     {
  1539.       val = *vmotion (Z - XFASTINT (w->window_end_pos),
  1540.               delta, width, hscroll, window);
  1541.       if (Z < val.bufpos)
  1542.         abort ();
  1543.       XFASTINT (w->window_end_pos) = Z - val.bufpos;
  1544.       XFASTINT (w->window_end_vpos) += val.vpos;
  1545.     }
  1546.     }
  1547.  
  1548.   w->window_end_valid = Qnil;
  1549.  
  1550.   /* If point was not in a line that was displayed, find it */
  1551.   if (cursor_vpos < 0)
  1552.     {
  1553.       val = *compute_motion (window,
  1554.                  start, 0, lmargin, point, 10000, 10000,
  1555.                  width, hscroll, pos_tab_offset (w, start),
  1556.                  0, 0);
  1557.       /* Admit failure if point is off screen now */
  1558.       if (val.vpos >= height)
  1559.     {
  1560.       for (vpos = 0; vpos < height; vpos++)
  1561.         cancel_line (vpos + top, s);
  1562.       return 0;
  1563.     }
  1564.       cursor_vpos = val.vpos + top;
  1565.       cursor_hpos = val.hpos + XFASTINT (w->left);
  1566.     }
  1567.  
  1568.   SCREEN_CURSOR_X (s) = max (0, cursor_hpos);
  1569.   SCREEN_CURSOR_Y (s) = cursor_vpos;
  1570.  
  1571. #if 0
  1572.   if (debug_end_pos)
  1573.     {
  1574.       val = *compute_motion (window,
  1575.                  start, 0, lmargin, ZV,
  1576.                  height, - (1 << (SHORTBITS - 1)),
  1577.                  width, hscroll, pos_tab_offset (w, start),
  1578.                  0, 0);
  1579.       if (val.vpos != XFASTINT (w->window_end_vpos))
  1580.     return 0;
  1581.       if (XFASTINT (w->window_end_pos)
  1582.       != Z - val.bufpos)
  1583.     return 0;
  1584.     }
  1585. #endif
  1586.  
  1587.   return 1;
  1588. }
  1589.  
  1590. /* Copy part of the contents of the string FROM into a glyph-vector at S.
  1591.    But don't actually copy the parts that would come in before T.
  1592.    Value is T, advanced past the copied data.
  1593.  
  1594.    Characters in FROM are grouped into units of `sizeof GLYPH' chars;
  1595.    any extra chars at the end of FROM are ignored.  */
  1596.  
  1597. #if 0
  1598. GLYPH *
  1599. copy_rope (t, s, from)
  1600.      register GLYPH *t; /* Copy to here. */
  1601.      register GLYPH *s; /* Starting point. */
  1602.      Lisp_Object from;    /* Data to copy; known to be a string.  */
  1603. {
  1604.   register int n = XSTRING (from)->size / sizeof (GLYPH);
  1605.   register GLYPH *f = (GLYPH *) XSTRING (from)->data;
  1606.  
  1607.   while (n--)
  1608.     {
  1609.       if (t >= s) *t = *f;
  1610.       ++t;
  1611.       ++f;
  1612.     }
  1613.   return t;
  1614. }
  1615. #endif
  1616.  
  1617. static struct glyphs_from_chars char_glyphs;
  1618.  
  1619. static GLYPH measure_glyphs[80];
  1620.  
  1621. #define GLYPH_SET_VALUE(g, v) ((g) = (v))
  1622.  
  1623. static struct glyphs_from_chars *
  1624. glyphs_from_char (screen, c, g, tab_width, ctl_arrow,
  1625.           fp, dp, hscroll, columns, tab_offset, pixel_values)
  1626.      SCREEN_PTR screen;
  1627.      register unsigned int c;
  1628.      GLYPH *g;
  1629.      struct face *fp;
  1630.      register int tab_width, ctl_arrow, hscroll, columns, tab_offset;
  1631.      register struct Lisp_Vector *dp;
  1632.      int pixel_values;
  1633. {
  1634.   register GLYPH *gp = g;
  1635.  
  1636.   char_glyphs.columns = 0;
  1637.   char_glyphs.faceptr = fp;
  1638.   char_glyphs.next_visible = 0;
  1639.   char_glyphs.begin_or_end = 0;
  1640.   char_glyphs.pixel_width = 0;
  1641.   char_glyphs.pixel_height = 0;
  1642.  
  1643.   if (c == '\n')            /* Newline character. */
  1644.     return &char_glyphs;
  1645.  
  1646.   if (((c >= 040 && c < 0177) ||    /* Normal character. */
  1647.        (!EQ (ctl_arrow, Qnil) &&    /* 8-bit display */
  1648.     !EQ (ctl_arrow, Qt) &&
  1649.     (FIXNUMP (ctl_arrow)
  1650.      ? c >= XINT (ctl_arrow)
  1651.      : c >= 0240)))
  1652.       && (dp == 0
  1653.       || NILP (DISP_CHAR_ROPE (dp, c))))
  1654.     {
  1655.       GLYPH_SET_VALUE (*gp++, GLYPH_FROM_CHAR (c == 0240 ? ' ' : c));
  1656.     }
  1657.   else if (c == '\t')        /* Tab character. */
  1658.     {
  1659.       register int j;
  1660.  
  1661.       j = tab_width - ((columns + tab_offset + hscroll - (hscroll > 0))
  1662.                % tab_width);
  1663.       while (j--)
  1664.     GLYPH_SET_VALUE (*gp++, TABGLYPH);
  1665.     }
  1666.   else if (dp != 0 && STRINGP (DISP_CHAR_ROPE (dp, c)))
  1667.     {
  1668.       register int i = XSTRING (DISP_CHAR_ROPE (dp, c))->size / sizeof (GLYPH);
  1669.       GLYPH *data = (GLYPH *) XSTRING (DISP_CHAR_ROPE (dp, c))->data;
  1670.  
  1671.       /* Note that ropes are 16 bit entities stored as double chars */
  1672.       while (i--)
  1673.     GLYPH_SET_VALUE (*gp++, *data++);
  1674.     }
  1675.   else if (c < 0200 && !NILP (ctl_arrow))
  1676.     {
  1677.       if (dp && FIXNUMP (DISP_CTRL_GLYPH (dp)))
  1678.     GLYPH_SET_VALUE (*gp, XINT (DISP_CTRL_GLYPH (dp)));
  1679.       else
  1680.     GLYPH_SET_VALUE (*gp, GLYPH_FROM_CHAR ('^'));
  1681.       gp++;
  1682.       GLYPH_SET_VALUE (*gp, GLYPH_FROM_CHAR (c ^ 0100));
  1683.       gp++;
  1684.     }
  1685.   else
  1686.     {
  1687.       GLYPH_SET_VALUE (*gp, (dp && FIXNUMP (DISP_ESCAPE_GLYPH (dp))
  1688.                  ? XINT (DISP_ESCAPE_GLYPH (dp))
  1689.                  : GLYPH_FROM_CHAR ('\\')));
  1690.       gp++;
  1691.       GLYPH_SET_VALUE (*gp, GLYPH_FROM_CHAR (((c >> 6) + '0')));
  1692.       gp++;
  1693.       GLYPH_SET_VALUE (*gp, GLYPH_FROM_CHAR (((7 & (c >> 3)) + '0')));
  1694.       gp++;
  1695.       GLYPH_SET_VALUE (*gp, GLYPH_FROM_CHAR (((7 & c) + '0')));
  1696.       gp++;
  1697.     }
  1698.  
  1699.   char_glyphs.columns = gp - g;
  1700.  
  1701. #ifdef HAVE_X_WINDOWS
  1702.   if (pixel_values)
  1703.     {
  1704.       register GLYPH *p = g;
  1705.  
  1706.       while (p < gp)
  1707.     {
  1708.       char_glyphs.pixel_width
  1709.         += X_CHAR_WIDTH (fp->font, ((*p == TABGLYPH) ? ' ' : *p));
  1710.       p++;
  1711.     }
  1712.       char_glyphs.pixel_height = FONT_HEIGHT (fp->font);
  1713.     }
  1714. #endif
  1715.  
  1716.   return &char_glyphs;
  1717. }
  1718.  
  1719. /* Cache the state of glyphs_from_bufpos. */
  1720.  
  1721. #define ASCII_BEGIN_GLYPH 99    /* some random number */
  1722. #define ASCII_END_GLYPH 399    /* another random number */
  1723.  
  1724. static struct buffer *last_buffer;
  1725. static struct screen* last_screen;
  1726. static int last_buffer_modiff;
  1727. static int last_buffer_facechange;
  1728. static EXTENT_FRAGMENT last_buffer_extfrag;
  1729. static int last_extfrag_from_pos, last_extfrag_to_pos;
  1730. static struct face *last_extfrag_face;
  1731.  
  1732. static struct glyphs_from_chars displayed_glyphs;
  1733.  
  1734. /* Determine how the character at POS in BUFFER would be displayed on
  1735.    SCREEN.  ONLY_NONCHARS means calculate only glyphs displayed around
  1736.    or instead of the characters, PIXEL_VALUES means return the pixel
  1737.    dimensions of the displayed glyphs.  Return value is a
  1738.    struct glyphs_from_chars pointer. */
  1739.  
  1740. static void
  1741. update_cache (buffer, extfrag)
  1742.      struct buffer* buffer;
  1743.      EXTENT_FRAGMENT extfrag;
  1744. {
  1745.   last_extfrag_from_pos = extfrag->from;
  1746.   last_extfrag_to_pos = extfrag->to;
  1747.   last_buffer_extfrag = extfrag;
  1748. }
  1749.  
  1750. extern int extent_cache_invalid;
  1751.  
  1752. struct glyphs_from_chars *
  1753. glyphs_from_bufpos (screen, buffer, pos, dp, hscroll, columns, tab_offset,
  1754.             direction, only_nonchars)
  1755.      SCREEN_PTR screen;
  1756.      struct buffer *buffer;
  1757.      register int pos, hscroll, columns, tab_offset;
  1758.      register struct Lisp_Vector *dp;
  1759.      int direction, only_nonchars;
  1760. {
  1761.   int pixel_values = SCREEN_IS_X (screen);
  1762.   register EXTENT_FRAGMENT extfrag;
  1763.   register struct face *fp;
  1764.   register UCHAR c;
  1765.   register GLYPH *gp;
  1766.   int ignore_glyphs = 0;
  1767.   /* we will cut our "run" short if we discover that the
  1768.      frag ends with some end glyphs */
  1769.   int frag_has_end_glyphs;
  1770.  
  1771.  retry:
  1772.  
  1773.   gp = measure_glyphs;
  1774.   frag_has_end_glyphs = 0;
  1775.   displayed_glyphs.glyphs = gp;
  1776.  
  1777.   /* Check if we can use our cached values */
  1778.   if (!extent_cache_invalid
  1779.       && buffer == last_buffer
  1780.       && screen == last_screen
  1781.       && BUF_MODIFF (buffer) == last_buffer_modiff
  1782.       && BUF_FACECHANGE (buffer) == last_buffer_facechange)
  1783.     {
  1784.       if (pos >= last_extfrag_from_pos
  1785.       && pos < last_extfrag_to_pos)
  1786.     {
  1787.       extfrag = last_buffer_extfrag;
  1788.       fp = last_extfrag_face;
  1789.       goto cache_used;
  1790.     }
  1791.       else if (pos == last_extfrag_to_pos)
  1792.     {
  1793.       extfrag = buffer_extent_fragment_at (pos, buffer, screen);
  1794.       fp = extfrag->fp;
  1795.       if (!fp)
  1796.         fp = &SCREEN_NORMAL_FACE (screen);
  1797.       last_extfrag_face = fp;
  1798.       update_cache (buffer, extfrag);
  1799.       goto cache_used;
  1800.     }
  1801.     }
  1802.  
  1803.   /* if (!cache_used) */
  1804.     {
  1805.       last_buffer = buffer;
  1806.       last_screen = screen;
  1807.       last_buffer_modiff = BUF_MODIFF (buffer);
  1808.       last_buffer_facechange = BUF_FACECHANGE (buffer);
  1809.       extfrag = buffer_extent_fragment_at (pos, buffer, screen);
  1810.       last_buffer_extfrag = extfrag;
  1811.       last_extfrag_from_pos = extfrag->from;
  1812.       last_extfrag_to_pos = extfrag->to;
  1813.       fp = extfrag->fp;
  1814.       if (!fp)
  1815.     fp = &SCREEN_NORMAL_FACE (screen);
  1816.       last_extfrag_face = fp;
  1817.     }
  1818.  
  1819.  cache_used:
  1820.  
  1821.   displayed_glyphs.faceptr = fp;
  1822.  
  1823. #ifdef HAVE_X_WINDOWS
  1824.   /* Deal with begin/end glyphs.  Should make all this a function. */
  1825.   if (pixel_values)
  1826.     {
  1827.       displayed_glyphs.begin_pixel_width = 0;
  1828.       displayed_glyphs.end_pixel_width = 0;
  1829.       displayed_glyphs.pixel_height = FONT_HEIGHT (fp->font);
  1830.     }
  1831. #endif
  1832.  
  1833. #ifdef LINE_INFO_COLUMN
  1834.   displayed_glyphs.info_column_glyphs = Qnil;
  1835. #endif
  1836.   displayed_glyphs.begin_or_end = 0;
  1837.   displayed_glyphs.n_nonfont = 0;
  1838.   displayed_glyphs.begin_columns = 0;
  1839.   displayed_glyphs.end_columns = 0;
  1840.   displayed_glyphs.begin_class[0] = Qnil;
  1841.   displayed_glyphs.end_class[0] = Qnil;
  1842.  
  1843.   /* Look for begin glyphs */
  1844.   if (extfrag && (pos == extfrag->from) && !ignore_glyphs)
  1845.     {
  1846.       int n_classes = 0;
  1847.       EXTENT *extents_vec = extfrag->extents_stack;
  1848.       EXTENT *extents_vec_bound = extents_vec + extfrag->number_of_extents;
  1849.  
  1850.       while (extents_vec < extents_vec_bound
  1851.          && n_classes < GLYPH_CLASS_VECTOR_SIZE - 1)
  1852.         {
  1853.           EXTENT current_extent = *extents_vec++;
  1854.           GLYPH g = EXTENT_BEGIN_GLYPH_AT (current_extent, pos);
  1855.  
  1856.           if (g)
  1857.             {
  1858. #ifdef LINE_INFO_COLUMN
  1859.               if (screen->display.x->line_info_column_width
  1860.                   && glyph_in_column_p (class))
  1861.                 displayed_glyphs.info_column_glyphs = pix;
  1862.               else
  1863. #endif
  1864. #ifdef HAVE_X_WINDOWS
  1865.                 if (pixel_values)
  1866.                   {
  1867.                     displayed_glyphs.n_nonfont++;
  1868.                     XSET (displayed_glyphs.begin_class[n_classes++],
  1869.                           Lisp_Extent, current_extent);
  1870.                     *gp++ = g;
  1871.                     displayed_glyphs.begin_columns++;
  1872.                     displayed_glyphs.begin_pixel_width +=
  1873.               glyph_to_x_pixmap (g)->width;
  1874.                   }
  1875.                 else
  1876. #endif
  1877.                   *gp++ = ASCII_BEGIN_GLYPH;            
  1878.             }
  1879.         }
  1880.  
  1881.       /* Note begin glyphs */
  1882.       if (n_classes > 0)
  1883.     displayed_glyphs.begin_or_end = 2;
  1884.       displayed_glyphs.begin_class[n_classes] = Qnil;
  1885.     }
  1886.   displayed_glyphs.pixel_width = displayed_glyphs.begin_pixel_width;
  1887.  
  1888.   if (! only_nonchars)
  1889.     {
  1890.       GLYPH *g0 = gp;
  1891.  
  1892.       c = BUF_CHAR_AT (buffer, pos);
  1893.       displayed_glyphs.c = c;
  1894.       if (c == '\n')        /* Newline character. */
  1895.     goto exit;
  1896.  
  1897.       if (((c >= 040 && c < 0177) ||    /* Normal character. */
  1898.        (!EQ (buffer->ctl_arrow, Qnil) &&    /* 8-bit display */
  1899.         !EQ (buffer->ctl_arrow, Qt) &&
  1900.         (FIXNUMP (buffer->ctl_arrow)
  1901.          ? c >= XINT (buffer->ctl_arrow)
  1902.          : c >= 0240)))
  1903.       && (dp == 0
  1904.           || NILP (DISP_CHAR_ROPE (dp, c))))
  1905.     {
  1906.       GLYPH_SET_VALUE (*gp++, GLYPH_FROM_CHAR (c == 0240 ? ' ' : c));
  1907.     }
  1908.       else if (c == '\t')    /* Tab character. */
  1909.     {
  1910.       register int j;
  1911.       int tab_width = 
  1912.             ((XINT (buffer->tab_width) <= 0) || 
  1913.              (XINT (buffer->tab_width) > 20))
  1914.               ? 8:(XINT(buffer->tab_width));
  1915.  
  1916.       j = tab_width - ((columns + tab_offset + hscroll - (hscroll > 0))
  1917.                % tab_width);
  1918.       while (j--)
  1919.         GLYPH_SET_VALUE (*gp++, TABGLYPH);
  1920.     }
  1921.       else if (dp != 0 && STRINGP (DISP_CHAR_ROPE (dp, c)))
  1922.     {
  1923.       register int i = 
  1924.             (XSTRING (DISP_CHAR_ROPE (dp, c))->size) / sizeof (GLYPH);
  1925.       GLYPH *data = (GLYPH *) XSTRING (DISP_CHAR_ROPE (dp, c))->data;
  1926.  
  1927.       /* Note that ropes are 16 bit entities stored as double chars */
  1928.       while (i--)
  1929.         GLYPH_SET_VALUE (*gp++, *data++);
  1930.     }
  1931.       else if (c < 0200 && !NILP (buffer->ctl_arrow))
  1932.     {
  1933.       if (dp && FIXNUMP (DISP_CTRL_GLYPH (dp)))
  1934.         GLYPH_SET_VALUE (*gp, XINT (DISP_CTRL_GLYPH (dp)));
  1935.       else
  1936.         GLYPH_SET_VALUE (*gp, GLYPH_FROM_CHAR ('^'));
  1937.       gp++;
  1938.       GLYPH_SET_VALUE (*gp, GLYPH_FROM_CHAR (c ^ 0100));
  1939.       gp++;
  1940.     }
  1941.       else
  1942.     {
  1943.       GLYPH_SET_VALUE 
  1944.             (*gp, (dp && FIXNUMP (DISP_ESCAPE_GLYPH (dp))
  1945.                    ? XINT (DISP_ESCAPE_GLYPH (dp))
  1946.                    : GLYPH_FROM_CHAR ('\\')));
  1947.       gp++;
  1948.       GLYPH_SET_VALUE (*gp, GLYPH_FROM_CHAR (((c >> 6) + '0')));
  1949.       gp++;
  1950.       GLYPH_SET_VALUE (*gp, GLYPH_FROM_CHAR (((7 & (c >> 3)) + '0')));
  1951.       gp++;
  1952.       GLYPH_SET_VALUE (*gp, GLYPH_FROM_CHAR (((7 & c) + '0')));
  1953.       gp++;
  1954.     }
  1955.  
  1956. #ifdef HAVE_X_WINDOWS
  1957.       if (pixel_values)
  1958.     while (g0 < gp)
  1959.       {
  1960.         displayed_glyphs.pixel_width
  1961.           += X_CHAR_WIDTH (fp->font, ((*g0==TABGLYPH) ? ' ' : *g0));
  1962.         g0++;
  1963.       }
  1964. #endif
  1965.     }
  1966.  
  1967.  exit:
  1968.  
  1969.   /* Look for end glyphs */
  1970.   if (extfrag && !ignore_glyphs)
  1971.     {
  1972.       int n_classes = 0;
  1973.       EXTENT *extents_vec = extfrag->extents_stack;
  1974.       EXTENT *extents_vec_bound = extents_vec + extfrag->number_of_extents;
  1975.       int endpos = extfrag->to - 1;
  1976.       int save_found_glyphs = (pos == endpos);
  1977.  
  1978.       while (extents_vec < extents_vec_bound
  1979.          && n_classes < GLYPH_CLASS_VECTOR_SIZE - 1)
  1980.         {
  1981.           EXTENT current_extent = *extents_vec++;
  1982.  
  1983.           if (current_extent->flags & EF_END_GLYPH)
  1984.             {
  1985.           GLYPH g = EXTENT_END_GLYPH_AT (current_extent, endpos);
  1986.               if (g)
  1987.                 {
  1988.                   frag_has_end_glyphs = 1;
  1989.  
  1990.                   if (save_found_glyphs)
  1991.                     {
  1992. #ifdef HAVE_X_WINDOWS
  1993.                       if (pixel_values)
  1994.                         {
  1995.                           displayed_glyphs.n_nonfont++;
  1996.                           XSET (displayed_glyphs.end_class[n_classes++],
  1997.                                 Lisp_Extent, current_extent);
  1998.                           *gp++ = g;
  1999.                           displayed_glyphs.end_columns++;
  2000.                           displayed_glyphs.end_pixel_width +=
  2001.                 glyph_to_x_pixmap (g)->width;
  2002.                         }
  2003.                       else
  2004. #endif
  2005.                         *gp++ = ASCII_END_GLYPH;
  2006.                     }
  2007.                 }
  2008.             }
  2009.         }
  2010.  
  2011.       /* Note end glyphs */
  2012.       if (n_classes > 0)
  2013.         displayed_glyphs.begin_or_end++;
  2014.       displayed_glyphs.end_class[n_classes] = Qnil;
  2015.  
  2016.       displayed_glyphs.pixel_width += displayed_glyphs.end_pixel_width;
  2017.     }
  2018.  
  2019.   if (columns == 0
  2020.       && displayed_glyphs.pixel_width
  2021.       > (MAX_LINE_WIDTH (screen) - EOL_CURSOR_WIDTH))
  2022.     {
  2023.       /* Just remove all glyphs.  This is wrong, but better than looping */
  2024.       last_extfrag_from_pos = last_extfrag_to_pos = 0; /* Invalidate cache */
  2025.       ignore_glyphs = 1;
  2026.       goto retry;
  2027.     }
  2028.  
  2029.   /* set the displayed_glyphs "run limits" from the extent_fragment info
  2030.      and the selection state
  2031.    */
  2032.   {
  2033.     int run_end = last_extfrag_to_pos - 1;
  2034.  
  2035.     /* don't go to last position of an extent_fragment in the
  2036.        cheapo loop in display_text_line() if there are end glyphs there, 
  2037.        because you will lose */
  2038.     if (frag_has_end_glyphs)
  2039.       run_end -= 1;
  2040.  
  2041.     displayed_glyphs.run_pos_lower = pos;
  2042.     displayed_glyphs.run_pos_upper = run_end;
  2043.   }
  2044.  
  2045.   displayed_glyphs.columns = gp - measure_glyphs;
  2046.   return &displayed_glyphs;
  2047. }
  2048.  
  2049. static int
  2050. new_run (screen, vpos, type, faceptr)
  2051.      SCREEN_PTR screen;
  2052.      int vpos, type;
  2053.      struct face *faceptr;
  2054. {
  2055.   struct screen_glyphs *glyph_lines = SCREEN_DESIRED_GLYPHS (screen);
  2056.   register int run;
  2057.  
  2058.   run = glyph_lines->nruns[vpos];
  2059.   glyph_lines->nruns[vpos]++;
  2060.   glyph_lines->face_list[vpos][run].type = type;
  2061.   glyph_lines->face_list[vpos][run].faceptr = faceptr;
  2062.   glyph_lines->face_list[vpos][run].length = 0;
  2063.   glyph_lines->face_list[vpos][run].w = 0;
  2064.   glyph_lines->face_list[vpos][run].bufp = 0;
  2065. #ifdef HAVE_X_WINDOWS
  2066.   glyph_lines->face_list[vpos][run].pix_length = 0;
  2067. #endif
  2068.  
  2069.   return run;
  2070. }
  2071.  
  2072. static int
  2073. glyph_pixel_width (g, t, f)
  2074.      register GLYPH g;
  2075.      register int t;
  2076.      struct face *f;
  2077. {
  2078.   switch (t)
  2079.     {
  2080.     case font:
  2081.       return X_CHAR_WIDTH (f->font, ((g == TABGLYPH) ? ' ' : g));
  2082.       break;
  2083.  
  2084.     case glyph:
  2085.       return glyph_to_x_pixmap (g)->width;
  2086.       break;
  2087.  
  2088.     case space:
  2089.       return g;
  2090.       break;
  2091.  
  2092.     default:
  2093.       abort ();
  2094.       break;
  2095.     }
  2096. }
  2097.  
  2098.  
  2099. static void
  2100. install_first_runs (s, vpos, pos, w)
  2101.      register SCREEN_PTR s;
  2102.      register int vpos, pos;
  2103.      struct window *w;
  2104. {
  2105.   register struct screen_glyphs *desired_glyphs = SCREEN_DESIRED_GLYPHS (s);
  2106.  
  2107.   desired_glyphs->bufp[vpos] = pos;
  2108.  
  2109.   /* put the window run */
  2110.   desired_glyphs->face_list[vpos][0].type = window;
  2111.   desired_glyphs->face_list[vpos][0].length = 0;
  2112.   desired_glyphs->face_list[vpos][0].faceptr = &SCREEN_NORMAL_FACE (s);
  2113.   desired_glyphs->face_list[vpos][0].w = w;
  2114.   desired_glyphs->face_list[vpos][0].bufp = pos;
  2115.   desired_glyphs->face_list[vpos][0].class = Qnil;
  2116.   desired_glyphs->face_list[vpos][0].begin_p = 0;
  2117.   if (SCREEN_IS_X (s))
  2118.     {
  2119.       desired_glyphs->face_list[vpos][0].pix_length = 0;
  2120.     }
  2121.  
  2122. #ifdef LINE_INFO_COLUMN
  2123.   if (s->display.x->line_info_column_width)
  2124.     {
  2125.       /* put the colum run */
  2126.       desired_glyphs->face_list[vpos][1].type = column_glyph;
  2127.       desired_glyphs->face_list[vpos][1].length = 1;
  2128.       desired_glyphs->face_list[vpos][1].faceptr
  2129.     = &SCREEN_NORMAL_FACE (s);
  2130.       desired_glyphs->face_list[vpos][1].w = 0;
  2131.       desired_glyphs->face_list[vpos][1].bufp = pos;
  2132.       desired_glyphs->face_list[vpos][1].class = Qnil;
  2133.       desired_glyphs->face_list[vpos][1].begin_p = 0;
  2134.       desired_glyphs->nruns[vpos] = 2;
  2135.       desired_glyphs->used[vpos] = 1;
  2136.  
  2137.       if (SCREEN_IS_X (s))
  2138.     {
  2139.       desired_glyphs->face_list[vpos][1].pix_length =
  2140.         s->display.x->line_info_column_width;
  2141.       desired_glyphs->pix_width[vpos] = 
  2142.         s->display.x->line_info_column_width;
  2143.       desired_glyphs->face_list[vpos][1].lineinfo_glyph_index = -1;
  2144.     }
  2145.     }
  2146.   else
  2147. #endif
  2148.     {
  2149.       desired_glyphs->nruns[vpos] = 1;
  2150.       desired_glyphs->used[vpos] = 0;
  2151.     }
  2152. }
  2153.  
  2154. static struct run *
  2155. append_run (s, vpos, type, class, faceptr, begin_p)
  2156.      SCREEN_PTR s;
  2157.      int vpos, type;
  2158.      Lisp_Object class;
  2159.      struct face *faceptr;
  2160.      int begin_p;
  2161. {
  2162.   register int run = SCREEN_DESIRED_GLYPHS (s)->nruns[vpos];
  2163.   struct run *new_run;
  2164.  
  2165.   SCREEN_DESIRED_GLYPHS (s)->nruns[vpos] = run + 1;
  2166.   new_run = &SCREEN_DESIRED_GLYPHS (s)->face_list[vpos][run];
  2167.   new_run->length = 0;
  2168.   new_run->type = type;
  2169.   new_run->class = class;
  2170.   new_run->faceptr = faceptr;
  2171.   new_run->begin_p = begin_p;
  2172.   if (SCREEN_IS_X (s))
  2173.     new_run->pix_length = 0;
  2174.  
  2175.   return new_run;
  2176. }
  2177.  
  2178. #define FONT_ASCENT(f)  FONT_BASE((f))
  2179.  
  2180. static void
  2181. append_glyph (s, vpos, g, type, class, faceptr, begin_p)
  2182.      SCREEN_PTR s;
  2183.      int vpos, type;
  2184.      GLYPH g;
  2185.      Lisp_Object class;
  2186.      struct face *faceptr;
  2187.      int begin_p;
  2188. {
  2189.   register struct screen_glyphs *glyphs = SCREEN_DESIRED_GLYPHS (s);
  2190.   int run = glyphs->nruns[vpos] - 1;
  2191.   int n = glyphs->used[vpos];
  2192.   struct run *this_run = &glyphs->face_list[vpos][run];
  2193.  
  2194.   if ((type != this_run->type) || 
  2195.       (faceptr != this_run->faceptr) ||
  2196.       (!EQ (class, this_run->class)))
  2197.     this_run = append_run (s, vpos, type, class, faceptr, begin_p);
  2198.  
  2199.   this_run->length++;
  2200.   glyphs->used[vpos] = n + 1;
  2201.   glyphs->glyphs[vpos][n] = g;
  2202.   glyphs->glyphs[vpos][n + 1] = NULL_GLYPH;
  2203.  
  2204.   /* Adjust pix bounds */
  2205.   if (SCREEN_IS_X (s))
  2206.     {
  2207.       register int pix_width, pix_height;
  2208.  
  2209.       switch (type)
  2210.     {
  2211.     case font:
  2212.     case glyph:
  2213.       pix_height = max (s->display.x->text_height,
  2214.                 FONT_HEIGHT (faceptr->font));
  2215.       pix_height += x_interline_space;
  2216.       break;
  2217.  
  2218.     case column_glyph:
  2219.     case window:
  2220.     case space:
  2221.     default:
  2222.       pix_height = 0;
  2223.       break;
  2224.     }
  2225.  
  2226.       glyphs->pix_height[vpos]
  2227.     = max (glyphs->pix_height[vpos], pix_height);
  2228.       glyphs->max_ascent[vpos]
  2229.     = max (glyphs->max_ascent[vpos],
  2230.            FONT_ASCENT (faceptr->font));
  2231.       pix_width = glyph_pixel_width (g, type, faceptr);
  2232.       this_run->pix_length += pix_width;
  2233.       glyphs->pix_width[vpos] += pix_width;
  2234.     }
  2235. }
  2236.  
  2237. static void
  2238. remove_glyph (s, vpos)
  2239.      SCREEN_PTR s;
  2240.      register int vpos;
  2241. {
  2242.   register int dead = SCREEN_DESIRED_GLYPHS (s)->used[vpos] - 1;
  2243.   register GLYPH g = SCREEN_DESIRED_GLYPHS (s)->glyphs[vpos][dead];
  2244.   register int run = SCREEN_DESIRED_GLYPHS (s)->nruns[vpos] - 1;
  2245.   register struct run* last_run
  2246.     = &(SCREEN_DESIRED_GLYPHS (s)->face_list[vpos][run]);
  2247.  
  2248.   if (last_run->length == 0)
  2249.     abort ();
  2250.  
  2251.   SCREEN_DESIRED_GLYPHS (s)->used[vpos] = dead;
  2252.   SCREEN_DESIRED_GLYPHS (s)->glyphs[vpos][dead] = NULL_GLYPH;
  2253.   if (SCREEN_IS_X (s))
  2254.     {
  2255.       register int pix_width = glyph_pixel_width (g, last_run->type,
  2256.                           last_run->faceptr);
  2257.  
  2258.       last_run->pix_length -= pix_width;
  2259.       SCREEN_DESIRED_GLYPHS (s)->pix_width[vpos] -= pix_width;
  2260.     }
  2261.  
  2262.   if (last_run->length == 1)
  2263.     SCREEN_DESIRED_GLYPHS (s)->nruns[vpos] = run;
  2264.   else
  2265.     last_run->length--;
  2266. }
  2267.  
  2268. /* Right shift runs starting with RUN to the right by NSLOTS. */
  2269.  
  2270. static void
  2271. right_shift_runs (s, vpos, run, nslots)
  2272.      SCREEN_PTR s;
  2273.      register int vpos, run, nslots;
  2274. {
  2275.   register int nruns = SCREEN_DESIRED_GLYPHS (s)->nruns[vpos];
  2276.   if (run < nruns)
  2277.     {
  2278.       int n_to_move = nruns - run;
  2279.  
  2280.       memcpy (&SCREEN_DESIRED_GLYPHS (s)->face_list[vpos][run + nslots],
  2281.           &SCREEN_DESIRED_GLYPHS (s)->face_list[vpos][run],
  2282.          (n_to_move * sizeof (struct run)));
  2283.     }
  2284.   SCREEN_DESIRED_GLYPHS (s)->nruns[vpos] += nslots;
  2285. }
  2286.  
  2287. #ifdef LINE_INFO_COLUMN
  2288. #define SET_RUN(screen, vpos, run, type, len, face, class, b_or_e, pix) \
  2289.   { \
  2290.      register struct run* this \
  2291.        = &(SCREEN_DESIRED_GLYPHS ((s))->face_list[(vpos)][(run)]); \
  2292.      this->type = (type);              \
  2293.      this->length = (len);             \
  2294.      this->faceptr = (face);           \
  2295.      this->w = 0;                      \
  2296.      this->bufp = 0;                   \
  2297.      this->class = (class);            \
  2298.      this->begin_p = (b_or_e);         \
  2299.      this->pix_length = (pix);         \
  2300.      this->lineinfo_glyph_index = -1;  \
  2301.   }
  2302. #else
  2303. #define SET_RUN(screen, vpos, run, type, len, face, class, b_or_e, pix) \
  2304.   { \
  2305.      register struct run* this \
  2306.        = &(SCREEN_DESIRED_GLYPHS ((s))->face_list[(vpos)][(run)]); \
  2307.      this->type = (type);              \
  2308.      this->length = (len);             \
  2309.      this->faceptr = (face);           \
  2310.      this->w = 0;                      \
  2311.      this->bufp = 0;                   \
  2312.      this->class = (class);            \
  2313.      this->begin_p = (b_or_e);         \
  2314.      this->pix_length = (pix);         \
  2315.   }
  2316. #endif
  2317.  
  2318. static void
  2319. overlay_glyph (s, vpos, g, type, class, faceptr, column, begin_p)
  2320.      register SCREEN_PTR s;
  2321.      int vpos, type, column;
  2322.      GLYPH g;
  2323.      Lisp_Object class;
  2324.      struct face *faceptr;
  2325.      int begin_p;
  2326. {
  2327.   register int run = 0;
  2328.   register int got = SCREEN_DESIRED_GLYPHS (s)->face_list[vpos][run].length;
  2329.   int nruns = SCREEN_DESIRED_GLYPHS (s)->nruns[vpos];
  2330.   register struct run this_run;
  2331.   int old_pix_width, new_pix_width;
  2332.  
  2333.   while (column >= got)
  2334.     {
  2335.       run++;
  2336.       if (run >= nruns)
  2337.     /* abort (); */
  2338.     return;
  2339.       got += SCREEN_DESIRED_GLYPHS (s)->face_list[vpos][run].length;
  2340.     }
  2341.   this_run = SCREEN_DESIRED_GLYPHS (s)->face_list[vpos][run];
  2342.  
  2343.   if (SCREEN_IS_X (s))
  2344.     {
  2345.       GLYPH old_glyph = SCREEN_DESIRED_GLYPHS (s)->glyphs[vpos][column];
  2346.       old_pix_width = glyph_pixel_width (old_glyph, this_run.type,
  2347.                      this_run.faceptr);
  2348.       new_pix_width = glyph_pixel_width (g, type, faceptr);
  2349.     }
  2350.  
  2351.   if (type != this_run.type || !EQ (class, this_run.class)
  2352.       || faceptr != this_run.faceptr)
  2353.     {
  2354.       if (this_run.length == 1)
  2355.     {
  2356.       /* Simply switch the type */
  2357.       SET_RUN (s, vpos, run, type, 1, faceptr, class, begin_p,
  2358.            new_pix_width);
  2359.     }
  2360.       else if (column == got - 1)
  2361.     {
  2362.       /* Last glyph of this run */
  2363.       right_shift_runs (s, vpos, run + 1, 1);
  2364.       SCREEN_DESIRED_GLYPHS (s)->face_list[vpos][run].length--;
  2365.       SCREEN_DESIRED_GLYPHS (s)->face_list[vpos][run].pix_length
  2366.         -= old_pix_width;
  2367.       run++;
  2368.       SET_RUN (s, vpos, run, type, 1, faceptr, class, begin_p,
  2369.            new_pix_width);
  2370.     }
  2371.       else if (column == got - this_run.length)
  2372.     {
  2373.       /* First glyph of this run */
  2374.       right_shift_runs (s, vpos, run, 1);
  2375.       SCREEN_DESIRED_GLYPHS (s)->face_list[vpos][run + 1].length--;
  2376.       SCREEN_DESIRED_GLYPHS (s)->face_list[vpos][run + 1].pix_length
  2377.         -= old_pix_width;
  2378.       SET_RUN (s, vpos, run, type, 1, faceptr, class, begin_p,
  2379.            new_pix_width);
  2380.     }
  2381.       else
  2382.     {
  2383.       /* Middle of the run */
  2384.       /* Let's just lose for the moment, as we shouldn't arrive here. */
  2385.       /* abort (); */
  2386.       return;
  2387.     }
  2388.     }
  2389.  
  2390.   SCREEN_DESIRED_GLYPHS (s)->glyphs[vpos][column] = g;
  2391.   SCREEN_DESIRED_GLYPHS (s)->pix_width[vpos]
  2392.     += (new_pix_width - old_pix_width);
  2393. }
  2394.  
  2395.  
  2396. #ifdef HAVE_X_WINDOWS
  2397. #define LEFT_OF_MARGIN \
  2398. (SCREEN_IS_X (s) \
  2399.  ? (desired_glyphs->pix_width[vpos] < MAX_LINE_WIDTH (s)) \
  2400.  : (p1 < endp))
  2401. #else
  2402. #define LEFT_OF_MARGIN (p1 < endp)
  2403. #endif /* HAVE_X_WINDOWS */
  2404.  
  2405. /* Display one line of window w, starting at position START in W's buffer.
  2406.    Display starting at horizontal position HPOS, which is normally zero
  2407.    or negative.  A negative value causes output up to hpos = 0 to be discarded.
  2408.    This is done for negative hscroll, or when this is a continuation line
  2409.    and the continuation occurred in the middle of a multi-column character.
  2410.  
  2411.    TABOFFSET is an offset for ostensible hpos, used in tab stop calculations.
  2412.  
  2413.    Display on position VPOS on the screen.  (origin 0).
  2414.  
  2415.    Returns a STRUCT POSITION giving character to start next line with
  2416.    and where to display it, including a zero or negative hpos.
  2417.    The vpos field is not really a vpos; it is 1 unless the line is continued */
  2418.  
  2419. static struct position val_display_text_line;
  2420.  
  2421.  
  2422. #ifdef LINE_INFO_COLUMN
  2423. #define TABOFFSET ((s->display.x->line_info_column_width > 0) \
  2424.            ? taboffset - 1 : taboffset)
  2425. #define INFO_COLUMN_ADJUST(col) ((col) + 1)
  2426. #else
  2427. #define TABOFFSET 0
  2428. #define INFO_COLUMN_ADJUST(col) ((col))
  2429. #endif
  2430.  
  2431. /* Construct a display line from buffer text. */
  2432. static struct position *
  2433. display_text_line (w, start, vpos, hpos, taboffset)
  2434.      struct window *w;
  2435.      int start;
  2436.      int vpos;
  2437.      int hpos;
  2438.      int taboffset;
  2439. {
  2440.   struct position val;
  2441.  
  2442.   SCREEN_PTR s = XSCREEN (w->screen);
  2443.   register struct screen_glyphs *desired_glyphs = SCREEN_DESIRED_GLYPHS (s);
  2444.   struct buffer *buffer = XBUFFER (w->buffer);
  2445.   register struct Lisp_Vector *dp = window_display_table (w);
  2446.  
  2447.   int hscroll = XINT (w->hscroll);
  2448.   int truncate = hscroll
  2449.     || (truncate_partial_width_windows
  2450.     && XFASTINT (w->width) < SCREEN_WIDTH (s))
  2451.       || !NILP (current_buffer->truncate_lines);
  2452.  
  2453. #if 0
  2454.   int selectively_truncated = 0;
  2455. #endif
  2456.  
  2457.   int start_column = XINT (w->left);
  2458.   int leftmost_column = start_column;
  2459.   int skip_columns = (hpos < 0 ? - hpos : 0);
  2460.   int window_column_width = XFASTINT (w->width)
  2461.     - (leftmost_column + XFASTINT (w->width) != SCREEN_WIDTH (s));
  2462.  
  2463.   GLYPH continuer = GLYPH_FROM_CHAR ('\\');
  2464.   GLYPH truncator = GLYPH_FROM_CHAR ('$');
  2465. #if 0
  2466.   GLYPH struncator = GLYPH_FROM_CHAR ('.');
  2467. #endif
  2468.  
  2469.   int buffer_position, pause, column, cpos, last_position;
  2470.   struct face *this_face = &SCREEN_NORMAL_FACE (s);
  2471.  
  2472.   register int line_width = 0;    /* Current total width of the line. */
  2473.   /* max_width is widest possible line terminated by newline */
  2474.   register int max_width;
  2475.   /* max_truncated_or_continued_width is widest possible line that is
  2476.      truncated or continued */
  2477.   int max_truncated_or_continued_width;
  2478.   register int this_width;    /* Width of last run of glyphs we examined. */
  2479.   int position_before_continuer = 0;
  2480.   int column_before_continuer;
  2481.   int cpos_before_continuer;
  2482.  
  2483.   /* Get the display line. */
  2484.   get_display_line (s, vpos, start_column);
  2485.  
  2486.   if (MINI_WINDOW_P (w) && start == 1 && vpos == XFASTINT (w->top))
  2487.     {
  2488.       int minibuf_len = (STRINGP (Vminibuf_prompt)
  2489.                          ? XSTRING (Vminibuf_prompt)->size
  2490.                          : 0);
  2491.       install_first_runs (s, vpos, 1 - minibuf_len, w);
  2492.       if (minibuf_len > 0)
  2493.     start_column = display_string (w, vpos,
  2494.                                        XSTRING (Vminibuf_prompt)->data, hpos,
  2495.                        (!truncate ? continuer : truncator),
  2496.                        -1, -1, &SCREEN_NORMAL_FACE (s),
  2497.                        &minibuf_prompt_pix_width);
  2498.       minibuf_prompt_width = start_column - leftmost_column;
  2499.       SCREEN_DESIRED_GLYPHS (s)->bufp[vpos] = 1 - minibuf_len;
  2500.       if (SCREEN_IS_TERMCAP (s))
  2501.     line_width = minibuf_prompt_width;
  2502.     }
  2503.   else
  2504.     /* Set up the buffer pointer, window, etc.  */
  2505.     install_first_runs (s, vpos, start, w);
  2506.  
  2507.   if (SCREEN_IS_TERMCAP (s))
  2508.     {
  2509.       max_width = leftmost_column + window_column_width - 1;
  2510.       max_truncated_or_continued_width = max_width;
  2511.       line_width += start_column;
  2512.     }
  2513.   else
  2514.     {
  2515.       max_width = MAX_LINE_WIDTH (s) - EOL_CURSOR_WIDTH;
  2516.       max_truncated_or_continued_width = (truncate ? TRUNCATE_WIDTH (s)
  2517.                       : CONTINUE_WIDTH (s));
  2518.       line_width = desired_glyphs->pix_width[vpos];
  2519.     }
  2520.  
  2521.   column = 0;    /* Start counting for tabs at 0, even when wrapped */
  2522.   cpos = 0;    /* Columns including glyphs */
  2523.   last_position = buffer_position = start;
  2524.   pause = ZV;
  2525.  
  2526.   /* Deal with the overlay arrow. */
  2527.   if (MARKERP (Voverlay_arrow_position)
  2528.       && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
  2529.       && start == marker_position (Voverlay_arrow_position)
  2530.       && STRINGP (Voverlay_arrow_string)
  2531.       && ! overlay_arrow_seen)
  2532.     {
  2533.       if (SCREEN_IS_TERMCAP (s))
  2534.     {
  2535.       unsigned char *arrow = XSTRING (Voverlay_arrow_string)->data;
  2536.       int arrow_len = XSTRING (Voverlay_arrow_string)->size;
  2537.  
  2538.       while (arrow_len--)
  2539.         {
  2540.           append_glyph (s, vpos, GLYPH_FROM_CHAR (*arrow++), font, Qnil,
  2541.                 this_face, 0);
  2542.           /* column++; */ /* The overlay arrow doesn't count in tabs */
  2543.           cpos++;
  2544.         }
  2545.     }
  2546.       else
  2547.     {
  2548.       append_glyph (s, vpos, builtin_rarrow_pixmap.glyph_id,
  2549.             glyph, Qnil, this_face, 0);
  2550.       /* column++; */ /* The overlay arrow doesn't count in tabs */
  2551.       cpos++;
  2552.     }
  2553.       overlay_arrow_seen = 1;
  2554.     }
  2555.  
  2556.   
  2557.  
  2558.   {
  2559.     register struct glyphs_from_chars *glyphs = 0;
  2560.     register int reusing_glyphs = 0;
  2561.     int screen_is_x = SCREEN_IS_X (s);
  2562.     XFontStruct *this_font = 0;
  2563.     int default_char_width = 0;
  2564.  
  2565.     while (1)
  2566.       {
  2567.         register int n_things;
  2568.         register GLYPH *gp;
  2569.         int save_column_before_continuer, save_cpos_before_continuer;
  2570.         UCHAR c;
  2571.  
  2572.         save_column_before_continuer = column;
  2573.         save_cpos_before_continuer = cpos;
  2574.  
  2575.         if (buffer_position == pause)
  2576.           {
  2577.             /* End of visible text */
  2578.             break;
  2579.           }
  2580.  
  2581.     c = BUF_CHAR_AT (buffer, buffer_position);
  2582.  
  2583. #if 0    /* This doesn't work */
  2584.     /* Handle the ^M variety of selective display... */
  2585.     if (c == 015 &&
  2586.         !NILP (buffer->selective_display) &&
  2587.         !FIXNUMP (buffer->selective_display))
  2588.       {
  2589.         while (buffer_position < BUF_ZV (buffer) &&
  2590.            BUF_CHAR_AT (buffer, buffer_position) != '\n')
  2591.           buffer_position++;
  2592.         c = '\n';
  2593.         selectively_truncated = 1;
  2594.       }
  2595.     else if (c == '\n' &&
  2596.          FIXNUMP (buffer->selective_display))
  2597.       {
  2598.         /* #### */
  2599.       }
  2600. #endif
  2601.  
  2602.         if (glyphs && 
  2603.             (buffer_position <= glyphs->run_pos_upper) &&
  2604.             (buffer_position >= glyphs->run_pos_lower) &&
  2605.             (((((c >= 040) && (c < 0177)) ||            /* Normal character. */
  2606.            (!EQ (buffer->ctl_arrow, Qnil) &&    /* 8-bit display */
  2607.         !EQ (buffer->ctl_arrow, Qt) &&
  2608.         (FIXNUMP (buffer->ctl_arrow)
  2609.          ? c > XINT (buffer->ctl_arrow)
  2610.          : c >= 0240))) &&            /* Normal + 8th bit */
  2611.               (dp == 0 || NILP (DISP_CHAR_ROPE (dp, c)))) ||
  2612.              /* newline */
  2613.              (c == '\n') ||
  2614.              /* or a tab */
  2615.              (c == '\t')))
  2616.           {
  2617.             /* inside a run, so update the glyphs structure "by hand" */
  2618.  
  2619.             reusing_glyphs = 1;
  2620.  
  2621.         if (c == 0240) c = ' ';  /* print `nobreakspace' as space */
  2622.  
  2623. #ifdef LINE_INFO_COLUMN
  2624.             glyphs->info_column_glyphs = Qnil;
  2625. #endif
  2626.             glyphs->begin_or_end = 0;
  2627.             glyphs->n_nonfont = 0;
  2628.             glyphs->glyphs = measure_glyphs;
  2629.             glyphs->c = c;
  2630.  
  2631.             if (c == '\n')
  2632.               {
  2633.                 glyphs->pixel_width = 0;
  2634.                 glyphs->columns = 0;
  2635. #ifdef HAVE_X_WINDOWS
  2636.                 displayed_glyphs.pixel_width = 0;
  2637. #endif
  2638.               }
  2639.             else if (c == '\t')
  2640.               {
  2641.                 int tab_width = ((XINT (buffer->tab_width) <= 0
  2642.                                   && XINT (buffer->tab_width) > 20)
  2643.                                  ? 8
  2644.                                  : XINT (buffer->tab_width));
  2645.                 register int j = 
  2646.                   tab_width - ((column + TABOFFSET + hscroll - (hscroll > 0))
  2647.                                % tab_width);
  2648.  
  2649.                 glyphs->columns = j;
  2650. #ifdef HAVE_X_WINDOWS
  2651.                 if (screen_is_x)
  2652.                   {
  2653.                     register int pix_width;
  2654.  
  2655.                     if (this_font->per_char)
  2656.                       pix_width = x_char_info(this_font, ' ')->width;
  2657.                     else
  2658.                       pix_width = default_char_width;
  2659.                     displayed_glyphs.pixel_width = j * pix_width;
  2660.                   }
  2661. #endif
  2662.                 while (j--)
  2663.                   GLYPH_SET_VALUE (measure_glyphs[j], TABGLYPH);
  2664.               }
  2665.             else
  2666.               {
  2667.                 GLYPH_SET_VALUE (*measure_glyphs, GLYPH_FROM_CHAR (c));
  2668. #ifdef HAVE_X_WINDOWS
  2669.                 if (screen_is_x)
  2670.                   {
  2671.                     register int pix_width;
  2672.  
  2673.                     if (this_font->per_char)
  2674.                       pix_width = x_char_info(this_font, c)->width;
  2675.                     else
  2676.                       pix_width = default_char_width;
  2677.                     displayed_glyphs.pixel_width = pix_width;
  2678.                   }
  2679. #endif
  2680.                 glyphs->columns = 1;
  2681.               }
  2682.           }
  2683.         else
  2684.           {
  2685.             glyphs = glyphs_from_bufpos (s, buffer, buffer_position,
  2686.                                          dp, hscroll, column, TABOFFSET,
  2687.                                          0, 0);
  2688.             reusing_glyphs = 0;
  2689.  
  2690.             if (this_font != glyphs->faceptr->font)
  2691.               {
  2692.                 this_font = glyphs->faceptr->font;
  2693.                 if (this_font->per_char)
  2694.                   {
  2695.                     int default_index = this_font->default_char;
  2696.                     int limit_index = 
  2697.                       this_font->max_char_or_byte2 - 
  2698.                         this_font->min_char_or_byte2;
  2699.  
  2700.                     if ((default_index >= 0) && 
  2701.                         (default_index < limit_index))
  2702.                       default_char_width = 
  2703.                         this_font->per_char[default_index].width;
  2704.                     else
  2705.                       default_char_width = 
  2706.                         this_font->per_char[0].width;
  2707.                   }
  2708.                 else
  2709.                   default_char_width = 
  2710.                     this_font->min_bounds.width;
  2711.               }
  2712.           }
  2713.  
  2714. #ifdef LINE_INFO_COLUMN
  2715.         if (glyphs->info_column_glyphs != Qnil
  2716.             && desired_glyphs->nruns[vpos] >= 2
  2717.             && desired_glyphs->face_list[vpos][1].type == column_glyph)
  2718.           {
  2719.             desired_glyphs->face_list[vpos][1].class = glyphs->begin_class[0];
  2720.             if (FIXNUMP (glyphs->info_column_glyphs))
  2721.               desired_glyphs->face_list[vpos][1].lineinfo_glyph_index
  2722.                 = XINT (glyphs->info_column_glyphs);
  2723.             else
  2724.               desired_glyphs->face_list[vpos][1].lineinfo_glyph_index = -1;
  2725.           }
  2726. #endif
  2727.  
  2728.         n_things = glyphs->columns;
  2729.         this_face = glyphs->faceptr;
  2730.         if (SCREEN_IS_TERMCAP (s))
  2731.           this_width = n_things;
  2732.         else
  2733.           this_width = glyphs->pixel_width;
  2734.  
  2735.         /* Handle skip columns */
  2736.         gp = glyphs->glyphs;
  2737.         if (skip_columns)
  2738.           {
  2739.             if (skip_columns >= n_things)
  2740.               skip_columns -= n_things;
  2741.             else
  2742.               while (skip_columns > 0 && n_things > 0)
  2743.                 {
  2744.                   skip_columns--;
  2745.                   n_things--;
  2746.                   if (screen_is_x)
  2747.                     this_width -= glyph_pixel_width (*gp, font, this_face);
  2748.                   gp++;
  2749.                 }
  2750.           }
  2751.  
  2752.         /* Handle the usual case, appending glyphs. */
  2753.         line_width += this_width;
  2754.  
  2755.         /* Insert any begin glyphs */
  2756.         if (glyphs->begin_or_end > 1)
  2757.           {
  2758.             register int i;
  2759.             for (i = 0; ! NILP (glyphs->begin_class[i]); i++)
  2760.               {
  2761.                 append_glyph (s, vpos, *gp++, glyph,
  2762.                               glyphs->begin_class[i], this_face, 1);
  2763.                 /* column++; */ /* Begin glyphs don't count in tabs */
  2764.                 cpos++;
  2765.               }
  2766.           }
  2767.  
  2768.         /* We have to set cursor_vpos and cursor_hpos after all the
  2769.            begin glyphs and before any regular glyphs, unless we're at EOL */
  2770.         if (buffer_position == point && glyphs->c != '\n')
  2771.           {
  2772.             cursor_vpos = vpos;
  2773.             /* cpos now points to the first regular character */
  2774.             cursor_hpos = INFO_COLUMN_ADJUST (cpos);
  2775.           }
  2776.  
  2777.         n_things -= glyphs->n_nonfont;
  2778.         
  2779.         if (reusing_glyphs)
  2780.           {
  2781.             register struct screen_glyphs *glyphs = SCREEN_DESIRED_GLYPHS (s);
  2782.         struct run *this_run =
  2783.           &(glyphs->face_list[vpos][glyphs->nruns[vpos] - 1]);
  2784.             int n = glyphs->used[vpos];
  2785.       
  2786.             glyphs->used[vpos] = n + n_things;
  2787.             glyphs->glyphs[vpos][n + n_things] = NULL_GLYPH;
  2788.         this_run->length += n_things;
  2789.         column += n_things;
  2790.         cpos += n_things;
  2791.  
  2792.             while (n_things--)
  2793.               {
  2794.                 GLYPH g = *gp++;
  2795.                 glyphs->glyphs[vpos][n++] = g;
  2796.               }
  2797. #ifdef HAVE_X_WINDOWS
  2798.             if (screen_is_x)                  
  2799.               {
  2800.                 register int pix_width = displayed_glyphs.pixel_width;
  2801.                 this_run->pix_length += pix_width;
  2802.                 glyphs->pix_width[vpos] += pix_width;
  2803.               }
  2804. #endif
  2805.           }
  2806.         else
  2807.           while (n_things--)
  2808.             {
  2809.               append_glyph (s, vpos, *gp++, font, Qnil, this_face, 0);
  2810.               column++;
  2811.               cpos++;
  2812.             }
  2813.  
  2814.         /* Append any end glyphs */
  2815.         if (glyphs->begin_or_end & 0x1)
  2816.           {
  2817.             register int i;
  2818.             for (i = 0; ! NILP (glyphs->end_class[i]); i++)
  2819.               {
  2820.                 append_glyph (s, vpos, *gp++, glyph,
  2821.                               glyphs->end_class[i], this_face, 0);
  2822.                 /* column++; */ /* End glyphs don't count in tabs */
  2823.                 cpos++;
  2824.               }
  2825.           }
  2826.  
  2827.         if (glyphs->c == '\n' && line_width <= max_truncated_or_continued_width)
  2828.           {
  2829.             /* End of line */
  2830.             if (buffer_position == point)
  2831.               {
  2832.                 cursor_vpos = vpos;
  2833.                 /* cpos now points to the first regular character */
  2834.                 cursor_hpos = INFO_COLUMN_ADJUST (cpos);
  2835.               }
  2836.             break;
  2837.           }
  2838.  
  2839.         last_position = buffer_position;
  2840.         /* This should deal with a single character line that
  2841.            will wrap, since that will lose here, causing infinite
  2842.            wrapping */
  2843.         if ((!position_before_continuer)
  2844.             && (line_width > max_truncated_or_continued_width))
  2845.           {
  2846.             position_before_continuer = buffer_position;
  2847.             column_before_continuer = save_column_before_continuer;
  2848.             cpos_before_continuer = save_cpos_before_continuer;
  2849.           }
  2850.         if (line_width > max_truncated_or_continued_width)
  2851.           break;
  2852.         buffer_position++;
  2853.       }
  2854.   }
  2855.  
  2856.   val.hpos = - XINT (w->hscroll);
  2857.   if (val.hpos)
  2858.     val.hpos++;
  2859.   val.vpos = 1;
  2860.  
  2861.   if (buffer_position == ZV)                     /* Quit due to EOT */
  2862.     {
  2863.       /* Don't miss point if it's after [visble] buffer text. */
  2864.       if (cursor_vpos < 0 && start <= point && point <= buffer_position)
  2865.     {
  2866.       cursor_vpos = vpos;
  2867.       cursor_hpos = INFO_COLUMN_ADJUST (cpos);
  2868.     }
  2869.       last_position = buffer_position;
  2870.     }
  2871.   else if (line_width > max_truncated_or_continued_width)
  2872.     {                /* Exceeded screen width */
  2873.       if (truncate)
  2874.     {
  2875.       if (SCREEN_IS_X (s))
  2876.         {
  2877.           while (cpos > cpos_before_continuer)
  2878.         {
  2879.           remove_glyph (s, vpos);
  2880.           cpos--;
  2881.         }
  2882.           buffer_position = position_before_continuer;
  2883.           column = column_before_continuer;
  2884.           /* Fix this to add space to align on right margin */
  2885.           append_glyph (s, vpos, builtin_truncator_pixmap.glyph_id,
  2886.                 glyph, Qnil, this_face, 0);
  2887.         }
  2888.       else
  2889.         append_glyph (s, vpos, truncator, font, Qnil, this_face, 0);
  2890.  
  2891.       {
  2892.         int newline_not_found;
  2893.         last_position = 
  2894.               scan_buffer ('\n', buffer_position, 1, &newline_not_found);
  2895.         if (point >= buffer_position
  2896.         && (point < last_position
  2897.             || (point == last_position
  2898.             && newline_not_found)))
  2899.           {
  2900.         cursor_vpos = vpos;
  2901.         cursor_hpos = INFO_COLUMN_ADJUST (cpos + 1);
  2902.           }
  2903.         val.hpos = (hscroll ? 1 - hscroll : 0);
  2904.       }
  2905.     }
  2906.       else
  2907.     {
  2908.       if (SCREEN_IS_X (s))
  2909.         {
  2910.           while (cpos > cpos_before_continuer)
  2911.         {
  2912.           remove_glyph (s, vpos);
  2913.           cpos--;
  2914.         }
  2915.           /* Maybe should add space to align on right margin */
  2916.           append_glyph 
  2917.                 (s, vpos, builtin_continuer_pixmap.glyph_id,
  2918.          glyph, Qnil, this_face, 0);
  2919.         }
  2920.       else
  2921.         append_glyph (s, vpos, continuer, font, Qnil, this_face, 0);
  2922.  
  2923.       val.vpos = 0;
  2924.       last_position = position_before_continuer;
  2925.     }
  2926.     }
  2927. #if 0    /* this doesn't work */
  2928.   else if (selectively_truncated &&
  2929.        !NILP (current_buffer->selective_display_ellipses))
  2930.     {
  2931.       int i;
  2932.       if (column < window_column_width)
  2933.     append_glyph (s, vpos, struncator, font, Qnil, this_face, 0),
  2934.     column++;
  2935.       if (column < window_column_width)
  2936.     append_glyph (s, vpos, struncator, font, Qnil, this_face, 0),
  2937.     column++;
  2938.       if (column < window_column_width)
  2939.     append_glyph (s, vpos, struncator, font, Qnil, this_face, 0),
  2940.     column++;
  2941.       last_position = buffer_position + 1;
  2942.     }
  2943. #endif
  2944.   else                /* New line. */
  2945.     {
  2946.       last_position = buffer_position + 1;
  2947.     }
  2948.  
  2949.   /* If selected window and point is on this line,
  2950.      set global cursor X and Y position.  Also, set this_line_*
  2951.      variables for the one-line optimization. */
  2952.   if (cursor_vpos == vpos)
  2953.     {
  2954.       cursor_hpos += start_column;
  2955.       if (cursor_hpos < 0)
  2956.     cursor_hpos = INFO_COLUMN_ADJUST (0);
  2957.       if (SCREEN_IS_TERMCAP (s)
  2958.       && cursor_hpos >= leftmost_column + window_column_width)
  2959.     cursor_hpos = window_column_width - 1;
  2960.  
  2961.       if (w == XWINDOW (selected_window))
  2962.     {
  2963.       SCREEN_CURSOR_Y (s) = cursor_vpos;
  2964.       SCREEN_CURSOR_X (s) = cursor_hpos;
  2965.  
  2966.       /* Line is not continued and did not start in middle of character */
  2967.       if (! skip_columns && val.vpos)
  2968.         {
  2969.           this_line_bufpos = start;
  2970.           this_line_buffer = current_buffer;
  2971.           this_line_vpos = cursor_vpos;
  2972.           this_line_start_hpos = hpos;
  2973.           this_line_endpos = Z - last_position;
  2974.         }
  2975.       else
  2976.         this_line_bufpos = 0;
  2977.     }
  2978.     }
  2979.  
  2980.   /* If hscroll and line not empty, insert truncation-at-left marker */
  2981.   if (hscroll && desired_glyphs->used[vpos] > 0)
  2982.     overlay_glyph (s, vpos, builtin_continuer_pixmap.glyph_id,
  2983.            font, Qnil, this_face, INFO_COLUMN_ADJUST (0), 0);
  2984.   
  2985.   /* If w is a vertical window, but not rightmost, insert spaces, then
  2986.      insert the '|' separator. */
  2987.   if (SCREEN_IS_TERMCAP (s)
  2988.       && (leftmost_column + window_column_width != SCREEN_WIDTH (s)))
  2989.     {
  2990.       while (desired_glyphs->used[vpos] <= max_truncated_or_continued_width)
  2991.     append_glyph (s, vpos, SPACEGLYPH, font, Qnil, this_face, 0);
  2992.       append_glyph (s, vpos, GLYPH_FROM_CHAR ('|'), font, Qnil, this_face, 0);
  2993.     }
  2994.  
  2995.   desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
  2996.  
  2997.   if (SCREEN_IS_X (s) && desired_glyphs->pix_height[vpos] == 0)
  2998.     {                /* Set the height of an empty line */
  2999.       desired_glyphs->pix_height[vpos] = s->display.x->text_height;
  3000.       desired_glyphs->max_ascent[vpos]
  3001.     = FONT_ASCENT (SCREEN_NORMAL_FACE (s).font);
  3002.     }
  3003.  
  3004.   val.bufpos = last_position;
  3005.   val_display_text_line = val;
  3006.  
  3007.   return &val_display_text_line;
  3008. }
  3009.  
  3010. #ifdef LINE_INFO_COLUMN
  3011. void 
  3012. add_in_column_glyph (desired_glyphs, vpos, element, class)
  3013.      struct screen_glyphs *desired_glyphs;
  3014.      int vpos;
  3015.      Lisp_Object element;
  3016.      Lisp_Object class;
  3017. {
  3018.   /* the column glyph is always the second glyph in the line */
  3019.   struct run* r;
  3020.   if (desired_glyphs->nruns [vpos] >= 2)
  3021.     {
  3022.       r = &desired_glyphs->face_list[vpos][1];
  3023.       if (r->type == column_glyph)
  3024.     {
  3025.       r->class = class;
  3026.       r->lineinfo_glyph_index = (FIXNUMP (element) ?
  3027.                      XINT(element) : -1);
  3028.     }
  3029.     }
  3030. }
  3031. #endif
  3032.  
  3033.  
  3034.  
  3035. static char *
  3036. decode_mode_spec (w, c, maxwidth)
  3037.      struct window *w;
  3038.      register char c;
  3039.      register int maxwidth;
  3040. {
  3041.   Lisp_Object obj = Qnil;
  3042.   SCREEN_PTR scr = XSCREEN (WINDOW_SCREEN (w));
  3043.   char *decode_mode_spec_buf
  3044.     = (char *) SCREEN_TEMP_GLYPHS (scr)->total_contents;
  3045.   struct buffer* buffer = XBUFFER (w->buffer);
  3046.  
  3047.   if (maxwidth > SCREEN_WIDTH (scr))
  3048.     maxwidth = SCREEN_WIDTH (scr);
  3049.  
  3050.   switch (c)
  3051.     {
  3052.     case 'b': 
  3053.       obj = buffer->name;
  3054.       break;
  3055.  
  3056.     case 'f': 
  3057.       obj = buffer->filename;
  3058.       break;
  3059.  
  3060.     case 'm': 
  3061.       obj = buffer->mode_name;
  3062.       break;
  3063.  
  3064.     case 'n':
  3065.       if (BUF_BEGV (buffer) > BUF_BEG (buffer)
  3066.       || BUF_ZV (buffer) < BUF_Z (buffer))
  3067.     return " Narrow";
  3068.       break;
  3069.  
  3070.     case '*':
  3071.       return (!NILP (buffer->read_only)
  3072.           ? "%"
  3073.           : ((MODIFF > buffer->save_modified) ? "*" : "-"));
  3074.  
  3075.     case 's':
  3076.       /* status of process */
  3077. #ifdef subprocesses
  3078.       obj = Fget_buffer_process (w->buffer);
  3079.       if (NILP (obj))
  3080.     return "no process";
  3081.       obj = Fsymbol_name (Fprocess_status (obj));
  3082.       break;
  3083. #else
  3084.       return "no processes";
  3085. #endif /* subprocesses */
  3086.  
  3087.     case 'S':
  3088.       /* name of screen */
  3089. #ifdef MULTI_SCREEN
  3090.       obj = scr->name;
  3091. #endif
  3092.       break;
  3093.  
  3094.     case 'p':
  3095.       {
  3096.     int pos = marker_position (w->start);
  3097.     int total = BUF_ZV (buffer) - BUF_BEGV (buffer);
  3098.  
  3099.     if (XFASTINT (w->window_end_pos) <= BUF_Z (buffer) - BUF_ZV (buffer))
  3100.       {
  3101.         if (pos <= BUF_BEGV (buffer))
  3102.           return "All";
  3103.         else
  3104.           return "Bottom";
  3105.       }
  3106.     else if (pos <= BUF_BEGV (buffer))
  3107.       return "Top";
  3108.     else
  3109.       {
  3110.         total = ((pos - BUF_BEGV (buffer)) * 100 + total - 1) / total;
  3111.         /* We can't normally display a 3-digit number,
  3112.            so get us a 2-digit number that is close.  */
  3113.         if (total == 100)
  3114.           total = 99;
  3115.         sprintf (decode_mode_spec_buf, "%2d%%", total);
  3116.         return decode_mode_spec_buf;
  3117.       }
  3118.       }
  3119.  
  3120.     case '%':
  3121.       return "%";
  3122.  
  3123.     case '[': 
  3124.       {
  3125.     int i;
  3126.     char *p;
  3127.  
  3128.     if (command_loop_level > 5)
  3129.       return "[[[... ";
  3130.     p = decode_mode_spec_buf;
  3131.     for (i = 0; i < command_loop_level; i++)
  3132.       *p++ = '[';
  3133.     *p = 0;
  3134.     return decode_mode_spec_buf;
  3135.       }
  3136.  
  3137.     case ']': 
  3138.       {
  3139.     int i;
  3140.     char *p;
  3141.  
  3142.     if (command_loop_level > 5)
  3143.       return " ...]]]";
  3144.     p = decode_mode_spec_buf;
  3145.     for (i = 0; i < command_loop_level; i++)
  3146.       *p++ = ']';
  3147.     *p = 0;
  3148.     return decode_mode_spec_buf;
  3149.       }
  3150.  
  3151.     case '-':
  3152.       {
  3153.     static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
  3154.     register char *p;
  3155.     register int i;
  3156.     
  3157.     if (maxwidth < sizeof (lots_of_dashes))
  3158.       return lots_of_dashes;
  3159.     else
  3160.       {
  3161.         for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
  3162.           *p++ = '-';
  3163.         *p = '\0';
  3164.       }
  3165.     return decode_mode_spec_buf;
  3166.       }
  3167.     }
  3168.  
  3169.   if (STRINGP (obj))
  3170.     return (char *) XSTRING (obj)->data;
  3171.   else
  3172.     return "";
  3173. }
  3174.  
  3175. /* Display NULL-terminated STRING on one line of window W, starting at HPOS.
  3176.    Display at position VPOS.  Caller should have done get_display_line.
  3177.  
  3178.    TRUNCATE is GLYPH to display at end if truncated.  Zero for none.
  3179.  
  3180.    MINCOL is the first column ok to end at.  (Pad with spaces to this col.)
  3181.    MAXCOL is the last column ok to end at.  Truncate here.
  3182.      -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
  3183.    Both count from the left edge of the screen, as does HPOS.
  3184.    The right edge of W is an implicit maximum.
  3185.    If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
  3186.  
  3187.    Display is performed using FACE, unless that is 0, then the screen
  3188.    default face is used.  Each new string on the smae line consitutes a
  3189.    different run.
  3190.  
  3191.    Returns ending hpos on the line.
  3192.  
  3193.    If PIX_WIDTH_PTR is nonzero, it is a pointer to an int variable that
  3194.    will be set to the pixel width of the string.   */
  3195.  
  3196. static int
  3197. display_string (w, vpos, string, hpos, truncate,
  3198.         mincol, maxcol, this_face, pix_width_ptr)
  3199.      struct window *w;
  3200.      unsigned char *string;
  3201.      int vpos, hpos;
  3202.      GLYPH truncate;
  3203.      int mincol, maxcol;
  3204.      struct face *this_face;
  3205.      int *pix_width_ptr;
  3206. {
  3207.   int hscroll = XINT (w->hscroll);
  3208.   int tab_width = XINT (current_buffer->tab_width);
  3209.   SCREEN_PTR s = XSCREEN (WINDOW_SCREEN (w));
  3210.   struct screen_glyphs *desired_glyphs = SCREEN_DESIRED_GLYPHS (s);
  3211.   register struct Lisp_Vector *dp = 0;
  3212.   register int end;
  3213.   register GLYPH *g
  3214.     = (GLYPH *) alloca (strlen ((char *) string) * sizeof (GLYPH));
  3215.   int pix_width = 0;
  3216.  
  3217.   if (tab_width <= 0 || tab_width > 20) tab_width = 8;
  3218.  
  3219.   /* Select a face */
  3220.   if (! this_face)
  3221.     this_face = &SCREEN_NORMAL_FACE (s);
  3222.  
  3223. #ifdef HAVE_X_WINDOWS
  3224.   if (SCREEN_IS_X (s))
  3225.     {
  3226.       if (this_face->font == (XFontStruct*)(~0) || !this_face->font)
  3227.     abort ();
  3228.       if (desired_glyphs->used[vpos] == 0)
  3229.     desired_glyphs->pix_height[vpos] = FONT_HEIGHT (this_face->font);
  3230.       else
  3231.     desired_glyphs->pix_height[vpos]
  3232.       = max (FONT_HEIGHT (this_face->font),
  3233.                  desired_glyphs->pix_height[vpos]);
  3234.       desired_glyphs->max_ascent[vpos]
  3235.     = max (FONT_ASCENT (this_face->font), 
  3236.                desired_glyphs->max_ascent[vpos]);
  3237.     }
  3238. #endif
  3239.  
  3240.   /* Use the standard display table, not the window's display table.
  3241.      We don't want the mode line in rot13.  */
  3242.   if (VECTORP (Vstandard_display_table)
  3243.       && XVECTOR (Vstandard_display_table)->size == DISP_TABLE_SIZE)
  3244.     dp = XVECTOR (Vstandard_display_table);
  3245.  
  3246.   while (desired_glyphs->used[vpos] < hpos)
  3247.     append_glyph (s, vpos, SPACEGLYPH, font, Qnil, this_face, 0);
  3248.  
  3249.   end = XINT (w->left) + XINT (w->width);
  3250.   if (maxcol > 0)
  3251.     end = min (maxcol, end);
  3252.  
  3253.   while (*string)
  3254.     {
  3255.       register struct glyphs_from_chars *glyphs;
  3256.       register int this_len;
  3257.       register GLYPH *gp = g;
  3258.  
  3259.       glyphs = glyphs_from_char (s, *string, g, tab_width,
  3260.                  buffer_defaults.ctl_arrow,
  3261.                  this_face, dp, hscroll, hpos, 0,
  3262.                  SCREEN_IS_X (s));
  3263.       this_len = glyphs->columns;
  3264.       pix_width += glyphs->pixel_width;
  3265.       if (hpos + this_len > end)
  3266.     break;
  3267.  
  3268.       gp = g;
  3269.       hpos += this_len;
  3270.       while (this_len--)
  3271.     {
  3272.       if (hpos < desired_glyphs->used[vpos])
  3273.         overlay_glyph (s, vpos, *gp, font, Qnil, this_face, hpos, 0);
  3274.       else
  3275.         append_glyph (s, vpos, *gp, font, Qnil, this_face, 0);
  3276.       gp++;
  3277.     }
  3278.  
  3279.       string++;
  3280.     }
  3281.  
  3282.   /* Should adjust pix_width here ... */
  3283.  
  3284.   if (*string && truncate)
  3285.     {
  3286.       if (SCREEN_IS_TERMCAP (s))
  3287.     append_glyph (s, vpos, builtin_truncator_pixmap.glyph_id,
  3288.               glyph, Qnil, this_face, 0);
  3289.       else
  3290.     {
  3291.       while (desired_glyphs->pix_width[vpos]
  3292.          > MAX_LINE_WIDTH (s) - builtin_truncator_pixmap.width)
  3293.         remove_glyph (s, vpos);
  3294.       append_glyph (s, vpos, builtin_truncator_pixmap.glyph_id,
  3295.             glyph, Qnil, this_face, 0);
  3296.     }
  3297.     }
  3298.   else if (mincol > 0)
  3299.     {
  3300.       int window_edge = XFASTINT (w->width) + XFASTINT (w->left);
  3301.  
  3302.       while (desired_glyphs->used[vpos] < min (mincol, window_edge))
  3303.     append_glyph (s, vpos, SPACEGLYPH, font, Qnil, this_face, 0);
  3304.  
  3305.       if (window_edge != SCREEN_WIDTH (s))
  3306.     overlay_glyph (s, vpos, GLYPH_FROM_CHAR ('|'), font, Qnil,
  3307.                this_face, window_edge - 1, 0);
  3308.     }
  3309.  
  3310.   if (pix_width_ptr)
  3311.     *pix_width_ptr = pix_width;
  3312.  
  3313.   return desired_glyphs->used[vpos];
  3314. }
  3315.  
  3316.  
  3317. /* Contribute ELT to the mode line for window W.
  3318.    How it translates into text depends on its data type.
  3319.  
  3320.    VPOS is the position of the mode line being displayed.
  3321.  
  3322.    HPOS is the position (absolute on screen) where this element's text
  3323.    should start.  The output is truncated automatically at the right
  3324.    edge of window W.
  3325.  
  3326.    DEPTH is the depth in recursion.  It is used to prevent
  3327.    infinite recursion here.
  3328.  
  3329.    MINENDCOL is the hpos before which the element may not end.
  3330.    The element is padded at the right with spaces if nec
  3331.    to reach this column.
  3332.  
  3333.    MAXENDCOL is the hpos past which this element may not extend.
  3334.    If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
  3335.    (This is necessary to make nested padding and truncation work.)
  3336.  
  3337.    Returns the hpos of the end of the text generated by ELT.
  3338.    The next element will receive that value as its HPOS arg,
  3339.    so as to concatenate the elements.
  3340.  
  3341.    FN is a function which takes the same args as display_string:
  3342.    (w, vpos, string, hpos, truncate, mincol, maxcol, this_face, pix_width_ptr)
  3343.    It is used to actually output the data.
  3344.  */
  3345.  
  3346. static int
  3347. display_mode_element (fn, w, vpos, hpos, depth, minendcol, maxendcol, elt)
  3348.      int (*fn) ();
  3349.      struct window *w;
  3350.      register int vpos, hpos;
  3351.      int depth;
  3352.      int minendcol;
  3353.      register int maxendcol;
  3354.      register Lisp_Object elt;
  3355. {
  3356.   register SCREEN_PTR s = XSCREEN (WINDOW_SCREEN (w));
  3357.  
  3358.   /* check that the MODELINE_FACE is legal. */
  3359.   if (SCREEN_IS_X (s) &&
  3360.       (SCREEN_MODELINE_FACE (s).font == (XFontStruct*)(~0) ||
  3361.       !SCREEN_MODELINE_FACE (s).font))
  3362.     abort ();
  3363.  
  3364.  tail_recurse:
  3365.   if (depth > 10)
  3366.     goto invalid;
  3367.  
  3368.   depth++;
  3369.  
  3370. #ifdef SWITCH_ENUM_BUG
  3371.   switch ((int) XTYPE (elt))
  3372. #else
  3373.   switch (XTYPE (elt))
  3374. #endif
  3375.     {
  3376.     case Lisp_String:
  3377.       {
  3378.     /* A string: output it and check for %-constructs within it.  */
  3379.     register unsigned char c;
  3380.     register unsigned char *this = XSTRING (elt)->data;
  3381.  
  3382.     while (hpos < maxendcol && *this)
  3383.       {
  3384.         unsigned char *last = this;
  3385.         while ((c = *this++) != '\0' && c != '%')
  3386.           ;
  3387.         if (this - 1 != last)
  3388.           {
  3389.         register int lim = --this - last + hpos;
  3390.         hpos = fn (w, vpos, last, hpos, 0, hpos,
  3391.                min (lim, maxendcol),
  3392.                &SCREEN_MODELINE_FACE (s), 0);
  3393.           }
  3394.         else /* c == '%' */
  3395.           {
  3396.         register int spec_width = 0;
  3397.  
  3398.         /* We can't allow -ve args due to the "%-" construct */
  3399.         /* Argument specifies minwidth but not maxwidth
  3400.            (maxwidth can be specified by
  3401.              (<negative-number> . <stuff>) mode-line elements) */
  3402.  
  3403.         while ((c = *this++) >= '0' && c <= '9')
  3404.           {
  3405.             spec_width = spec_width * 10 + (c - '0');
  3406.           }
  3407.  
  3408.         spec_width += hpos;
  3409.         if (spec_width > maxendcol)
  3410.           spec_width = maxendcol;
  3411.  
  3412.         if (c == 'M')
  3413.           hpos = display_mode_element (fn, w, vpos, hpos, depth,
  3414.                            spec_width, maxendcol,
  3415.                            Vglobal_mode_string);
  3416.         else if (c != 0)
  3417.           hpos = fn (w, vpos,
  3418.                  decode_mode_spec (w, c, maxendcol - hpos),
  3419.                  hpos, 0, spec_width, maxendcol,
  3420.                  &SCREEN_MODELINE_FACE (s), 0);
  3421.           }
  3422.       }
  3423.       }
  3424.       break;
  3425.  
  3426.     case Lisp_Symbol:
  3427.       /* A symbol: process the value of the symbol recursively
  3428.      as if it appeared here directly.  Avoid error if symbol void.
  3429.      Special case: if value of symbol is a string, output the string
  3430.      literally.  */
  3431.       {
  3432.     register Lisp_Object tem;
  3433.     tem = Fboundp (elt);
  3434.     if (!NILP (tem))
  3435.       {
  3436.         tem = Fsymbol_value (elt);
  3437.         /* If value is a string, output that string literally:
  3438.            don't check for % within it.  */
  3439.         if (STRINGP (tem))
  3440.           hpos = fn (w, vpos, XSTRING (tem)->data,
  3441.              hpos, 0, minendcol, maxendcol,
  3442.              &SCREEN_MODELINE_FACE (s), 0);
  3443.         /* Give up right away for nil or t.  */
  3444.         else if (!EQ (tem, elt))
  3445.           { elt = tem; goto tail_recurse; }
  3446.       }
  3447.       }
  3448.       break;
  3449.  
  3450.     case Lisp_Cons:
  3451.       {
  3452.     register Lisp_Object car, tem;
  3453.  
  3454.     /* A cons cell: three distinct cases.
  3455.        If first element is a string or a cons, process all the elements
  3456.        and effectively concatenate them.
  3457.        If first element is a negative number, truncate displaying cdr to
  3458.        at most that many characters.  If positive, pad (with spaces)
  3459.        to at least that many characters.
  3460.        If first element is a symbol, process the cadr or caddr recursively
  3461.        according to whether the symbol's value is non-nil or nil.  */
  3462.     car = XCONS (elt)->car;
  3463.     if (SYMBOLP (car))
  3464.       {
  3465.         tem = Fboundp (car);
  3466.         elt = XCONS (elt)->cdr;
  3467.         if (!CONSP (elt))
  3468.           goto invalid;
  3469.         /* elt is now the cdr, and we know it is a cons cell.
  3470.            Use its car if CAR has a non-nil value.  */
  3471.         if (!NILP (tem))
  3472.           {
  3473.         tem = Fsymbol_value (car);
  3474.         if (!NILP (tem))
  3475.           { elt = XCONS (elt)->car; goto tail_recurse; }
  3476.           }
  3477.         /* Symbol's value is nil (or symbol is unbound)
  3478.            Get the cddr of the original list
  3479.            and if possible find the caddr and use that.  */
  3480.         elt = XCONS (elt)->cdr;
  3481.         if (NILP (elt))
  3482.           break;
  3483.         else if (!CONSP (elt))
  3484.           goto invalid;
  3485.         elt = XCONS (elt)->car;
  3486.         goto tail_recurse;
  3487.       }
  3488.     else if (FIXNUMP (car))
  3489.       {
  3490.         register int lim = XINT (car);
  3491.         elt = XCONS (elt)->cdr;
  3492.         if (lim < 0)
  3493.           /* Negative int means reduce maximum width.
  3494.          DO NOT change MINENDCOL here!
  3495.          (20 -10 . foo) should truncate foo to 10 col
  3496.          and then pad to 20.  */
  3497.           maxendcol = min (maxendcol, hpos - lim);
  3498.         else if (lim > 0)
  3499.           {
  3500.         /* Padding specified.  Don't let it be more than
  3501.            current maximum.  */
  3502.         lim += hpos;
  3503.         if (lim > maxendcol)
  3504.           lim = maxendcol;
  3505.         /* If that's more padding than already wanted, queue it.
  3506.            But don't reduce padding already specified even if
  3507.            that is beyond the current truncation point.  */
  3508.         if (lim > minendcol)
  3509.           minendcol = lim;
  3510.           }
  3511.         goto tail_recurse;
  3512.       }
  3513.     else if (STRINGP (car) || CONSP (car))
  3514.       {
  3515.         register int limit = 50;
  3516.         /* LIMIT is to protect against circular lists.  */
  3517.         while (CONSP (elt) && --limit > 0
  3518.            && hpos < maxendcol)
  3519.           {
  3520.         hpos = display_mode_element (fn, w, vpos, hpos, depth,
  3521.                          hpos, maxendcol,
  3522.                          XCONS (elt)->car);
  3523.         elt = XCONS (elt)->cdr;
  3524.           }
  3525.       }
  3526.       }
  3527.       break;
  3528.  
  3529.     default:
  3530.     invalid:
  3531.       return (fn (w, vpos, "*invalid*", hpos, 0,
  3532.           minendcol, maxendcol, &SCREEN_MODELINE_FACE (s), 0));
  3533.     }
  3534.  
  3535.   if (minendcol > hpos)
  3536.     hpos = fn (w, vpos, "", hpos, 0, minendcol, -1,
  3537.            &SCREEN_MODELINE_FACE (s), 0);
  3538.  
  3539.   return hpos;
  3540. }
  3541.  
  3542.  
  3543. /* Lucid addition */
  3544.  
  3545. Lisp_Object Vscreen_title_format, Vscreen_icon_title_format;
  3546. Lisp_Object Qscreen_title_format, Qscreen_icon_title_format;
  3547.  
  3548. #ifdef HAVE_X_WINDOWS
  3549.  
  3550. static char screen_title_buffer [1024];
  3551. static int screen_title_buffer_index;
  3552.  
  3553. static int
  3554. screen_title_display_string (w, vpos, string, hpos, truncate,
  3555.                  mincol, maxcol, this_face, pix_width_ptr)
  3556.      struct window *w;
  3557.      unsigned char *string;
  3558.      int vpos, hpos;
  3559.      GLYPH truncate;
  3560.      int mincol, maxcol;
  3561.      struct face *this_face;
  3562.      int *pix_width_ptr;
  3563. {
  3564.   int end = sizeof (screen_title_buffer) - 1;
  3565.   while (screen_title_buffer_index < hpos)
  3566.     screen_title_buffer [screen_title_buffer_index++] = ' ';
  3567.   if (maxcol > 0)
  3568.     end = min (maxcol, end);
  3569.   for (; *string && screen_title_buffer_index < end;
  3570.        *string++, screen_title_buffer_index++)
  3571.     screen_title_buffer [screen_title_buffer_index] = *string;
  3572.   while (screen_title_buffer_index < mincol)
  3573.     screen_title_buffer [screen_title_buffer_index++] = ' ';
  3574.   screen_title_buffer [screen_title_buffer_index] = '\0';
  3575.   return screen_title_buffer_index;
  3576. }
  3577.  
  3578. extern void x_set_title_from_char (struct screen *, char *);
  3579. extern void x_set_icon_name_from_char (struct screen *, char *);
  3580.  
  3581. void
  3582. x_format_screen_title (s)
  3583.      struct screen *s;
  3584. {
  3585.   struct window *w = XWINDOW (s->selected_window);
  3586.   Lisp_Object title_format;
  3587.   Lisp_Object icon_format;
  3588.   Lisp_Object obuf = Fcurrent_buffer ();
  3589.  
  3590.   /* do not change for the minibuffer */
  3591.   if (MINI_WINDOW_P (w))
  3592.     return;
  3593.   /* protect from deleted buffers ! */
  3594.   if (NILP (XBUFFER (w->buffer)->name))
  3595.     return;
  3596.   /* evaluate screen-title-format and screen-icon-title-format in the
  3597.      buffer of the selected window of the screen in question.
  3598.    */
  3599.   Fset_buffer (w->buffer);
  3600.   title_format = Fsymbol_value (Qscreen_title_format);
  3601.   icon_format = Fsymbol_value (Qscreen_icon_title_format);
  3602.   Fset_buffer (obuf);
  3603.   screen_title_buffer_index = 0;
  3604.   display_mode_element (screen_title_display_string, w, 0, 0, 0, 0,
  3605.             sizeof (screen_title_buffer) -1,
  3606.             title_format);
  3607.   x_set_title_from_char (s, screen_title_buffer);
  3608.  
  3609.   if (!(EQ (icon_format, title_format) ||
  3610.     EQ (icon_format, Qscreen_title_format)))
  3611.     {
  3612.       screen_title_buffer_index = 0;
  3613.       display_mode_element (screen_title_display_string, w, 0, 0, 0, 0,
  3614.                 sizeof (screen_title_buffer) -1,
  3615.                 icon_format);
  3616.     }
  3617.   x_set_icon_name_from_char (s, screen_title_buffer);
  3618. }
  3619.  
  3620. #endif /* HAVE_X_WINDOWS */
  3621.  
  3622.  
  3623. /* Display the mode line for window w */
  3624.  
  3625. static void
  3626. display_mode_line (w)
  3627.      struct window *w;
  3628. {
  3629.   register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
  3630.   register int left = XFASTINT (w->left);
  3631.   register int right = XFASTINT (w->width) + left;
  3632.   register SCREEN_PTR s = XSCREEN (WINDOW_SCREEN (w));
  3633.  
  3634.   if (vpos < 0)
  3635.     return;
  3636.  
  3637.   get_display_line (s, vpos, left);
  3638.   /* indicate this line is a mode line */
  3639.   SCREEN_DESIRED_GLYPHS (s)->bufp[vpos] = 0;
  3640.   display_mode_element (display_string, w, vpos, left, 0, right, right,
  3641.             current_buffer->mode_line_format);
  3642.  
  3643. #ifdef HAVE_X_WINDOWS
  3644.   if (SCREEN_IS_X (s))
  3645.       {
  3646.     if (s->desired_glyphs->pix_width[vpos]
  3647.         < (PIXEL_WIDTH (s) - (2 * s->display.x->internal_border_width)))
  3648.       {
  3649.         int pix_len;
  3650.         int nruns = s->desired_glyphs->nruns[vpos];
  3651.         struct face *last_face
  3652.           = s->desired_glyphs->face_list[vpos][nruns - 1].faceptr;
  3653.  
  3654.         pix_len = 
  3655.               (PIXEL_WIDTH (s) - 
  3656.                (2 * s->display.x->internal_border_width)) - 
  3657.                  s->desired_glyphs->pix_width[vpos];
  3658.         append_glyph (s, vpos, (GLYPH) pix_len, space, Qnil, last_face, 0);
  3659.       }
  3660.       }
  3661. #endif
  3662. }
  3663.  
  3664.  
  3665. static struct glyph_dimensions dimensions;
  3666.  
  3667. struct glyph_dimensions *
  3668. get_glyph_dimensions (s, hpos, vpos)
  3669.      SCREEN_PTR s;
  3670.      int hpos, vpos;
  3671. {
  3672.   register struct screen_glyphs *current_screen = SCREEN_CURRENT_GLYPHS (s);
  3673.   register struct run *face_list;
  3674.   register int run_len, this_run, pix_len;
  3675.   XFontStruct *default_font = SCREEN_NORMAL_FACE (s).font;
  3676.  
  3677.   if (!current_screen->enable[vpos] || s->garbaged)
  3678.     return 0;
  3679.  
  3680.   dimensions.top_left_y = current_screen->top_left_y[vpos];
  3681.   dimensions.top_left_x = current_screen->top_left_x[vpos];
  3682.   dimensions.height = current_screen->pix_height[vpos] - x_interline_space;
  3683.  
  3684.   /* Handle empty lines */
  3685.   if (current_screen->used[vpos] == 0
  3686.       || current_screen->enable[vpos] == 0
  3687.       || hpos >= current_screen->used[vpos])
  3688.     {
  3689.       if (current_screen->used[vpos] == 0 || current_screen->enable[vpos] == 0)
  3690.     {
  3691.       dimensions.run = 0;
  3692.     }
  3693.       else
  3694.     {
  3695.       dimensions.top_left_x += current_screen->pix_width[vpos];
  3696.       dimensions.run = current_screen->nruns[vpos] - 1;
  3697.     }
  3698.       dimensions.width = X_DEFAULT_WIDTH (default_font);
  3699.       if (dimensions.top_left_y + dimensions.height
  3700.       >= s->display.x->pixel_height)
  3701.     return &dimensions;
  3702.  
  3703.       return &dimensions;
  3704.     }
  3705.  
  3706.   face_list = current_screen->face_list[vpos];
  3707.   this_run = run_len = pix_len = 0;
  3708.  
  3709.   /* Advance to the correct run. */
  3710.   while (hpos >= run_len + face_list[this_run].length)
  3711.     {
  3712.       run_len += face_list[this_run].length;
  3713.       dimensions.top_left_x += face_list[this_run].pix_length;
  3714.       this_run++;
  3715.     }
  3716.   dimensions.run = this_run;
  3717.  
  3718.   switch (face_list[this_run].type)
  3719.     {
  3720.     case font:
  3721.       {
  3722.     register unsigned char this_ch = (current_screen->glyphs[vpos][hpos]
  3723.                       & 0377);
  3724.     int len = hpos - run_len;
  3725.     register int l = len;
  3726.     char *buf;
  3727.     register char *cp;
  3728.     register GLYPH *gp = ¤t_screen->glyphs[vpos][run_len];
  3729.     XFontStruct *this_font = face_list[this_run].faceptr->font;
  3730.  
  3731.     buf = (char *) alloca (len);
  3732.     cp = buf;
  3733.  
  3734.     if (this_font == 0)
  3735.       this_font = default_font;
  3736.  
  3737.     while (l--)
  3738.       *cp++ = *gp++;
  3739.     dimensions.top_left_x += XTextWidth (this_font, buf, len);
  3740.     dimensions.width = 
  3741.           X_CHAR_WIDTH (this_font,
  3742.                         (this_ch == TABGLYPH) ? ' ' : this_ch);
  3743.       }
  3744.       if (dimensions.top_left_y + dimensions.height
  3745.       >= s->display.x->pixel_height)
  3746.     return &dimensions;
  3747.  
  3748.       return &dimensions;
  3749.  
  3750.     case column_glyph:
  3751.     case glyph:
  3752.     case space:
  3753.     case window:
  3754.       {
  3755.     dimensions.width = face_list[this_run].pix_length;
  3756.       }
  3757.       if (dimensions.top_left_y + dimensions.height
  3758.       >= s->display.x->pixel_height)
  3759.     return &dimensions;
  3760.  
  3761.       return &dimensions;
  3762.  
  3763.     default:
  3764.       abort ();
  3765.     }
  3766. }
  3767.  
  3768.  
  3769. void
  3770. syms_of_xdisp ()
  3771. {
  3772.   staticpro (&last_arrow_position);
  3773.   staticpro (&last_arrow_string);
  3774.   last_arrow_position = Qnil;
  3775.   last_arrow_string = Qnil;
  3776.  
  3777.   staticpro (&echo_area_buffer);
  3778.   echo_area_buffer = Fget_buffer_create (build_string (" *echo area buffer*"));
  3779.  
  3780.   DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
  3781.     "String displayed by mode-line-format's \"%m\" specification.");
  3782.   Vglobal_mode_string = Qnil;
  3783.  
  3784.   DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
  3785.     "Marker for where to display an arrow on top of the buffer text.\n\
  3786. This must be the beginning of a line in order to work.\n\
  3787. See also `overlay-arrow-string'.");
  3788.   Voverlay_arrow_position = Qnil;
  3789.  
  3790.   DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
  3791.     "String to display as an arrow.  See also `overlay-arrow-position'.");
  3792.   Voverlay_arrow_string = Qnil;
  3793.  
  3794.   DEFVAR_INT ("scroll-step", &scroll_step,
  3795.     "*The number of lines to try scrolling a window by when point moves out.\n\
  3796. If that fails to bring point back on screen, point is centered instead.\n\
  3797. If this is zero, point is always centered after it moves off screen.");
  3798.  
  3799. /*  DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");*/
  3800.  
  3801.   DEFVAR_BOOL ("truncate-partial-width-windows",
  3802.            &truncate_partial_width_windows,
  3803.  "*Non-nil means truncate lines in all windows less than full screen wide.");
  3804.   truncate_partial_width_windows = 1;
  3805.  
  3806.   DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
  3807.     "*Non-nil means use inverse video for the mode line.");
  3808.   mode_line_inverse_video = 1;
  3809.  
  3810.   /* Lucid addition */
  3811.   DEFVAR_LISP ("screen-title-format", &Vscreen_title_format,
  3812.   "Controls the title of the X window corresponding to the selected screen.\n\
  3813. This is the same format as `mode-line-format'.");
  3814.   Vscreen_title_format = build_string ("%S: %b");
  3815.   Qscreen_title_format = intern ("screen-title-format");
  3816.   staticpro (&Qscreen_title_format);
  3817.   DEFVAR_LISP ("screen-icon-title-format", &Vscreen_icon_title_format,
  3818.   "Controls the title of the icon corresponding to the selected screen.\n\
  3819. See also the variable `screen-title-format'");
  3820.   Vscreen_icon_title_format = build_string ("%b");
  3821.   Qscreen_icon_title_format = intern ("screen-icon-title-format");
  3822.  
  3823. #ifdef MULTI_SCREEN
  3824.   defsubr (&Sredraw_screen);
  3825. #endif /* MULTI_SCREEN */
  3826.   defsubr (&Sredraw_display);
  3827. }
  3828.  
  3829. /* initialize the window system */
  3830. void
  3831. init_xdisp ()
  3832. {
  3833.   Lisp_Object root_window;
  3834. #ifndef COMPILER_REGISTER_BUG
  3835.   register
  3836. #endif /* COMPILER_REGISTER_BUG */
  3837.     struct window *mini_w;
  3838.  
  3839.   this_line_bufpos = 0;
  3840.  
  3841.   mini_w = XWINDOW (minibuf_window);
  3842.   root_window = mini_w->prev;
  3843.  
  3844.   echo_area_glyphs = 0;
  3845.   previous_echo_glyphs = 0;
  3846.  
  3847.   if (!noninteractive)
  3848.     {
  3849.       SCREEN_PTR s = XSCREEN (WINDOW_SCREEN (XWINDOW (root_window)));
  3850.  
  3851. #ifdef HAVE_X_WINDOWS
  3852.       if (!NILP (Vwindow_system) && !SCREEN_IS_X (s))
  3853.     return;
  3854. #endif
  3855.  
  3856.       XFASTINT (XWINDOW (root_window)->top) = 0;
  3857.       set_window_height (root_window, SCREEN_HEIGHT (s) - 1, 0);
  3858.       XFASTINT (mini_w->top) = SCREEN_HEIGHT (s) - 1;
  3859.       set_window_height (minibuf_window, 1, 0);
  3860.  
  3861.       XFASTINT (XWINDOW (root_window)->width) = SCREEN_WIDTH (s);
  3862.       XFASTINT (mini_w->width) = SCREEN_WIDTH (s);
  3863.     }
  3864. }
  3865.