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

unix.superglobalmegacorp.com

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