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

unix.superglobalmegacorp.com

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