Annotation of 43BSDReno/contrib/emacs-18.55/src/xdisp.c, revision 1.1

1.1     ! root        1: /* Display generation from window structure and buffer text.
        !             2:    Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU Emacs.
        !             5: 
        !             6: GNU Emacs is distributed in the hope that it will be useful,
        !             7: but WITHOUT ANY WARRANTY.  No author or distributor
        !             8: accepts responsibility to anyone for the consequences of using it
        !             9: or for whether it serves any particular purpose or works at all,
        !            10: unless he says so in writing.  Refer to the GNU Emacs General Public
        !            11: License for full details.
        !            12: 
        !            13: Everyone is granted permission to copy, modify and redistribute
        !            14: GNU Emacs, but only under the conditions described in the
        !            15: GNU Emacs General Public License.   A copy of this license is
        !            16: supposed to have been given to you along with GNU Emacs so you
        !            17: can know your rights and responsibilities.  It should be in a
        !            18: file named COPYING.  Among other things, the copyright notice
        !            19: and this notice must be preserved on all copies.  */
        !            20: 
        !            21: 
        !            22: #include "config.h"
        !            23: #include <stdio.h>
        !            24: /*#include <ctype.h>*/
        !            25: #undef NULL
        !            26: #include "lisp.h"
        !            27: #include "window.h"
        !            28: #include "termchar.h"
        !            29: #include "dispextern.h"
        !            30: #include "buffer.h"
        !            31: #include "indent.h"
        !            32: #include "commands.h"
        !            33: #include "macros.h"
        !            34: 
        !            35: extern int interrupt_input;
        !            36: 
        !            37: /* Nonzero means print newline before next minibuffer message.  */
        !            38: 
        !            39: int noninteractive_need_newline;
        !            40: 
        !            41: #define min(a, b) ((a) < (b) ? (a) : (b))
        !            42: #define max(a, b) ((a) > (b) ? (a) : (b))
        !            43: 
        !            44: /* The buffer position of the first character appearing
        !            45:  entirely or partially on the current screen line.
        !            46:  Or zero, which disables the optimization for the current screen line. */
        !            47: static int this_line_bufpos;
        !            48: 
        !            49: /* Number of characters past the end of this line,
        !            50:    including the terminating newline */
        !            51: static int this_line_endpos;
        !            52: 
        !            53: /* The vertical position of this screen line. */
        !            54: static int this_line_vpos;
        !            55: 
        !            56: /* Hpos value for start of display on this screen line.
        !            57:    Usually zero, but negative if first character really began
        !            58:    on previous line */
        !            59: static int this_line_start_hpos;
        !            60: 
        !            61: /* Buffer that this_line variables are describing. */
        !            62: static struct buffer *this_line_buffer;
        !            63: 
        !            64: /* Value of minibuf_message when it was last acted on.
        !            65:   If this is nonzero, there is a message on the screen
        !            66:   in the minibuffer and it should be erased as soon
        !            67:   as it is no longer requested to appear. */
        !            68: char *prev_minibuf_message;
        !            69: 
        !            70: /* Nonzero means truncate lines in all windows less wide than the screen */
        !            71: int truncate_partial_width_windows;
        !            72: 
        !            73: Lisp_Object Vglobal_mode_string;
        !            74: 
        !            75: /* Marker for where to display an arrow on top of the buffer text.  */
        !            76: Lisp_Object Voverlay_arrow_position;
        !            77: 
        !            78: /* String to display for the arrow.  */
        !            79: Lisp_Object Voverlay_arrow_string;
        !            80: 
        !            81: /* Values of those variables at last redisplay.  */
        !            82: Lisp_Object last_arrow_position, last_arrow_string;
        !            83: 
        !            84: /* The number of lines to try scrolling a
        !            85:   window by when point leaves the window; if
        !            86:   it is <=0 then point is centered in the window */
        !            87: int scroll_step;
        !            88: 
        !            89: /* Nonzero means send various TERMCAP strings when screen is cleared.  */
        !            90: int reset_terminal_on_clear;
        !            91: 
        !            92: /* Nonzero if try_window_id has made blank lines at window bottom
        !            93:  since the last redisplay that paused */
        !            94: static int blank_end_of_window;
        !            95: 
        !            96: /* Number of windows showing the buffer of the selected window.
        !            97:    keyboard.c refers to this.  */
        !            98: int buffer_shared;
        !            99: 
        !           100: /* display_text_line sets these to the screen position (origin 0) of point,
        !           101:   whether the window is selected or not.
        !           102:  Set one to -1 first to determine whether point was found afterwards.  */
        !           103: 
        !           104: static int point_vpos;
        !           105: static int point_hpos;
        !           106: 
        !           107: int debug_end_pos;
        !           108: 
        !           109: /* Nonzero means display mode line highlighted */
        !           110: int mode_line_inverse_video;
        !           111: 
        !           112: struct position *display_text_line ();
        !           113: 
        !           114: /* Prompt to display in front of the minibuffer contents */
        !           115: char *minibuf_prompt;
        !           116: 
        !           117: /* Width in columns of current minibuffer prompt.  */
        !           118: int minibuf_prompt_width;
        !           119: 
        !           120: /* Message to display instead of minibuffer contents
        !           121:    This is what the functions error and message make,
        !           122:    and command echoing uses it as well.
        !           123:    It overrides the minibuf_prompt as well as the buffer.  */
        !           124: char *minibuf_message;
        !           125: 
        !           126: /* Depth in recursive edits */
        !           127: int RecurseDepth;
        !           128: 
        !           129: /* Depth in minibuffer invocations */
        !           130: int MinibufDepth;
        !           131: 
        !           132: /* true iff we should redraw the mode lines on the next redisplay */
        !           133: int RedoModes;
        !           134: 
        !           135: /* Minimum value of bf_s1 since last redisplay that finished.
        !           136:  Valid for current buffer unless Cant1WinOpt is nonzero. */
        !           137: int beg_unchanged;
        !           138: 
        !           139: /* Minimum value of bf_s2 since last redisplay that finished.
        !           140:  Valid for current buffer unless Cant1WinOpt is nonzero. */
        !           141: int end_unchanged;
        !           142: 
        !           143: /* bf_modified as of last redisplay that finished;
        !           144:  if it matches bf_modified, beg_unchanged and end_unchanged
        !           145:  contain no useful information */
        !           146: int unchanged_modified;
        !           147: 
        !           148: /* Nonzero if head_clip or tail_clip of current buffer has changed
        !           149:  since last redisplay that finished */
        !           150: int clip_changed;
        !           151: 
        !           152: /* Nonzero if window sizes or contents have changed
        !           153:  since last redisplay that finished */
        !           154: int windows_or_buffers_changed;
        !           155: 
        !           156: char *decode_mode_spec ();
        !           157: 
        !           158: DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
        !           159:   "Clear the screen and output again what is supposed to appear on it.")
        !           160:   ()
        !           161: {
        !           162:   if (screen_height == 0) abort (); /* Some bug zeros some core */
        !           163:   if (reset_terminal_on_clear)
        !           164:     set_terminal_modes ();
        !           165:   clear_screen ();
        !           166:   fflush (stdout);
        !           167:   clear_screen_records ();
        !           168:   if (screen_height == 0) abort (); /* Some bug zeros some core */
        !           169:   windows_or_buffers_changed++;
        !           170:   /* Mark all windows as INaccurate,
        !           171:      so that every window will have its redisplay done.  */
        !           172:   mark_window_display_accurate (XWINDOW (minibuf_window)->prev, 0);
        !           173:   if (screen_height == 0) abort (); /* Some bug zeros some core */
        !           174:   return Qnil;
        !           175: }
        !           176: 
        !           177: static char message_buf[MScreenWidth + 1];
        !           178: 
        !           179: /* dump an informative message to the minibuf */
        !           180: /* VARARGS 1 */
        !           181: message (m, a1, a2, a3)
        !           182:      char *m;
        !           183: {
        !           184:   if (noninteractive)
        !           185:     {
        !           186:       if (noninteractive_need_newline)
        !           187:        putchar ('\n');
        !           188:       printf (m, a1, a2, a3);
        !           189:       printf ("\n");
        !           190:       fflush (stdout);
        !           191:     }
        !           192:   else if (INTERACTIVE)
        !           193:     {
        !           194: #ifdef NO_ARG_ARRAY
        !           195:       int a[3];
        !           196:       a[0] = a1;
        !           197:       a[1] = a2;
        !           198:       a[2] = a3;
        !           199: 
        !           200:       doprnt (message_buf, sizeof message_buf - 1, m, 3, a);
        !           201: #else
        !           202:       doprnt (message_buf, sizeof message_buf - 1, m, 3, &a1);
        !           203: #endif /* NO_ARG_ARRAY */
        !           204:       minibuf_message = message_buf;
        !           205:       do {
        !           206:        hold_window_change ();
        !           207:        display_minibuf_message ();
        !           208:        update_screen (1, 1);
        !           209:        unhold_window_change ();
        !           210:       } while (screen_garbaged);
        !           211:     }
        !           212: }
        !           213: 
        !           214: /* Specify m, a string, as a message in the minibuf.  */
        !           215: message1 (m)
        !           216:      char *m;
        !           217: {
        !           218:   if (noninteractive)
        !           219:     {
        !           220:       if (noninteractive_need_newline)
        !           221:        putchar ('\n');
        !           222:       printf ("%s\n", m);
        !           223:       fflush (stdout);
        !           224:     }
        !           225:   else if (INTERACTIVE)
        !           226:     {
        !           227:       minibuf_message = m;
        !           228:       do {
        !           229:        hold_window_change ();
        !           230:        display_minibuf_message ();
        !           231:        update_screen (1, 1);
        !           232:        unhold_window_change ();
        !           233:       } while (screen_garbaged);
        !           234:     }
        !           235: }
        !           236: 
        !           237: display_minibuf_message ()
        !           238: {
        !           239:   register int vpos;
        !           240:   register struct display_line *line;
        !           241: 
        !           242:   if (screen_garbaged)
        !           243:     {
        !           244:       Fredraw_display ();
        !           245:       screen_garbaged = 0;
        !           246:     }
        !           247: 
        !           248:   if (minibuf_message || !MinibufDepth)
        !           249:     {
        !           250:       vpos = XFASTINT (XWINDOW (minibuf_window)->top);
        !           251:       line = get_display_line (vpos, 0);
        !           252:       display_string (XWINDOW (minibuf_window), line,
        !           253:                      minibuf_message ? minibuf_message : "",
        !           254:                      0, 0, 0, screen_width);
        !           255: 
        !           256:       /* If desired cursor location is on this line, put it at end of text */
        !           257:       if (cursY == vpos)
        !           258:        cursX = line->length;
        !           259:     }
        !           260:   else if (!EQ (minibuf_window, selected_window))
        !           261:     windows_or_buffers_changed++;
        !           262: 
        !           263:   if (EQ (minibuf_window, selected_window))
        !           264:     this_line_bufpos = 0;
        !           265: 
        !           266:   prev_minibuf_message = minibuf_message;
        !           267: }
        !           268: 
        !           269: /* Do a screen update, taking possible shortcuts into account.
        !           270:    This is the main external entry point for redisplay.
        !           271: 
        !           272:    If the last redisplay displayed a minibuffer message and that
        !           273:    message is no longer requested, we usually redraw the contents
        !           274:    of the minibuffer, or clear the minibuffer if it is not in use.
        !           275:    If the argument SaveMiniBuf is nonzero, this is not done.
        !           276: 
        !           277:    Everyone would like to have a hook here to call eval,
        !           278:    but that cannot be done safely without a lot of changes elsewhere.
        !           279:    This can be called from signal handlers; with alarms set up;
        !           280:    or with synchronous processes running.
        !           281:    See the function EchoThem in keyboard.c.
        !           282:    See Fcall_process; if you called it from here, it could be
        !           283:    entered recursively.  */
        !           284: 
        !           285: DoDsp (SaveMiniBuf)
        !           286: {
        !           287:   register struct window *w = XWINDOW (selected_window);
        !           288:   register int pause;
        !           289:   int inhibit_hairy_id = 0;
        !           290:   int must_finish = 0;
        !           291:   int all_windows;
        !           292:   register int tlbufpos, tlendpos;
        !           293:   struct position pos;
        !           294:   extern int input_pending;
        !           295: 
        !           296:   if (noninteractive)
        !           297:     return;
        !           298: 
        !           299:   hold_window_change ();
        !           300: 
        !           301:   if (screen_garbaged)
        !           302:     {
        !           303:       Fredraw_display ();
        !           304:       screen_garbaged = 0;
        !           305:     }
        !           306: 
        !           307:   if (minibuf_message ||
        !           308:       (prev_minibuf_message && !SaveMiniBuf))
        !           309:     {
        !           310:       display_minibuf_message ();
        !           311:       must_finish = 1;
        !           312:     }
        !           313: 
        !           314:   if (clip_changed || windows_or_buffers_changed)
        !           315:     RedoModes++;
        !           316: 
        !           317:   /* Detect case that we need to write a star in the mode line.  */
        !           318:   if (XFASTINT (w->last_modified) < bf_modified
        !           319:       && XFASTINT (w->last_modified) <= bf_cur->save_modified)
        !           320:     {
        !           321:       w->redo_mode_line = Qt;
        !           322:       if (buffer_shared > 1)
        !           323:        RedoModes++;
        !           324:     }
        !           325: 
        !           326:   all_windows = RedoModes || buffer_shared > 1;
        !           327: 
        !           328:   /* If specs for an arrow have changed, do thorough redisplay
        !           329:      to ensure we remove any arrow that should no longer exist.  */
        !           330:   if (Voverlay_arrow_position != last_arrow_position
        !           331:       || Voverlay_arrow_string != last_arrow_string)
        !           332:     all_windows = 1, clip_changed = 1;
        !           333: 
        !           334:   tlbufpos = this_line_bufpos;
        !           335:   tlendpos = this_line_endpos;
        !           336:   if (!all_windows && tlbufpos > 0 && NULL (w->redo_mode_line)
        !           337:       /* Make sure recorded data applies to current buffer, etc */
        !           338:       && this_line_buffer == bf_cur
        !           339:       && bf_cur == XBUFFER (w->buffer)
        !           340:       && NULL (w->force_start)
        !           341:       /* Point must be on the line that we have info recorded about */
        !           342:       && point >= tlbufpos
        !           343:       && point <= bf_s1 + bf_s2 + 1 - tlendpos
        !           344:       /* All text outside that line, including its final newline,
        !           345:         must be unchanged */
        !           346:       && (XFASTINT (w->last_modified) >= bf_modified
        !           347:          || (beg_unchanged >= tlbufpos - 1
        !           348:              && bf_s1 >= tlbufpos - 1
        !           349:              && end_unchanged >= tlendpos
        !           350:              && bf_s2 >= tlendpos)))
        !           351:     {
        !           352:       if (tlbufpos > FirstCharacter && CharAt (tlbufpos - 1) != '\n'
        !           353:          && (tlbufpos == NumCharacters + 1
        !           354:              || CharAt (tlbufpos) == '\n'))
        !           355:        /* Former continuation line has disappeared by becoming empty */
        !           356:        goto cancel;
        !           357:       else if (XFASTINT (w->last_modified) < bf_modified
        !           358:               || EQ (selected_window, minibuf_window))
        !           359:        {
        !           360:          point_vpos = -1;
        !           361:          display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos,
        !           362:                             pos_tab_offset (w, tlbufpos));
        !           363:          /* If line contains point, is not continued,
        !           364:                 and ends at same distance from eob as before, we win */
        !           365:          if (point_vpos >= 0 && this_line_bufpos
        !           366:              && this_line_endpos == tlendpos)
        !           367:            {
        !           368:              /* Done by display_text_line
        !           369:                 cursX = point_hpos;
        !           370:                 cursY = this_line_vpos;
        !           371:               */
        !           372:              if (XFASTINT (w->width) != screen_width)
        !           373:                preserve_other_columns (w);
        !           374:              goto update;
        !           375:            }
        !           376:          else
        !           377:            goto cancel;
        !           378:        }
        !           379:       else if (point == XFASTINT (w->last_point))
        !           380:        {
        !           381:          if (!must_finish)
        !           382:            return;
        !           383:          goto update;
        !           384:        }
        !           385:       else
        !           386:        {
        !           387:          pos = *compute_motion (tlbufpos, 0,
        !           388:                                XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
        !           389:                                point, 2, - (1 << (SHORTBITS - 1)),
        !           390:                                XFASTINT (w->width) - 1
        !           391:                                - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width),
        !           392:                                XINT (w->hscroll), 0);
        !           393:          if (pos.vpos < 1)
        !           394:            {
        !           395:              cursX = max (XFASTINT (w->left), pos.hpos);
        !           396:              cursY = this_line_vpos;
        !           397:              goto update;
        !           398:            }
        !           399:          else
        !           400:            goto cancel;
        !           401:        }
        !           402:     cancel:
        !           403:       /* Text changed drastically or point moved off of line */
        !           404:       cancel_line (this_line_vpos);
        !           405:     }
        !           406: 
        !           407:   this_line_bufpos = 0;
        !           408: 
        !           409:   if (all_windows)
        !           410:     redisplay_all_windows ();
        !           411:   else
        !           412:     {
        !           413:       inhibit_hairy_id = redisplay_window (selected_window, 1);
        !           414:       if (XFASTINT (w->width) != screen_width)
        !           415:        preserve_other_columns (w);
        !           416:     }
        !           417: 
        !           418: update: 
        !           419:   if (interrupt_input)
        !           420:     unrequest_sigio ();
        !           421: 
        !           422:   pause = update_screen (0, inhibit_hairy_id);
        !           423: 
        !           424:   /* If screen does not match, prevent doing single-line-update next time.
        !           425:      Also, don't forget to check every line to update the arrow.  */
        !           426:   if (pause)
        !           427:     {
        !           428:       this_line_bufpos = 0;
        !           429:       if (!NULL (last_arrow_position))
        !           430:        {
        !           431:          last_arrow_position = Qt;
        !           432:          last_arrow_string = Qt;
        !           433:        }
        !           434:       /* If we pause after scrolling, some lines in PhysScreen may be null
        !           435:         and then preserve_other_columns won't be able to preserve all
        !           436:         the vertical-bar separators.  So avoid using it in that case.  */
        !           437:       if (XFASTINT (w->width) != screen_width)
        !           438:        RedoModes = 1;
        !           439:     }
        !           440: 
        !           441:   /* Now text on screen agrees with windows, so
        !           442:      put info into the windows for partial redisplay to follow */
        !           443: 
        !           444:   if (!pause)
        !           445:     {
        !           446:       register struct buffer_text *t
        !           447:        = XBUFFER (w->buffer) == bf_cur
        !           448:          ? &bf_text : &XBUFFER (w->buffer)->text;
        !           449: 
        !           450:       blank_end_of_window = 0;
        !           451:       clip_changed = 0;
        !           452:       unchanged_modified = t->modified;
        !           453:       beg_unchanged = t->size1, end_unchanged = t->size2;
        !           454: 
        !           455:       XFASTINT (w->last_point) = t->pointloc;
        !           456:       XFASTINT (w->last_point_x) = cursX;
        !           457:       XFASTINT (w->last_point_y) = cursY;
        !           458: 
        !           459:       if (all_windows)
        !           460:        mark_window_display_accurate (XWINDOW (minibuf_window)->prev, 1);
        !           461:       else
        !           462:        {
        !           463:          w->redo_mode_line = Qnil;
        !           464:          XFASTINT (w->last_modified) = t->modified;
        !           465:          w->window_end_valid = Qt;
        !           466:          last_arrow_position = Voverlay_arrow_position;
        !           467:          last_arrow_string = Voverlay_arrow_string;
        !           468:        }
        !           469:       RedoModes = 0;
        !           470:       windows_or_buffers_changed = 0;
        !           471:     }
        !           472: 
        !           473:   /* Start SIGIO interrupts coming again.
        !           474:      Having them off during the code above
        !           475:      makes it less likely one will discard output,
        !           476:      but not impossible, since there might be stuff
        !           477:      in the system buffer here.
        !           478:      But it is much hairier to try to do anything about that.  */
        !           479: 
        !           480:   if (interrupt_input)
        !           481:     request_sigio ();
        !           482: 
        !           483:   unhold_window_change ();
        !           484: 
        !           485:   if (screen_garbaged)
        !           486:     DoDsp (SaveMiniBuf);
        !           487: }
        !           488: 
        !           489: mark_window_display_accurate (window, flag)
        !           490:      Lisp_Object window;
        !           491:      int flag;
        !           492: {
        !           493:   register struct window *w;
        !           494: 
        !           495:   for (;!NULL (window); window = w->next)
        !           496:     {
        !           497:       w = XWINDOW (window);
        !           498: 
        !           499:       if (!NULL (w->buffer))
        !           500:        XFASTINT (w->last_modified)
        !           501:          = !flag ? 0
        !           502:            : XBUFFER (w->buffer) == bf_cur
        !           503:              ? bf_modified : XBUFFER (w->buffer)->text.modified;
        !           504:       w->window_end_valid = Qt;
        !           505:       w->redo_mode_line = Qnil;
        !           506: 
        !           507:       if (!NULL (w->vchild))
        !           508:        mark_window_display_accurate (w->vchild, flag);
        !           509:       if (!NULL (w->hchild))
        !           510:        mark_window_display_accurate (w->hchild, flag);
        !           511:     }
        !           512: 
        !           513:   if (flag)
        !           514:     {
        !           515:       last_arrow_position = Voverlay_arrow_position;
        !           516:       last_arrow_string = Voverlay_arrow_string;
        !           517:     }
        !           518:   else
        !           519:     {
        !           520:       /* t is unequal to any useful value of Voverlay_arrow_... */
        !           521:       last_arrow_position = Qt;
        !           522:       last_arrow_string = Qt;
        !           523:     }
        !           524: }
        !           525: 
        !           526: int do_id = 1;
        !           527: 
        !           528: /* Do full redisplay of one or all windows.
        !           529:   This does not include updating the screen;
        !           530:   just generating lines to pass to update_screen.  */
        !           531: 
        !           532: /* Entry point to redisplay all windows */
        !           533: 
        !           534: redisplay_all_windows ()
        !           535: {
        !           536:   buffer_shared = 0;
        !           537: 
        !           538:   redisplay_windows (XWINDOW (minibuf_window)->prev);
        !           539: }
        !           540: 
        !           541: redisplay_windows (window)
        !           542:      Lisp_Object window;
        !           543: {
        !           544:   for (; !NULL (window); window = XWINDOW (window)->next)
        !           545:     redisplay_window (window, 0);
        !           546: }
        !           547: 
        !           548: redisplay_window (window, just_this_one)
        !           549:      Lisp_Object window;
        !           550:      int just_this_one;
        !           551: {
        !           552:   register struct window *w = XWINDOW (window);
        !           553:   int height;
        !           554:   register int lpoint = point;
        !           555:   struct buffer *old = bf_cur;
        !           556:   register int width = XFASTINT (w->width) - 1
        !           557:     - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width);
        !           558:   register int startp;
        !           559:   register int hscroll = XINT (w->hscroll);
        !           560:   struct position pos;
        !           561:   int inhibit_hairy_id = 0;
        !           562:   int opoint;
        !           563:   int tem;
        !           564: 
        !           565:   if (screen_height == 0) abort (); /* Some bug zeros some core */
        !           566: 
        !           567:   /* If this is a combination window, do its children; that's all.  */
        !           568: 
        !           569:   if (!NULL (w->vchild))
        !           570:     {
        !           571:       redisplay_windows (w->vchild);
        !           572:       return 0;
        !           573:     }
        !           574:   if (!NULL (w->hchild))
        !           575:     {
        !           576:       redisplay_windows (w->hchild);
        !           577:       return 0;
        !           578:     }
        !           579:   if (NULL (w->buffer))
        !           580:     abort ();
        !           581: 
        !           582:   if (RedoModes)
        !           583:     w->redo_mode_line = Qt;
        !           584: 
        !           585:   /* Otherwise set up data on this window; select its buffer and point value */
        !           586: 
        !           587:   height = XFASTINT (w->height);
        !           588:   if (w != XWINDOW (minibuf_window))
        !           589:     height--;
        !           590:   else if (minibuf_message)
        !           591:     return 0;
        !           592: 
        !           593:   SetBfx (XBUFFER (w->buffer));
        !           594:   opoint = point;
        !           595: 
        !           596:   if (!just_this_one
        !           597:       && bf_cur == XBUFFER (XWINDOW (selected_window)->buffer))
        !           598:     buffer_shared++;
        !           599: 
        !           600:   if (!EQ (window, selected_window))
        !           601:     {
        !           602:       SetPoint (marker_position (w->pointm));
        !           603:       if (point < FirstCharacter)
        !           604:        point = FirstCharacter;
        !           605:       else if (point > NumCharacters)
        !           606:        point = NumCharacters + 1;
        !           607:     }
        !           608: 
        !           609:   /* If window-start is screwed up, choose a new one.  */
        !           610: 
        !           611:   if (XMARKER (w->start)->buffer != bf_cur)
        !           612:     goto recenter;
        !           613: 
        !           614:   startp = marker_position (w->start);
        !           615: 
        !           616:   /* Handle case where place to start displaying has been specified */
        !           617: 
        !           618:   if (!NULL (w->force_start))
        !           619:     {
        !           620:       w->redo_mode_line = Qt;
        !           621:       w->force_start = Qnil;
        !           622:       XFASTINT (w->last_modified) = 0;
        !           623:       if (!try_window (window, startp))
        !           624:        {
        !           625:          /* If point does not appear, move point so it does appear */
        !           626:          pos = *compute_motion (startp, 0,
        !           627:                                ((EQ (window, minibuf_window) && startp == 1)
        !           628:                                 ? minibuf_prompt_width : 0)
        !           629:                                +
        !           630:                                (hscroll ? 1 - hscroll : 0),
        !           631:                                NumCharacters + 1, height / 2,
        !           632:                                - (1 << (SHORTBITS - 1)),
        !           633:                                width, hscroll, pos_tab_offset (w, startp));
        !           634:          SetPoint (pos.bufpos);
        !           635:          if (w != XWINDOW (selected_window))
        !           636:            Fset_marker (w->pointm, make_number (point), Qnil);
        !           637:          else
        !           638:            lpoint = point;
        !           639: 
        !           640:          if (EQ (window, selected_window))
        !           641:            {
        !           642:              cursX = max (0, pos.hpos) + XFASTINT (w->left);
        !           643:              cursY = pos.vpos + XFASTINT (w->top);
        !           644:            }
        !           645:        }
        !           646:       goto done;
        !           647:     }
        !           648: 
        !           649:   /* Handle case where text has not changed, only point,
        !           650:      and it has not moved off the screen */
        !           651: 
        !           652:   /* This code is not used for minibuffer for the sake of
        !           653:      the case of redisplaying to replace an echo area message;
        !           654:      since in that case the minibuffer contents per se are usually unchanged.
        !           655:      This code is of no real use in the minibuffer since
        !           656:      the handling of tlbufpos, etc., in DoDsp handles the same cases.  */
        !           657: 
        !           658:   if (XFASTINT (w->last_modified) >= bf_modified
        !           659:       && point >= startp && !clip_changed
        !           660:       && (just_this_one || XFASTINT (w->width) == screen_width)
        !           661:       && !EQ (window, minibuf_window))
        !           662:     {
        !           663:       pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0),
        !           664:                            point, height + 1, 10000, width, hscroll,
        !           665:                            pos_tab_offset (w, startp));
        !           666: 
        !           667:       if (pos.vpos < height)
        !           668:        {
        !           669:          /* Ok, point is still on screen */
        !           670:          if (w == XWINDOW (selected_window))
        !           671:            {
        !           672:              /* These variables are supposed to be origin 1 */
        !           673:              cursX = max (0, pos.hpos) + XFASTINT (w->left);
        !           674:              cursY = pos.vpos + XFASTINT (w->top);
        !           675:            }
        !           676: /* This doesn't do the trick, because if a window to the right of
        !           677:  this one must be redisplayed, this does nothing because there
        !           678:  is nothing in DesiredScreen yet, and then the other window is
        !           679:  redisplayed, making likes that are empty in this window's columns.
        !           680:          if (XFASTINT (w->width) != screen_width)
        !           681:            preserve_my_columns (w);
        !           682: */
        !           683:          goto done;
        !           684:        }
        !           685:       /* Don't bother trying redisplay with same start;
        !           686:        we already know it will lose */
        !           687:     }
        !           688:   /* If current starting point was originally the beginning of a line
        !           689:      but no longer is, find a new starting point.  */
        !           690:   else if (!NULL (w->start_at_line_beg)
        !           691:           && !(startp == FirstCharacter
        !           692:                || CharAt (startp - 1) == '\n'))
        !           693:     {
        !           694:       goto recenter;
        !           695:     }
        !           696:   else if (just_this_one && !EQ (window, minibuf_window)
        !           697:           && point >= startp
        !           698:           && XFASTINT (w->last_modified)
        !           699:           && ! EQ (w->window_end_valid, Qnil)
        !           700:           && do_id && !clip_changed
        !           701:           && !blank_end_of_window
        !           702:           && XFASTINT (w->width) == screen_width
        !           703:           && EQ (last_arrow_position, Voverlay_arrow_position)
        !           704:           && EQ (last_arrow_string, Voverlay_arrow_string)
        !           705:           && (tem = try_window_id (selected_window))
        !           706:           && tem != -2)
        !           707:     {
        !           708:       /* tem > 0 means success.  tem == -1 means choose new start.
        !           709:         tem == -2 means try again with same start,
        !           710:          and nothing but whitespace follows the changed stuff.
        !           711:         tem == 0 means try again with same start.  */
        !           712:       if (tem > 0)
        !           713:        {
        !           714: /*       inhibit_hairy_id = 1;   */
        !           715:          goto done;
        !           716:        }
        !           717:     }
        !           718:   else if (startp >= FirstCharacter && startp <= NumCharacters + 1
        !           719:           /* Avoid starting display at end of buffer! */
        !           720:           && (startp <= NumCharacters || startp == FirstCharacter
        !           721:               || (XFASTINT (w->last_modified) >= bf_modified)))
        !           722:     {
        !           723:       /* Try to redisplay starting at same place as before */
        !           724:       /* If point has not moved off screen, accept the results */
        !           725:       if (try_window (window, startp))
        !           726:        goto done;
        !           727:       else
        !           728:        cancel_my_columns (w);
        !           729:     }
        !           730: 
        !           731:   XFASTINT (w->last_modified) = 0;
        !           732:   w->redo_mode_line = Qt;
        !           733: 
        !           734:   /* Try to scroll by specified few lines */
        !           735: 
        !           736:   if (scroll_step && !clip_changed)
        !           737:     {
        !           738:       if (point > startp)
        !           739:        {
        !           740:          pos = *vmotion (bf_s1 + bf_s2 + 1 - XFASTINT (w->window_end_pos),
        !           741:                          scroll_step, width, hscroll, window);
        !           742:          if (pos.vpos >= height)
        !           743:            goto scroll_fail;
        !           744:        }
        !           745: 
        !           746:       pos = *vmotion (startp, point < startp ? - scroll_step : scroll_step,
        !           747:                      width, hscroll, window);
        !           748: 
        !           749:       if (point >= pos.bufpos)
        !           750:        {
        !           751:          if (try_window (window, pos.bufpos))
        !           752:            goto done;
        !           753:          else
        !           754:            cancel_my_columns (w);
        !           755:        }
        !           756:     scroll_fail: ;
        !           757:     }
        !           758: 
        !           759:   /* Finally, just choose place to start which centers point */
        !           760: 
        !           761: recenter:
        !           762:   pos = *vmotion (point, - height / 2, width, hscroll, window);
        !           763:   try_window (window, pos.bufpos);
        !           764: 
        !           765:   startp = marker_position (w->start);
        !           766:   w->start_at_line_beg = 
        !           767:     (startp == FirstCharacter || CharAt (startp - 1) == '\n') ? Qt : Qnil;
        !           768: 
        !           769: done:
        !           770:   /* If window not full width, must redo its mode line
        !           771:      if the window to its side is being redone */
        !           772:   if ((!NULL (w->redo_mode_line)
        !           773:        || (!just_this_one && width < screen_width - 1))
        !           774:       && !EQ (window, minibuf_window))
        !           775:     display_mode_line (w);
        !           776: 
        !           777:   SetPoint (opoint);
        !           778:   SetBfx (old);
        !           779:   SetPoint (lpoint);
        !           780: 
        !           781:   return inhibit_hairy_id;
        !           782: }
        !           783: 
        !           784: /* Do full redisplay on one window,
        !           785:   starting at position `pos',
        !           786:   and return nonzero if point appears in the displayed text */
        !           787: 
        !           788: try_window (window, pos)
        !           789:      Lisp_Object window;
        !           790:      register int pos;
        !           791: {
        !           792:   register struct window *w = XWINDOW (window);
        !           793:   register int height = XFASTINT (w->height) - !EQ (window, minibuf_window);
        !           794:   register int vpos = XFASTINT (w->top);
        !           795:   register int last_text_vpos = vpos;
        !           796:   int tab_offset = pos_tab_offset (w, pos);
        !           797: 
        !           798:   struct position val;
        !           799: 
        !           800:   Fset_marker (w->start, make_number (pos), Qnil);
        !           801: 
        !           802:   point_vpos = -1;
        !           803:   val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
        !           804: 
        !           805:   while (--height >= 0)
        !           806:     {
        !           807:       val = *display_text_line (w, pos, vpos, val.hpos, tab_offset);
        !           808:       tab_offset += XFASTINT (w->width) - 1;
        !           809:       if (val.vpos) tab_offset = 0;
        !           810:       vpos++;
        !           811:       if (pos != val.bufpos)
        !           812:        last_text_vpos
        !           813:          /* Next line, unless prev line ended in end of buffer with no cr */
        !           814:          = vpos - (val.vpos && CharAt (val.bufpos - 1) != '\n');
        !           815:       pos = val.bufpos;
        !           816:     }
        !           817: 
        !           818:   /* If last line is continued in middle of character,
        !           819:      include the split character in the text considered on the screen */
        !           820:   if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
        !           821:     pos++;
        !           822: 
        !           823:   /* Say where last char on screen will be, once redisplay is finished.  */
        !           824:   XFASTINT (w->window_end_pos) = bf_s1 + bf_s2 + 1 - pos;
        !           825:   XFASTINT (w->window_end_vpos) = last_text_vpos - XFASTINT (w->top);
        !           826:   /* But that is not valid info until redisplay finishes.  */
        !           827:   w->window_end_valid = Qnil;
        !           828:   return point_vpos >= 0;
        !           829: }
        !           830: 
        !           831: /* Try to redisplay when buffer is modified locally,
        !           832:  computing insert/delete line to preserve text outside
        !           833:  the bounds of the changes.
        !           834:  Return 1 if successful, 0 if if cannot tell what to do,
        !           835:  or -1 to tell caller to find a new window start,
        !           836:  or -2 to tell caller to do normal redisplay with same window start.  */
        !           837: 
        !           838: try_window_id (window)
        !           839:      Lisp_Object window;
        !           840: {
        !           841:   int pos;
        !           842:   register struct window *w = XWINDOW (window);
        !           843:   register int height = XFASTINT (w->height) - !EQ (window, minibuf_window);
        !           844:   int top = XFASTINT (w->top);
        !           845:   int start = marker_position (w->start);
        !           846:   int width = XFASTINT (w->width) - 1
        !           847:     - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width);
        !           848:   int hscroll = XINT (w->hscroll);
        !           849:   int lmargin = hscroll > 0 ? 1 - hscroll : 0;
        !           850:   register int vpos;
        !           851:   register int i, tem;
        !           852:   int last_text_vpos = 0;
        !           853:   int stop_vpos;
        !           854: 
        !           855:   struct position val, bp, ep, xp, pp;
        !           856:   int scroll_amount = 0;
        !           857:   int delta;
        !           858:   int tab_offset, epto;
        !           859: 
        !           860:   if (bf_s1 < beg_unchanged)
        !           861:     beg_unchanged = bf_s1;
        !           862:   if (bf_s2 < end_unchanged)
        !           863:     end_unchanged = bf_s2;
        !           864: 
        !           865:   if (beg_unchanged + 1 < start)
        !           866:     return 0;                  /* Give up if changes go above top of window */
        !           867: 
        !           868:   /* Find position before which nothing is changed.  */
        !           869:   bp = *compute_motion (start, 0, lmargin,
        !           870:                        beg_unchanged + 1, 10000, 10000, width, hscroll,
        !           871:                        pos_tab_offset (w, start));
        !           872:   if (bp.vpos >= height)
        !           873:     return point < bp.bufpos && !bp.contin;
        !           874: 
        !           875:   vpos = bp.vpos;
        !           876: 
        !           877:   /* Find beginning of that screen line.  Must display from there.  */
        !           878:   bp = *vmotion (bp.bufpos, 0, width, hscroll, window);
        !           879: 
        !           880:   pos = bp.bufpos;
        !           881:   val.hpos = lmargin;
        !           882:   if (pos < start)
        !           883:     return -1;
        !           884: 
        !           885:   /* If about to start displaying at the beginning of a continuation line,
        !           886:      really start with previous screen line, in case it was not
        !           887:      continued when last redisplayed */
        !           888:   if (bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
        !           889:     {
        !           890:       bp = *vmotion (bp.bufpos, -1, width, hscroll, window);
        !           891:       --vpos;
        !           892:       pos = bp.bufpos;
        !           893:     }
        !           894: 
        !           895:   if (bp.contin && bp.hpos != lmargin)
        !           896:     {
        !           897:       val.hpos = bp.prevhpos - width + lmargin;
        !           898:       pos--;
        !           899:     }
        !           900: 
        !           901:   bp.vpos = vpos;
        !           902: 
        !           903:   /* Find first visible newline after which no more is changed.  */
        !           904:   tem = find_next_newline (bf_s1 + bf_s2 + 1
        !           905:                           - max (end_unchanged, bf_tail_clip),
        !           906:                           1);
        !           907:   if (XTYPE (bf_cur->selective_display) == Lisp_Int
        !           908:       && XINT (bf_cur->selective_display) > 0)
        !           909:     while (tem < NumCharacters
        !           910:           && (position_indentation (tem)
        !           911:               >= XINT (bf_cur->selective_display)))
        !           912:       tem = find_next_newline (tem, 1);
        !           913: 
        !           914:   /* Compute the cursor position after that newline.  */
        !           915:   ep = *compute_motion (pos, vpos, val.hpos, tem,
        !           916:                        height, - (1 << (SHORTBITS - 1)),
        !           917:                        width, hscroll, pos_tab_offset (w, bp.bufpos));
        !           918: 
        !           919:   /* If changes reach past the text available on the screen,
        !           920:      just display rest of screen.  */
        !           921:   if (ep.bufpos > bf_s1 + bf_s2 + 1 - XFASTINT (w->window_end_pos))
        !           922:     stop_vpos = height;
        !           923:   else
        !           924:     stop_vpos = ep.vpos;
        !           925: 
        !           926:   /* If no newline before ep, the line ep is on includes some changes
        !           927:      that must be displayed.  Make sure we don't stop before it.  */
        !           928:   /* Also, if changes reach all the way until ep.bufpos,
        !           929:      it is possible that something was deleted after the
        !           930:      newline before it, so the following line must be redrawn. */
        !           931:   if (stop_vpos == ep.vpos
        !           932:       && (ep.bufpos == FirstCharacter
        !           933:          || CharAt (ep.bufpos - 1) != '\n'
        !           934:          || ep.bufpos == bf_s1 + bf_s2 + 1 - end_unchanged))
        !           935:     stop_vpos = ep.vpos + 1;
        !           936: 
        !           937:   point_vpos = -1;
        !           938: 
        !           939:   /* If changes do not reach to bottom of window,
        !           940:      figure out how much to scroll the rest of the window */
        !           941:   if (stop_vpos < height)
        !           942:     {
        !           943:       /* Now determine how far up or down the rest of the window has moved */
        !           944:       epto = pos_tab_offset (w, ep.bufpos);
        !           945:       xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
        !           946:                            bf_s1 + bf_s2 + 1 - XFASTINT (w->window_end_pos),
        !           947:                            10000, 0, width, hscroll, epto);
        !           948:       scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
        !           949: 
        !           950:       /* Is everything on screen below the changes whitespace?
        !           951:         If so, no scrolling is really necessary.  */
        !           952:       for (i = ep.bufpos; i < xp.bufpos; i++)
        !           953:        {
        !           954:          tem = CharAt (i);
        !           955:          if (tem != ' ' && tem != '\n' && tem != '\t')
        !           956:            break;
        !           957:        }
        !           958:       if (i == xp.bufpos)
        !           959:        return -2;
        !           960: 
        !           961:       XFASTINT (w->window_end_vpos) += scroll_amount;
        !           962: 
        !           963:       /* Before doing any scrolling, verify that point will be on screen. */
        !           964:       if (point > ep.bufpos && !(point <= xp.bufpos && xp.bufpos < height))
        !           965:        {
        !           966:          if (point <= xp.bufpos)
        !           967:            {
        !           968:              pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
        !           969:                                    point, height, - (1 << (SHORTBITS - 1)),
        !           970:                                    width, hscroll, epto);
        !           971:            }
        !           972:          else
        !           973:            {
        !           974:              pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos,
        !           975:                                    point, height, - (1 << (SHORTBITS - 1)),
        !           976:                                    width, hscroll, pos_tab_offset (w, xp.bufpos));
        !           977:            }
        !           978:          if (pp.bufpos < point || pp.vpos == height)
        !           979:            return 0;
        !           980:          point_vpos = pp.vpos + top;
        !           981:          point_hpos = pp.hpos + XFASTINT (w->left);
        !           982:        }
        !           983: 
        !           984:       if (stop_vpos - scroll_amount >= height
        !           985:          || ep.bufpos == xp.bufpos)
        !           986:        {
        !           987:          if (scroll_amount < 0)
        !           988:            stop_vpos -= scroll_amount;
        !           989:          scroll_amount = 0;
        !           990:          /* In this path, we have altered window_end_vpos
        !           991:             and not left it negative.
        !           992:             We must make sure that, in case display is preempted
        !           993:             before the screen changes to reflect what we do here,
        !           994:             further updates will not come to try_window_id
        !           995:             and assume the screen and window_end_vpos match.  */
        !           996:          blank_end_of_window = 1;
        !           997:        }
        !           998:       else if (!scroll_amount)
        !           999:        {}
        !          1000:       else if (bp.bufpos == bf_s1 + bf_s2 + 1 - end_unchanged)
        !          1001:        {
        !          1002:          /* If reprinting everything is nearly as fast as scrolling,
        !          1003:             don't bother scrolling.  Can happen if lines are short.  */
        !          1004:          if (scroll_cost (bp.vpos + top - scroll_amount,
        !          1005:                           top + height - max (0, scroll_amount),
        !          1006:                           scroll_amount)
        !          1007:              > xp.bufpos - bp.bufpos - 20)
        !          1008:            /* Return "try normal display with same window-start."
        !          1009:               Too bad we can't prevent further scroll-thinking.  */
        !          1010:            return -2;
        !          1011:          /* If pure deletion, scroll up as many lines as possible.
        !          1012:             In common case of killing a line, this can save the
        !          1013:             following line from being overwritten by scrolling
        !          1014:             and therefore having to be redrawn.  */
        !          1015:          tem = scroll_screen_lines (bp.vpos + top - scroll_amount,
        !          1016:                                     top + height - max (0, scroll_amount),
        !          1017:                                     scroll_amount);
        !          1018:          if (!tem) stop_vpos = height;
        !          1019:        }
        !          1020:       else if (scroll_amount)
        !          1021:        {
        !          1022:          /* If reprinting everything is nearly as fast as scrolling,
        !          1023:             don't bother scrolling.  Can happen if lines are short.  */
        !          1024:          /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an
        !          1025:             overestimate of cost of reprinting, since xp.bufpos
        !          1026:             would end up below the bottom of the window.  */
        !          1027:          if (scroll_cost (ep.vpos + top - scroll_amount,
        !          1028:                           top + height - max (0, scroll_amount),
        !          1029:                           scroll_amount)
        !          1030:              > xp.bufpos - ep.bufpos - 20)
        !          1031:            /* Return "try normal display with same window-start."
        !          1032:               Too bad we can't prevent further scroll-thinking.  */
        !          1033:            return -2;
        !          1034:          tem = scroll_screen_lines (ep.vpos + top - scroll_amount,
        !          1035:                                     top + height - max (0, scroll_amount),
        !          1036:                                     scroll_amount);
        !          1037:          if (!tem) stop_vpos = height;
        !          1038:        }
        !          1039:     }
        !          1040: 
        !          1041:   /* In any case, do not display past bottom of window */
        !          1042:   if (stop_vpos >= height)
        !          1043:     {
        !          1044:       stop_vpos = height;
        !          1045:       scroll_amount = 0;
        !          1046:     }
        !          1047: 
        !          1048:   /* Handle case where pos is before w->start --
        !          1049:      can happen if part of line had been clipped and is not clipped now */
        !          1050:   if (vpos == 0 && pos < marker_position (w->start))
        !          1051:     Fset_marker (w->start, make_number (pos), Qnil);
        !          1052: 
        !          1053:   /* Redisplay the lines where the text was changed */
        !          1054:   last_text_vpos = vpos;
        !          1055:   tab_offset = pos_tab_offset (w, pos);
        !          1056:   if (val.hpos < 0)
        !          1057:     tab_offset += XFASTINT (w->width) - 1;
        !          1058:   while (vpos < stop_vpos)
        !          1059:     {
        !          1060:       val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
        !          1061:       tab_offset += XFASTINT (w->width) - 1;
        !          1062:       if (val.vpos) tab_offset = 0;
        !          1063:       if (pos != val.bufpos)
        !          1064:        last_text_vpos
        !          1065:          /* Next line, unless prev line ended in end of buffer with no cr */
        !          1066:            = vpos - (val.vpos && CharAt (val.bufpos - 1) != '\n');
        !          1067:       pos = val.bufpos;
        !          1068:     }
        !          1069: 
        !          1070:   /* There are two cases:
        !          1071:      1) we have displayed down to the bottom of the window
        !          1072:      2) we have scrolled lines below stop_vpos by scroll_amount  */
        !          1073: 
        !          1074:   if (vpos == height)
        !          1075:     {
        !          1076:       /* If last line is continued in middle of character,
        !          1077:         include the split character in the text considered on the screen */
        !          1078:       if (val.hpos < lmargin)
        !          1079:        val.bufpos++;
        !          1080:       XFASTINT (w->window_end_vpos) = last_text_vpos;
        !          1081:       XFASTINT (w->window_end_pos) = bf_s1 + bf_s2 + 1 - val.bufpos;
        !          1082:     }
        !          1083: 
        !          1084:   /* If scrolling made blank lines at window bottom,
        !          1085:      redisplay to fill those lines */
        !          1086:   if (scroll_amount < 0)
        !          1087:     {
        !          1088:       vpos = xp.vpos;
        !          1089:       pos = xp.bufpos;
        !          1090:       val.hpos = lmargin;
        !          1091:       if (pos == NumCharacters + 1)
        !          1092:        vpos = height + scroll_amount;
        !          1093:       else if (xp.contin && xp.hpos != lmargin)
        !          1094:        {
        !          1095:          val.hpos = xp.prevhpos - width + lmargin;
        !          1096:          pos--;
        !          1097:        }
        !          1098: 
        !          1099:       blank_end_of_window = 1;
        !          1100:       tab_offset = pos_tab_offset (w, pos);
        !          1101:       if (val.hpos < 0)
        !          1102:        tab_offset += XFASTINT (w->width) - 1;
        !          1103: 
        !          1104:       while (vpos < height)
        !          1105:        {
        !          1106:          val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
        !          1107:          tab_offset += XFASTINT (w->width) - 1;
        !          1108:          if (val.vpos) tab_offset = 0;
        !          1109:          pos = val.bufpos;
        !          1110:        }
        !          1111: 
        !          1112:       /* Here is a case where display_line_text sets point_vpos wrong.
        !          1113:         Make it be fixed up, below.  */
        !          1114:       if (xp.bufpos == NumCharacters + 1
        !          1115:          && xp.bufpos == point)
        !          1116:        point_vpos = -1;
        !          1117:     }
        !          1118: 
        !          1119:   /* Attempt to adjust end-of-text positions to new bottom line */
        !          1120:   if (scroll_amount)
        !          1121:     {
        !          1122:       delta = height - xp.vpos;
        !          1123:       if (delta < 0
        !          1124:          || (delta > 0 && xp.bufpos <= NumCharacters)
        !          1125:          || (delta == 0 && xp.hpos))
        !          1126:        {
        !          1127:          val = *vmotion (bf_s1 + bf_s2 + 1 - XFASTINT (w->window_end_pos),
        !          1128:                          delta, width, hscroll, window);
        !          1129:          XFASTINT (w->window_end_pos) = bf_s1 + bf_s2 + 1 - val.bufpos;
        !          1130:          XFASTINT (w->window_end_vpos) += val.vpos;
        !          1131:        }
        !          1132:     }
        !          1133: 
        !          1134:   w->window_end_valid = Qnil;
        !          1135: 
        !          1136:   /* If point was not in a line that was displayed, find it */
        !          1137:   if (point_vpos < 0)
        !          1138:     {
        !          1139:       val = *compute_motion (start, 0, lmargin, point, 10000, 10000,
        !          1140:                             width, hscroll, pos_tab_offset (w, start));
        !          1141:       /* Admit failure if point is off screen now */
        !          1142:       if (val.vpos >= height)
        !          1143:        {
        !          1144:          for (vpos = 0; vpos < height; vpos++)
        !          1145:            cancel_line (vpos + top);
        !          1146:          return 0;
        !          1147:        }
        !          1148:       point_vpos = val.vpos + top;
        !          1149:       point_hpos = val.hpos + XFASTINT (w->left);
        !          1150:     }
        !          1151: 
        !          1152:   cursX = max (0, point_hpos);
        !          1153:   cursY = point_vpos;
        !          1154: 
        !          1155:   if (debug_end_pos)
        !          1156:     {
        !          1157:       val = *compute_motion (start, 0, lmargin, NumCharacters + 1,
        !          1158:                             height, - (1 << (SHORTBITS - 1)),
        !          1159:                             width, hscroll, pos_tab_offset (w, start));
        !          1160:       if (val.vpos != XFASTINT (w->window_end_vpos))
        !          1161:        abort ();
        !          1162:       if (XFASTINT (w->window_end_pos)
        !          1163:          != bf_s1 + bf_s2 + 1 - val.bufpos)
        !          1164:        abort ();
        !          1165:     }
        !          1166: 
        !          1167:   return 1;
        !          1168: }
        !          1169: 
        !          1170: /* Display one line of window w, starting at position `start' in w's buffer.
        !          1171:  Display starting at horizontal position `hpos',
        !          1172:   which is normally zero or negative.
        !          1173:   A negative value causes output up to hpos = 0 to be discarded.
        !          1174:   This is done for negative hscroll, or when this is a continuation line
        !          1175:   and the continuation occurred in the middle of a multi-column character.
        !          1176: 
        !          1177:  `taboffset' is an offset for ostensible hpos, used in tab stop calculations.
        !          1178: 
        !          1179:  Display on position `vpos' on the screen.  (origin 0).
        !          1180: 
        !          1181:  Returns a `struct position' giving character to start next line with
        !          1182:  and where to display it, including a zero or negative hpos.
        !          1183:  The vpos field is not really a vpos; it is 1 unless the line is continued */
        !          1184: 
        !          1185: struct position val_display_text_line;
        !          1186: 
        !          1187: struct position *
        !          1188: display_text_line (w, start, vpos, hpos, taboffset)
        !          1189:      struct window *w;
        !          1190:      int start;
        !          1191:      int vpos;
        !          1192:      int hpos;
        !          1193:      int taboffset;
        !          1194: {
        !          1195:   register int pos = start;
        !          1196:   register int c;
        !          1197:   register char *p1;
        !          1198:   int end;
        !          1199:   register int pause;
        !          1200:   register unsigned char *p;
        !          1201:   char *endp;
        !          1202:   register char *startp;
        !          1203:   register char *p1prev;
        !          1204:   register struct display_line *line;
        !          1205:   int tab_width = XINT (bf_cur->tab_width);
        !          1206:   int ctl_arrow = !NULL (bf_cur->ctl_arrow);
        !          1207:   int width = XFASTINT (w->width) - 1
        !          1208:     - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width);
        !          1209:   struct position val;
        !          1210:   int lastpos;
        !          1211:   int invis;
        !          1212:   int hscroll = XINT (w->hscroll);
        !          1213:   int truncate = hscroll
        !          1214:     || (truncate_partial_width_windows
        !          1215:        && XFASTINT (w->width) < screen_width)
        !          1216:     || !NULL (bf_cur->truncate_lines);
        !          1217:   int selective
        !          1218:     = XTYPE (bf_cur->selective_display) == Lisp_Int
        !          1219:       ? XINT (bf_cur->selective_display)
        !          1220:        : !NULL (bf_cur->selective_display) ? -1 : 0;
        !          1221:   int selective_e = selective && !NULL (bf_cur->selective_display_ellipses);
        !          1222: 
        !          1223:   hpos += XFASTINT (w->left);
        !          1224:   line = get_display_line (vpos, XFASTINT (w->left));
        !          1225:   if (tab_width <= 0 || tab_width > 20) tab_width = 8;
        !          1226: 
        !          1227:   if (w == XWINDOW (minibuf_window) && start == 1
        !          1228:       && vpos == XFASTINT (w->top))
        !          1229:     {
        !          1230:       if (minibuf_prompt)
        !          1231:        hpos = display_string (w, line, minibuf_prompt, hpos,
        !          1232:                               !truncate ? '\\' : '$', -1, -1);
        !          1233:       minibuf_prompt_width = hpos;
        !          1234:     }
        !          1235: 
        !          1236:   p1 = line->body + hpos;
        !          1237: 
        !          1238:   end = NumCharacters + 1;
        !          1239: 
        !          1240:   startp = line->body + XFASTINT (w->left);
        !          1241:   endp = startp + width;
        !          1242: 
        !          1243:   /* Loop generating characters.
        !          1244:    Stop at end of buffer, before newline,
        !          1245:    or if reach or pass continuation column.  */
        !          1246: 
        !          1247:   pause = pos;
        !          1248:   while (p1 < endp)
        !          1249:     {
        !          1250:       p1prev = p1;
        !          1251:       if (pos == pause)
        !          1252:        {
        !          1253:          if (pos == end)
        !          1254:            break;
        !          1255:          if (pos == point && point_vpos < 0)
        !          1256:            {
        !          1257:              point_vpos = vpos;
        !          1258:              point_hpos = p1 - startp;
        !          1259:            }
        !          1260: 
        !          1261:          pause = end;
        !          1262:          if (pos < point && point < pause)
        !          1263:            pause = point;
        !          1264:          if (pos <= bf_s1 && bf_s1 + 1 < pause)
        !          1265:            pause = bf_s1 + 1;
        !          1266: 
        !          1267:          p = &CharAt (pos);
        !          1268:        }
        !          1269:       c = *p++;
        !          1270:       if (c >= 040 && c < 0177)
        !          1271:        {
        !          1272:          if (p1 >= startp)
        !          1273:            *p1 = c;
        !          1274:          p1++;
        !          1275:        }
        !          1276:       else if (c == '\n')
        !          1277:        {
        !          1278:          invis = 0;
        !          1279:          while (pos < end
        !          1280:                 && selective > 0
        !          1281:                 && position_indentation (pos + 1) >= selective)
        !          1282:            {
        !          1283:              invis = 1;
        !          1284:              pos = find_next_newline (pos + 1, 1);
        !          1285:              if (CharAt (pos - 1) == '\n')
        !          1286:                pos--;
        !          1287:            }
        !          1288:          if (invis && selective_e)
        !          1289:            {
        !          1290:              p1 += 4;
        !          1291:              if (p1 - startp > width)
        !          1292:                p1 = endp;
        !          1293:              strncpy (p1prev, " ...", p1 - p1prev);
        !          1294:            }
        !          1295:          break;
        !          1296:        }
        !          1297:       else if (c == '\t')
        !          1298:        {
        !          1299:          do
        !          1300:            {
        !          1301:              if (p1 >= startp)
        !          1302:                *p1 = ' ';
        !          1303:              p1++;
        !          1304:            }
        !          1305:          while ((p1 - startp + taboffset + hscroll - (hscroll > 0))
        !          1306:                 % tab_width);
        !          1307:        }
        !          1308:       else if (c == Ctl('M') && selective == -1)
        !          1309:        {
        !          1310:          pos = find_next_newline (pos, 1);
        !          1311:          if (CharAt (pos - 1) == '\n')
        !          1312:            pos--;
        !          1313:          if (selective_e)
        !          1314:            {
        !          1315:              p1 += 4;
        !          1316:              if (p1 - startp > width)
        !          1317:                p1 = endp;
        !          1318:              strncpy (p1prev, " ...", p1 - p1prev);
        !          1319:            }
        !          1320:          break;
        !          1321:        }
        !          1322:       else if (c < 0200 && ctl_arrow)
        !          1323:        {
        !          1324:          if (p1 >= startp)
        !          1325:            *p1 = '^';
        !          1326:          p1++;
        !          1327:          if (p1 >= startp)
        !          1328:            *p1 = c ^ 0100;
        !          1329:          p1++;
        !          1330:        }
        !          1331:       else
        !          1332:        {
        !          1333:          if (p1 >= startp)
        !          1334:            *p1 = '\\';
        !          1335:          p1++;
        !          1336:          if (p1 >= startp)
        !          1337:            *p1 = (c >> 6) + '0';
        !          1338:          p1++;
        !          1339:          if (p1 >= startp)
        !          1340:            *p1 = (7 & (c >> 3)) + '0';
        !          1341:          p1++;
        !          1342:          if (p1 >= startp)
        !          1343:            *p1 = (7 & c) + '0';
        !          1344:          p1++;
        !          1345:        }
        !          1346:       pos++;
        !          1347:     }
        !          1348: 
        !          1349:   val.hpos = - XINT (w->hscroll);
        !          1350:   if (val.hpos)
        !          1351:     val.hpos++;
        !          1352: 
        !          1353:   val.vpos = 1;
        !          1354: 
        !          1355:   lastpos = pos;
        !          1356: 
        !          1357:   /* Handle continuation in middle of a character */
        !          1358:   /* by backing up over it */
        !          1359:   if (p1 > endp)
        !          1360:     {
        !          1361:       /* Start the next line with that same character */
        !          1362:       pos--;
        !          1363:       /* but at a negative hpos, to skip the columns output on this line.  */
        !          1364:       val.hpos += p1prev - endp;
        !          1365:       /* Keep in this line everything up to the continuation column.  */
        !          1366:       p1 = endp;
        !          1367:     }
        !          1368: 
        !          1369:   /* Finish deciding which character to start the next line on,
        !          1370:      and what hpos to start it at.
        !          1371:      Also set `lastpos' to the last position which counts as "on this line"
        !          1372:      for cursor-positioning.  */
        !          1373: 
        !          1374:   if (pos < NumCharacters + 1)
        !          1375:     {
        !          1376:       if (CharAt (pos) == '\n')
        !          1377:        /* If stopped due to a newline, start next line after it */
        !          1378:        pos++;
        !          1379:       else
        !          1380:        /* Stopped due to right margin of window */
        !          1381:        {
        !          1382:          if (truncate)
        !          1383:            {
        !          1384:              *p1++ = '$';
        !          1385:              /* Truncating => start next line after next newline,
        !          1386:                 and point is on this line if it is before the newline,
        !          1387:                 and skip none of first char of next line */
        !          1388:              pos = find_next_newline (pos, 1);
        !          1389:              val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
        !          1390: 
        !          1391:              lastpos = pos - (CharAt (pos - 1) == '\n');
        !          1392:            }
        !          1393:          else
        !          1394:            {
        !          1395:              *p1++ = '\\';
        !          1396:              val.vpos = 0;
        !          1397:              lastpos--;
        !          1398:            }
        !          1399:        }
        !          1400:     }
        !          1401: 
        !          1402:   /* If point is at eol or in invisible text at eol,
        !          1403:      record its screen location now.  */
        !          1404: 
        !          1405:   if (start <= point && point <= lastpos && point_vpos < 0)
        !          1406:     {
        !          1407:       point_vpos = vpos;
        !          1408:       point_hpos = p1 - startp;
        !          1409:     }
        !          1410: 
        !          1411:   if (point_vpos == vpos)
        !          1412:     {
        !          1413:       if (point_hpos < 0) point_hpos = 0;
        !          1414:       if (point_hpos > width) point_hpos = width;
        !          1415:       point_hpos += XFASTINT (w->left);
        !          1416:       if (w == XWINDOW (selected_window))
        !          1417:        {
        !          1418:          cursY = point_vpos;
        !          1419:          cursX = point_hpos;
        !          1420: 
        !          1421:          /* Line is not continued and did not start in middle of character */
        !          1422:          if (hpos == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0)
        !          1423:              && val.vpos)
        !          1424:            {
        !          1425:              this_line_bufpos = start;
        !          1426:              this_line_buffer = bf_cur;
        !          1427:              this_line_vpos = point_vpos;
        !          1428:              this_line_start_hpos = hpos;
        !          1429:              this_line_endpos = bf_s1 + bf_s2 + 1 - lastpos;
        !          1430:            }
        !          1431:          else
        !          1432:            this_line_bufpos = 0;
        !          1433:        }
        !          1434:     }
        !          1435: 
        !          1436:   /* If hscroll and line not empty, insert truncation-at-left marker */
        !          1437:   if (hscroll && lastpos != start)
        !          1438:     {
        !          1439:       *startp = '$';
        !          1440:       if (p1 <= startp)
        !          1441:        p1 = startp + 1;
        !          1442:     }
        !          1443: 
        !          1444:   if (XFASTINT (w->width) + XFASTINT (w->left) != screen_width)
        !          1445:     {
        !          1446:       endp++;
        !          1447:       if (p1 < startp) p1 = startp;
        !          1448:       while (p1 < endp) *p1++ = ' ';
        !          1449:       *p1++ = '|';
        !          1450:     }
        !          1451:   line->length = max (line->length, p1 - line->body);
        !          1452:   line->body[line->length] = 0;
        !          1453: 
        !          1454:   /* If the start of this line is the overlay arrow-position,
        !          1455:      then put the arrow string into the display-line.  */
        !          1456: 
        !          1457:   if (XTYPE (Voverlay_arrow_position) == Lisp_Marker
        !          1458:       && bf_cur == XMARKER (Voverlay_arrow_position)->buffer
        !          1459:       && start == marker_position (Voverlay_arrow_position)
        !          1460:       && XTYPE (Voverlay_arrow_string) == Lisp_String)
        !          1461:     {
        !          1462:       unsigned char *p = XSTRING (Voverlay_arrow_string)->data;
        !          1463:       int len = XSTRING (Voverlay_arrow_string)->size;
        !          1464:       if (len > XFASTINT (w->width) - 1)
        !          1465:        len = XFASTINT (w->width) - 1;
        !          1466:       bcopy (p, startp, len);
        !          1467:       if (line->length < len + startp - line->body)
        !          1468:        line->length = len + startp - line->body;
        !          1469:     }
        !          1470: 
        !          1471:   val.bufpos = pos;
        !          1472:   val_display_text_line = val;
        !          1473:   return &val_display_text_line;
        !          1474: }
        !          1475: 
        !          1476: /* Display the mode line for window w */
        !          1477: 
        !          1478: display_mode_line (w)
        !          1479:      struct window *w;
        !          1480: {
        !          1481:   register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
        !          1482:   register int left = XFASTINT (w->left);
        !          1483:   register int right = XFASTINT (w->width) + left;
        !          1484:   register struct display_line *line = get_display_line (vpos, left);
        !          1485: 
        !          1486:   display_mode_element (w, line, left, 0, right, right,
        !          1487:                        bf_cur->mode_line_format);
        !          1488: 
        !          1489:   /* Make the mode line inverse video if the entire line
        !          1490:      is made of mode lines.
        !          1491:      I.e. if this window is full width,
        !          1492:      or if it is the child of a full width window
        !          1493:      (which implies that that window is split side-by-side
        !          1494:      and the rest of this line is mode lines of the sibling windows).  */
        !          1495:   if (XFASTINT (w->width) == screen_width ||
        !          1496:       XFASTINT (XWINDOW (w->parent)->width) == screen_width)
        !          1497:     line->highlighted = mode_line_inverse_video;
        !          1498: 
        !          1499: }
        !          1500: 
        !          1501: /* Contribute ELT to the mode line for window W.
        !          1502:    How it translates into text depends on its data type.
        !          1503: 
        !          1504:    LINE is the display-line that the mode line is being displayed in.
        !          1505: 
        !          1506:    HPOS is the position (absolute on screen) where this element's text
        !          1507:    should start.  The output is truncated automatically at the right
        !          1508:    edge of window W.
        !          1509: 
        !          1510:    DEPTH is the depth in recursion.  It is used to prevent
        !          1511:    infinite recursion here.
        !          1512: 
        !          1513:    MINENDCOL is the hpos before which the element may not end.
        !          1514:    The element is padded at the right with spaces if nec
        !          1515:    to reach this column.
        !          1516: 
        !          1517:    MAXENDCOL is the hpos past which this element may not extend.
        !          1518:    If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority.
        !          1519:    (This is necessary to make nested padding and truncation work.)
        !          1520: 
        !          1521:    Returns the hpos of the end of the text generated by ELT.
        !          1522:    The next element will receive that value as its HPOS arg,
        !          1523:    so as to concatenate the elements.  */
        !          1524: 
        !          1525: int
        !          1526: display_mode_element (w, line, hpos, depth, minendcol, maxendcol, elt)
        !          1527:      struct window *w;
        !          1528:      struct display_line *line;
        !          1529:      register int hpos;
        !          1530:      int depth;
        !          1531:      int minendcol;
        !          1532:      register int maxendcol;
        !          1533:      register Lisp_Object elt;
        !          1534: {
        !          1535:  tail_recurse:
        !          1536:   if (depth > 10)
        !          1537:     goto invalid;
        !          1538: 
        !          1539:   depth++;
        !          1540: 
        !          1541: #ifdef SWITCH_ENUM_BUG
        !          1542:   switch ((int) XTYPE (elt))
        !          1543: #else
        !          1544:   switch (XTYPE (elt))
        !          1545: #endif
        !          1546:     {
        !          1547:     case Lisp_String:
        !          1548:       {
        !          1549:        /* A string: output it and check for %-constructs within it.  */
        !          1550:        register unsigned char c;
        !          1551:        register unsigned char *this = XSTRING (elt)->data;
        !          1552: 
        !          1553:        while (hpos < maxendcol && *this)
        !          1554:          {
        !          1555:            unsigned char *last = this;
        !          1556:            while ((c = *this++) != '\0' && c != '%')
        !          1557:              ;
        !          1558:            if (this - 1 != last)
        !          1559:              {
        !          1560:                register int lim = --this - last + hpos;
        !          1561:                hpos = display_string (w, line, last, hpos, 0, hpos,
        !          1562:                                       min (lim, maxendcol));
        !          1563:              }
        !          1564:            else /* c == '%' */
        !          1565:              {
        !          1566:                register int spec_width = 0;
        !          1567: 
        !          1568:                /* We can't allow -ve args due to the "%-" construct */
        !          1569:                /* Argument specifies minwidth but not maxwidth
        !          1570:                   (maxwidth can be specified by
        !          1571:                     (<negative-number> . <stuff>) mode-line elements) */
        !          1572: 
        !          1573:                while ((c = *this++) >= '0' && c <= '9')
        !          1574:                  {
        !          1575:                    spec_width = spec_width * 10 + (c - '0');
        !          1576:                  }
        !          1577: 
        !          1578:                spec_width += hpos;
        !          1579:                if (spec_width > maxendcol)
        !          1580:                  spec_width = maxendcol;
        !          1581: 
        !          1582:                if (c == 'M')
        !          1583:                  hpos = display_mode_element (w, line, hpos, depth,
        !          1584:                                               spec_width, maxendcol,
        !          1585:                                               Vglobal_mode_string);
        !          1586:                else if (c != 0)
        !          1587:                  hpos = display_string (w, line,
        !          1588:                                         decode_mode_spec (w, c,
        !          1589:                                                           maxendcol - hpos),
        !          1590:                                         hpos, 0, spec_width, maxendcol);
        !          1591:              }
        !          1592:          }
        !          1593:       }
        !          1594:       break;
        !          1595: 
        !          1596:     case Lisp_Symbol:
        !          1597:       /* A symbol: process the value of the symbol recursively
        !          1598:         as if it appeared here directly.  Avoid error if symbol void.
        !          1599:         Special case: if value of symbol is a string, output the string
        !          1600:         literally.  */
        !          1601:       {
        !          1602:        register Lisp_Object tem;
        !          1603:        tem = Fboundp (elt);
        !          1604:        if (!NULL (tem))
        !          1605:          {
        !          1606:            tem = Fsymbol_value (elt);
        !          1607:            /* If value is a string, output that string literally:
        !          1608:               don't check for % within it.  */
        !          1609:            if (XTYPE (tem) == Lisp_String)
        !          1610:              hpos = display_string (w, line, XSTRING (tem)->data,
        !          1611:                                     hpos, 0, minendcol, maxendcol);
        !          1612:            /* Give up right away for nil or t.  */
        !          1613:            else if (!EQ (tem, elt))
        !          1614:              { elt = tem; goto tail_recurse; }
        !          1615:          }
        !          1616:       }
        !          1617:       break;
        !          1618: 
        !          1619:     case Lisp_Cons:
        !          1620:       {
        !          1621:        register Lisp_Object car, tem;
        !          1622: 
        !          1623:        /* A cons cell: three distinct cases.
        !          1624:           If first element is a string or a cons, process all the elements
        !          1625:           and effectively concatenate them.
        !          1626:           If first element is a negative number, truncate displaying cdr to
        !          1627:           at most that many characters.  If positive, pad (with spaces)
        !          1628:           to at least that many characters.
        !          1629:           If first element is a symbol, process the cadr or caddr recursively
        !          1630:           according to whether the symbol's value is non-nil or nil.  */
        !          1631:        car = XCONS (elt)->car;
        !          1632:        if (XTYPE (car) == Lisp_Symbol)
        !          1633:          {
        !          1634:            tem = Fboundp (car);
        !          1635:            elt = XCONS (elt)->cdr;
        !          1636:            if (XTYPE (elt) != Lisp_Cons)
        !          1637:              goto invalid;
        !          1638:            /* elt is now the cdr, and we know it is a cons cell.
        !          1639:               Use its car if CAR has a non-nil value.  */
        !          1640:            if (!NULL (tem))
        !          1641:              {
        !          1642:                tem = Fsymbol_value (car);
        !          1643:                if (!NULL (tem))
        !          1644:                  { elt = XCONS (elt)->car; goto tail_recurse; }
        !          1645:              }
        !          1646:            /* Symbol's value is nil (or symbol is unbound)
        !          1647:               Get the cddr of the original list
        !          1648:               and if possible find the caddr and use that.  */
        !          1649:            elt = XCONS (elt)->cdr;
        !          1650:            if (NULL (elt))
        !          1651:              break;
        !          1652:            else if (XTYPE (elt) != Lisp_Cons)
        !          1653:              goto invalid;
        !          1654:            elt = XCONS (elt)->car;
        !          1655:            goto tail_recurse;
        !          1656:          }
        !          1657:        else if (XTYPE (car) == Lisp_Int)
        !          1658:          {
        !          1659:            register int lim = XINT (car);
        !          1660:            elt = XCONS (elt)->cdr;
        !          1661:            if (lim < 0)
        !          1662:              /* Negative int means reduce maximum width.
        !          1663:                 DO NOT change MINENDCOL here!
        !          1664:                 (20 -10 . foo) should truncate foo to 10 col
        !          1665:                 and then pad to 20.  */
        !          1666:              maxendcol = min (maxendcol, hpos - lim);
        !          1667:            else if (lim > 0)
        !          1668:              {
        !          1669:                /* Padding specified.  Don't let it be more than
        !          1670:                   current maximum.  */
        !          1671:                lim += hpos;
        !          1672:                if (lim > maxendcol)
        !          1673:                  lim = maxendcol;
        !          1674:                /* If that's more padding than already wanted, queue it.
        !          1675:                   But don't reduce padding already specified even if
        !          1676:                   that is beyond the current truncation point.  */
        !          1677:                if (lim > minendcol)
        !          1678:                  minendcol = lim;
        !          1679:              }
        !          1680:            goto tail_recurse;
        !          1681:          }
        !          1682:        else if (XTYPE (car) == Lisp_String || XTYPE (car) == Lisp_Cons)
        !          1683:          {
        !          1684:            register int limit = 50;
        !          1685:            /* LIMIT is to protect against circular lists.  */
        !          1686:            while (XTYPE (elt) == Lisp_Cons && --limit > 0
        !          1687:                   && hpos < maxendcol)
        !          1688:              {
        !          1689:                hpos = display_mode_element (w, line, hpos, depth,
        !          1690:                                             hpos, maxendcol,
        !          1691:                                             XCONS (elt)->car);
        !          1692:                elt = XCONS (elt)->cdr;
        !          1693:              }
        !          1694:          }
        !          1695:       }
        !          1696:       break;
        !          1697: 
        !          1698:     default:
        !          1699:     invalid:
        !          1700:       return (display_string (w, line, "*invalid*", hpos, 0,
        !          1701:                              minendcol, maxendcol));
        !          1702:     }
        !          1703: 
        !          1704:  end:
        !          1705:   if (minendcol > hpos)
        !          1706:     hpos = display_string (w, line, "", hpos, 0, minendcol, -1);
        !          1707:   return hpos;
        !          1708: }
        !          1709: 
        !          1710: 
        !          1711: char decode_mode_spec_buf[MScreenWidth + 1];
        !          1712: 
        !          1713: static char *
        !          1714: fmodetrunc (str, width, buf)
        !          1715:      char *str, *buf;
        !          1716:      long width;
        !          1717: {
        !          1718:   register char *bp = buf;
        !          1719:   register long len;
        !          1720:     
        !          1721:   len = strlen (str);
        !          1722:   if (width && width < len)
        !          1723:     {
        !          1724:       strcpy (buf, str + len - width);
        !          1725:       if (buf[0] != '/')
        !          1726:        while (*bp)
        !          1727:          if (*bp++ == '/')
        !          1728:            {
        !          1729:              bp--;
        !          1730:              *--bp = '$';
        !          1731:              return bp;
        !          1732:            }
        !          1733:       buf[0] = '$';
        !          1734:       return buf;
        !          1735:     }
        !          1736:   return str;
        !          1737: }
        !          1738: 
        !          1739: char *
        !          1740: decode_mode_spec (w, c, maxwidth)
        !          1741:      struct window *w;
        !          1742:      register char c;
        !          1743:      register int maxwidth;
        !          1744: {
        !          1745:   Lisp_Object obj = Qnil;
        !          1746:   char *tbuf = decode_mode_spec_buf;
        !          1747: 
        !          1748:   switch (c)
        !          1749:     {
        !          1750:     case 'b': 
        !          1751:       obj = bf_cur->name;
        !          1752:       if (maxwidth >= 3 && XSTRING (obj)->size > maxwidth)
        !          1753:        {
        !          1754:          bcopy (XSTRING (obj)->data, tbuf, maxwidth - 1);
        !          1755:          tbuf[maxwidth - 1] = '\\';
        !          1756:          tbuf[maxwidth] = '\0';
        !          1757:          return tbuf;
        !          1758:        }
        !          1759:       break;
        !          1760: 
        !          1761:     case 'f': 
        !          1762:       obj = bf_cur->filename;
        !          1763:       if (NULL (obj))
        !          1764:        return "[none]";
        !          1765:       else if (XTYPE (obj) == Lisp_String)
        !          1766:        return fmodetrunc (XSTRING (obj)->data, maxwidth, tbuf);
        !          1767:       break;
        !          1768: 
        !          1769:     case 'm': 
        !          1770:       obj = bf_cur->mode_name;
        !          1771:       break;
        !          1772: 
        !          1773:     case 'n':
        !          1774:       if (bf_head_clip > 1 || bf_tail_clip > 0)
        !          1775:        return " Narrow";
        !          1776:       break;
        !          1777: 
        !          1778: /*  Handled specially in display_mode_element
        !          1779:     case 'M': 
        !          1780:       obj = Vglobal_mode_string;
        !          1781:       break;
        !          1782:  */
        !          1783: 
        !          1784:     case '*':
        !          1785:       return (!NULL (bf_cur->read_only)
        !          1786:              ? "%"
        !          1787:              : ((bf_modified > bf_cur->save_modified)
        !          1788:                 ? "*"
        !          1789:                 : "-"));
        !          1790: 
        !          1791:     case 's':
        !          1792:       /* status of process */
        !          1793: #ifdef subprocesses
        !          1794:       obj = Fget_buffer_process (Fcurrent_buffer ());
        !          1795:       if (NULL (obj))
        !          1796:        return "no process";
        !          1797:       obj = Fsymbol_name (Fprocess_status (obj));
        !          1798:       break;
        !          1799: #else
        !          1800:       return "no processes";
        !          1801: #endif /* subprocesses */
        !          1802: 
        !          1803:     case 'p':
        !          1804:       {
        !          1805:        int pos = marker_position (w->start);
        !          1806:        int total = NumCharacters + 1 - FirstCharacter;
        !          1807: 
        !          1808:        if (XFASTINT (w->window_end_pos) <= bf_tail_clip)
        !          1809:          {
        !          1810:            if (pos <= FirstCharacter)
        !          1811:              return "All";
        !          1812:            else
        !          1813:              return "Bottom";
        !          1814:          }
        !          1815:        else if (pos <= FirstCharacter)
        !          1816:          return "Top";
        !          1817:        else
        !          1818:          {
        !          1819:            total = ((pos - FirstCharacter) * 100 + total - 1) / total;
        !          1820:            /* We can't normally display a 3-digit number,
        !          1821:               so get us a 2-digit number that is close.  */
        !          1822:            if (total == 100)
        !          1823:              total = 99;
        !          1824:            sprintf (tbuf, "%2d%%", total);
        !          1825:            return tbuf;
        !          1826:          }
        !          1827:       }
        !          1828: 
        !          1829:     case '[': 
        !          1830:       if (RecurseDepth - MinibufDepth > 10)
        !          1831:        return "[[[... ";
        !          1832:       else
        !          1833:        return ("[[[[[[[[[[" + 10 - (RecurseDepth - MinibufDepth));
        !          1834: 
        !          1835:     case '%':
        !          1836:       return "%";
        !          1837: 
        !          1838:     case ']': 
        !          1839:       if (RecurseDepth - MinibufDepth > 10)
        !          1840:        return " ...]]]";
        !          1841:       else
        !          1842:        return ("]]]]]]]]]]" + 10 - (RecurseDepth - MinibufDepth));
        !          1843: 
        !          1844:     case '-':
        !          1845:       return "--------------------------------------------------------------------------------------------------------------------------------------------";
        !          1846:     }
        !          1847: 
        !          1848:   if (XTYPE (obj) == Lisp_String)
        !          1849:     return (char *) XSTRING (obj)->data;
        !          1850:   else
        !          1851:     return "";
        !          1852: }
        !          1853: 
        !          1854: /* Display STRING on one line of window W, starting at HPOS.
        !          1855:    Display on the display_line LINE, which should have
        !          1856:    been obtained by get_display_line (vpos, hpos)
        !          1857:    or in some suitable manner.
        !          1858: 
        !          1859:   TRUNCATE is character to display at end if truncated.  Zero for none.
        !          1860: 
        !          1861:   MINCOL is the first column ok to end at.  (Pad with spaces to this col.)
        !          1862:   MAXCOL is the last column ok to end at.  Truncate here.
        !          1863:     -1 for MINCOL or MAXCOL means no explicit minimum or maximum.
        !          1864:   Both count from the left edge of the screen, as does HPOS.
        !          1865:   The right edge of W is an implicit maximum.
        !          1866:   If TRUNCATE is nonzero, the implicit maximum is one column before the edge.
        !          1867: 
        !          1868:   Returns ending hpos */
        !          1869: 
        !          1870: display_string (w, line, string, hpos, truncate, mincol, maxcol)
        !          1871:      struct window *w;
        !          1872:      register struct display_line *line;
        !          1873:      unsigned char *string;
        !          1874:      int hpos;
        !          1875:      char truncate;
        !          1876:      int mincol, maxcol;
        !          1877: {
        !          1878:   register int c;
        !          1879:   register unsigned char *p1;
        !          1880:   int hscroll = XINT (w->hscroll);
        !          1881:   int tab_width = XINT (bf_cur->tab_width);
        !          1882:   register unsigned char *start;
        !          1883:   register unsigned char *end;
        !          1884:   unsigned char *p1start = (unsigned char *) line->body + hpos;
        !          1885:   int window_width = XFASTINT (w->width);
        !          1886: 
        !          1887:   if (tab_width <= 0 || tab_width > 20) tab_width = 8;
        !          1888: 
        !          1889:   p1 = p1start;
        !          1890:   start = (unsigned char *) line->body + XFASTINT (w->left);
        !          1891:   end = start + window_width - (truncate != 0);
        !          1892: 
        !          1893:   if ((window_width + XFASTINT (w->left)) != screen_width)
        !          1894:     *end-- = '|';
        !          1895: 
        !          1896:   if (maxcol >= 0 && end - (unsigned char *) line->body > maxcol)
        !          1897:     end = (unsigned char *) line->body + maxcol;
        !          1898:   if (maxcol >= 0 && mincol > maxcol)
        !          1899:     mincol = maxcol;
        !          1900: 
        !          1901:   while (p1 < end)
        !          1902:     {
        !          1903:       c = *string++;
        !          1904:       if (!c) break;
        !          1905:       if (c >= 040 && c < 0177)
        !          1906:        {
        !          1907:          if (p1 >= start)
        !          1908:            *p1 = c;
        !          1909:          p1++;
        !          1910:        }
        !          1911:       else if (c == '\t')
        !          1912:        {
        !          1913:          do
        !          1914:            {
        !          1915:              if (p1 >= start)
        !          1916:                *p1 = ' ';
        !          1917:              p1++;
        !          1918:            }
        !          1919:          while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
        !          1920:        }
        !          1921:       else if (c < 0200 && buffer_defaults.ctl_arrow)
        !          1922:        {
        !          1923:          if (p1 >= start)
        !          1924:            *p1 = '^';
        !          1925:          p1++;
        !          1926:          if (p1 >= start)
        !          1927:            *p1 = c ^ 0100;
        !          1928:          p1++;
        !          1929:        }
        !          1930:       else
        !          1931:        {
        !          1932:          if (p1 >= start)
        !          1933:            *p1 = '\\';
        !          1934:          p1++;
        !          1935:          if (p1 >= start)
        !          1936:            *p1 = (c >> 6) + '0';
        !          1937:          p1++;
        !          1938:          if (p1 >= start)
        !          1939:            *p1 = (7 & (c >> 3)) + '0';
        !          1940:          p1++;
        !          1941:          if (p1 >= start)
        !          1942:            *p1 = (7 & c) + '0';
        !          1943:          p1++;
        !          1944:        }
        !          1945:     }
        !          1946: 
        !          1947:   if (c)
        !          1948:     {
        !          1949:       p1 = end;
        !          1950:       if (truncate) *p1++ = truncate;
        !          1951:     }
        !          1952:   else if (mincol >= 0)
        !          1953:     {
        !          1954:       end = (unsigned char *) line->body + mincol;
        !          1955:       while (p1 < end)
        !          1956:        *p1++ = ' ';
        !          1957:     }
        !          1958: 
        !          1959:   {
        !          1960:     register int len = p1 - (unsigned char *) line->body;
        !          1961:     if (len > line->length)
        !          1962:       line->length = len;
        !          1963:     line->body[line->length] = 0;
        !          1964:     return len;
        !          1965:   }
        !          1966: }
        !          1967: 
        !          1968: syms_of_xdisp ()
        !          1969: {
        !          1970:   staticpro (&last_arrow_position);
        !          1971:   staticpro (&last_arrow_string);
        !          1972:   last_arrow_position = Qnil;
        !          1973:   last_arrow_string = Qnil;
        !          1974: 
        !          1975:   DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
        !          1976:     "String displayed by mode-line-format's \"%m\" specifiation.");
        !          1977:   Vglobal_mode_string = Qnil;
        !          1978: 
        !          1979:   DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
        !          1980:     "Marker for where to display an arrow on top of the buffer text.\n\
        !          1981: This must be the beginning of a line in order to work.\n\
        !          1982: See also overlay-arrow-string.");
        !          1983:   Voverlay_arrow_position = Qnil;
        !          1984: 
        !          1985:   DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
        !          1986:     "String to display as an arrow.  See also overlay-arrow-position.");
        !          1987:   Voverlay_arrow_string = Qnil;
        !          1988: 
        !          1989:   DEFVAR_INT ("scroll-step", &scroll_step,
        !          1990:     "*The number of lines to try scrolling a window by when point moves out.\n\
        !          1991: If that fails to bring point back on screen, point is centered instead.\n\
        !          1992: If this is zero, point is always centered after it moves off screen.");
        !          1993: 
        !          1994:   DEFVAR_BOOL ("reset-terminal-on-clear", &reset_terminal_on_clear,
        !          1995:     "Non-nil means re-init terminal modes for clear screen as on entry to Emacs.");
        !          1996:   reset_terminal_on_clear = 1;
        !          1997: 
        !          1998:   DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
        !          1999: 
        !          2000:   DEFVAR_BOOL ("truncate-partial-width-windows",
        !          2001:               &truncate_partial_width_windows,
        !          2002:     "*Non-nil means truncate lines in all windows less than full screen wide.");
        !          2003:   truncate_partial_width_windows = 1;
        !          2004: 
        !          2005:   DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
        !          2006:     "*Non-nil means use inverse video, or other suitable display mode, for the mode line.");
        !          2007:   mode_line_inverse_video = 1;
        !          2008: 
        !          2009:   defsubr (&Sredraw_display);
        !          2010: }
        !          2011: 
        !          2012: /* initialize the window system */
        !          2013: init_xdisp ()
        !          2014: {
        !          2015:   Lisp_Object root_window;
        !          2016: #ifndef COMPILER_REGISTER_BUG
        !          2017:   register
        !          2018: #endif COMPILER_REGISTER_BUG
        !          2019:     struct window *mini_w;
        !          2020: 
        !          2021:   this_line_bufpos = 0;
        !          2022: 
        !          2023:   mini_w = XWINDOW (minibuf_window);
        !          2024:   root_window = mini_w->prev;
        !          2025: 
        !          2026:   minibuf_message = 0;
        !          2027:   prev_minibuf_message = 0;
        !          2028: 
        !          2029:   if (!noninteractive)
        !          2030:     {
        !          2031:       XFASTINT (XWINDOW (root_window)->top) = 0;
        !          2032:       set_window_height (root_window, screen_height - 1, 0);
        !          2033:       XFASTINT (mini_w->top) = screen_height - 1;
        !          2034:       set_window_height (minibuf_window, 1, 0);
        !          2035: 
        !          2036:       XFASTINT (XWINDOW (root_window)->width) = screen_width;
        !          2037:       XFASTINT (mini_w->width) = screen_width;
        !          2038:     }
        !          2039: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.