Annotation of GNUtools/emacs/src/xdisp.c, revision 1.1.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.