Annotation of 43BSD/contrib/emacs/src/xdisp.c, revision 1.1.1.1

1.1       root        1: /* Display generation from window structure and buffer text.
                      2:    Copyright (C) 1985 Richard M. Stallman.
                      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: #define CURRENT_END_POS(w) \
                     45:   (XFASTINT (w->window_end_pos) < 0 \
                     46:    ? -1 - XFASTINT(w->window_end_pos) \
                     47:    : XFASTINT(w->window_end_pos))
                     48: 
                     49: /* The buffer position of the first character appearing
                     50:  entirely or partially on the current screen line.
                     51:  Or zero, which disables the optimization for the current screen line. */
                     52: int this_line_bufpos;
                     53: 
                     54: /* Number of characters past the end of this line,
                     55:    including the terminating newline */
                     56: int this_line_endpos;
                     57: 
                     58: /* The vertical position of this screen line. */
                     59: int this_line_vpos;
                     60: 
                     61: /* Hpos value for start of display on this screen line.
                     62:  Usually zero, but negative if first character really began on previous line */
                     63: int this_line_hpos;
                     64: 
                     65: /* Buffer that this_line variables are describing. */
                     66: struct buffer *this_line_buffer;
                     67: 
                     68: /* Value of minibuf_message when it was last acted on.
                     69:   If this is nonzero, there is a message on the screen
                     70:   in the minibuffer and it should be erased as soon
                     71:   as it is no longer requested to appear. */
                     72: char *prev_minibuf_message;
                     73: 
                     74: /* Nonzero means truncate lines in all windows less wide than the screen */
                     75: 
                     76: int truncate_partial_width_windows;
                     77: 
                     78: Lisp_Object Vglobal_mode_string;
                     79: 
                     80: Lisp_Object Vglobal_minor_modes;
                     81: 
                     82: /* The number of lines to try scrolling a
                     83:   window by when point leaves the window; if
                     84:   it is <=0 then point is centered in the window */
                     85: int scroll_step;
                     86: 
                     87: /* Nonzero if try_window_id has made blank lines at window bottom
                     88:  since the last redisplay that paused */
                     89: int blank_end_of_window;
                     90: 
                     91: /* Number of windows showing the buffer of the selected window.  */
                     92: static int buffer_shared;
                     93: 
                     94: /* display_text_line sets these to the screen position (origin 0) of point,
                     95:   whether the window is selected or not.
                     96:  Set one to -1 first to determine whether point was found afterwards.  */
                     97: 
                     98: int point_vpos;
                     99: int point_hpos;
                    100: 
                    101: int debug_end_pos;
                    102: 
                    103: extern int default_ctl_arrow;  /* Nonzero means display ctl chars */
                    104:                                /* with uparrow in mode lines, etc */
                    105: 
                    106: int mode_line_inverse_video;   /* Nonzero means display mode line highlighted */
                    107: 
                    108: struct position *display_text_line ();
                    109: 
                    110: char *minibuf_prompt;  /* Prompt to display in front of the minibuffer contents */
                    111: 
                    112: /* Width in columns of current minibuffer prompt.  */
                    113: 
                    114: int minibuf_prompt_width;
                    115: 
                    116: char *minibuf_message; /* Message to display instead of minibuffer contents
                    117:                           This is what the functions error and message make,
                    118:                           and command echoing uses it as well.
                    119:                           It overrides the minibuf_prompt as well as the buffer.  */
                    120: 
                    121: int RecurseDepth;      /* Depth in recursive edits */
                    122: 
                    123: int MinibufDepth;      /* Depth in minibuffer invocations */
                    124: 
                    125: int RedoModes;         /* true iff we should redraw the mode lines
                    126:                           on the next redisplay */
                    127: 
                    128: /* Minimum value of bf_s1 since last redisplay that finished.
                    129:  Valid for current buffer unless Cant1WinOpt is nonzero. */
                    130: 
                    131: int beg_unchanged;
                    132: 
                    133: /* Minimum value of bf_s2 since last redisplay that finished.
                    134:  Valid for current buffer unless Cant1WinOpt is nonzero. */
                    135: 
                    136: int end_unchanged;
                    137: 
                    138: /* bf_modified as of last redisplay that finished;
                    139:  if it matches bf_modified, beg_unchanged and end_unchanged
                    140:  contain no useful information */
                    141: int unchanged_modified;
                    142: 
                    143: /* Nonzero if head_clip or tail_clip of current buffer has changed
                    144:  since last redisplay that finished */
                    145: int clip_changed;
                    146: 
                    147: /* Nonzero if window sizes or contents have changed
                    148:  since last redisplay that finished */
                    149: int windows_or_buffers_changed;
                    150: 
                    151: DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
                    152:   "Clear the screen and output again what is supposed to appear on it.")
                    153:   ()
                    154: {
                    155:   if (screen_height == 0) abort (); /* Some bug zeros some core */
                    156:   set_terminal_modes ();
                    157:   clear_screen ();
                    158:   fflush (stdout);
                    159:   clear_screen_records ();
                    160:   if (screen_height == 0) abort (); /* Some bug zeros some core */
                    161:   windows_or_buffers_changed++;
                    162:   /* Mark all windows as INaccurate,
                    163:      so that every window will have its redisplay done.  */
                    164:   mark_window_display_accurate (XWINDOW (minibuf_window)->prev, 0);
                    165:   if (screen_height == 0) abort (); /* Some bug zeros some core */
                    166:   return Qnil;
                    167: }
                    168: 
                    169: static char message_buf[MScreenWidth + 1];
                    170: 
                    171: /* dump an informative message to the minibuf */
                    172: /* VARARGS 1 */
                    173: message (m, a1, a2, a3)
                    174:      char *m;
                    175: {
                    176:   if (noninteractive)
                    177:     {
                    178:       if (noninteractive_need_newline)
                    179:        putchar ('\n');
                    180:       printf (m, a1, a2, a3);
                    181:       printf ("\n");
                    182:       fflush (stdout);
                    183:     }
                    184:   else if (INTERACTIVE)
                    185:     {
                    186:       doprnt (message_buf, sizeof message_buf - 1, m, &a1);
                    187:       minibuf_message = message_buf;
                    188:       display_minibuf_message ();
                    189:       update_screen (1, 1);
                    190:     }
                    191: }
                    192: 
                    193: /* Specify m, a string, as a message in the minibuf.  */
                    194: message1 (m)
                    195:      char *m;
                    196: {
                    197:   if (noninteractive)
                    198:     {
                    199:       if (noninteractive_need_newline)
                    200:        putchar ('\n');
                    201:       printf ("%s\n", m);
                    202:       fflush (stdout);
                    203:     }
                    204:   else if (INTERACTIVE)
                    205:     {
                    206:       minibuf_message = m;
                    207:       display_minibuf_message ();
                    208:       update_screen (1, 1);
                    209:     }
                    210: }
                    211: 
                    212: display_minibuf_message ()
                    213: {
                    214:   register int vpos;
                    215:   register struct display_line *line;
                    216: 
                    217:   if (screen_garbaged)
                    218:     {
                    219:       Fredraw_display ();
                    220:       screen_garbaged = 0;
                    221:     }
                    222: 
                    223:   if (minibuf_message || !MinibufDepth)
                    224:     {
                    225:       vpos = XFASTINT (XWINDOW (minibuf_window)->top);
                    226:       line = get_display_line (vpos, 0);
                    227:       display_string (XWINDOW (minibuf_window), line,
                    228:                      minibuf_message ? minibuf_message : "",
                    229:                      0, 0, 0);
                    230: 
                    231:       /* If desired cursor location is on this line, put it at end of text */
                    232:       if (cursY == vpos)
                    233:        cursX = line->length;
                    234:     }
                    235:   else if (!EQ (minibuf_window, selected_window))
                    236:     windows_or_buffers_changed++;
                    237: 
                    238:   if (EQ (minibuf_window, selected_window))
                    239:     this_line_bufpos = 0;
                    240: 
                    241:   prev_minibuf_message = minibuf_message;
                    242: }
                    243: 
                    244: /* Do a screen update, taking possible shortcuts into account.
                    245:  This is the main external entry point for redisplay */
                    246: 
                    247: DoDsp (SaveMiniBuf)
                    248: {
                    249:   register struct window *w = XWINDOW (selected_window);
                    250:   register int pause;
                    251:   int inhibit_hairy_id = 0;
                    252:   int must_finish = 0;
                    253:   int all_windows = 0;
                    254:   register int tlbufpos, tlendpos;
                    255:   struct position pos;
                    256:   extern int input_pending;
                    257: 
                    258:   if (noninteractive)
                    259:     return;
                    260: 
                    261:   if (screen_garbaged)
                    262:     {
                    263:       Fredraw_display ();
                    264:       screen_garbaged = 0;
                    265:     }
                    266: 
                    267:   if (minibuf_message ||
                    268:       (prev_minibuf_message && !SaveMiniBuf))
                    269:     {
                    270:       display_minibuf_message ();
                    271:       must_finish = 1;
                    272:     }
                    273: 
                    274:   if (clip_changed || windows_or_buffers_changed)
                    275:     RedoModes++;
                    276: 
                    277:   /* Detect case that we need to write a star in the mode line.  */
                    278:   if (XFASTINT (w->last_modified) < bf_modified
                    279:       && XFASTINT (w->last_modified) <= bf_cur->save_modified)
                    280:     {
                    281:       w->redo_mode_line = Qt;
                    282:       if (buffer_shared > 1)
                    283:        RedoModes++;
                    284:     }
                    285: 
                    286:   all_windows = RedoModes || buffer_shared > 1;
                    287: 
                    288:   tlbufpos = this_line_bufpos;
                    289:   tlendpos = this_line_endpos;
                    290:   if (!all_windows && tlbufpos > 0 && NULL (w->redo_mode_line)
                    291:       /* Point must be on the line that we have info recorded about */
                    292:       && point >= tlbufpos
                    293:       && point <= bf_s1 + bf_s2 + 1 - tlendpos
                    294:       /* All text outside that line, including its final newline,
                    295:         must be unchanged */
                    296:       && (XFASTINT (w->last_modified) >= bf_modified
                    297:          || (beg_unchanged >= tlbufpos - 1
                    298:              && bf_s1 >= tlbufpos - 1
                    299:              && end_unchanged >= tlendpos
                    300:              && bf_s2 >= tlendpos))
                    301:       /* Make sure recorded data applies to current buffer, etc */
                    302:       && NULL (w->force_start)
                    303:       && bf_cur == XBUFFER (w->buffer)
                    304:       && this_line_buffer == bf_cur)
                    305:     {
                    306:       if (tlbufpos > FirstCharacter && CharAt (tlbufpos - 1) != '\n'
                    307:          && (tlbufpos == NumCharacters + 1
                    308:              || CharAt (tlbufpos) == '\n'))
                    309:        /* Former continuation line has disappeared by becoming empty */
                    310:        ;
                    311:       else if (XFASTINT (w->last_modified) < bf_modified
                    312:               || EQ (selected_window, minibuf_window))
                    313:        {
                    314:          point_vpos = -1;
                    315:          display_text_line (w, tlbufpos, this_line_vpos, this_line_hpos,
                    316:                             pos_tab_offset (w, tlbufpos));
                    317:          /* If line contains point, is not continued,
                    318:                 and ends at same distance from eob as before, we win */
                    319:          if (point_vpos >= 0 && this_line_bufpos
                    320:              && this_line_endpos == tlendpos)
                    321:            {
                    322:              cursX = point_hpos;
                    323:              if (XFASTINT (w->width) != screen_width)
                    324:                preserve_other_columns (w);
                    325:              if (interrupt_input)
                    326:                unrequest_sigio ();
                    327:              goto update;
                    328:            }
                    329:        }
                    330:       else if (point == XFASTINT (w->last_point))
                    331:        {
                    332:          if (!must_finish)
                    333:            return;
                    334:          goto update;
                    335:        }
                    336:       else
                    337:        {
                    338:          pos = *compute_motion (tlbufpos, 0,
                    339:                                XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
                    340:                                point, 2, - (1 << (SHORTBITS - 1)),
                    341:                                XFASTINT (w->width) - 1
                    342:                                - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width),
                    343:                                XINT (w->hscroll), 0);
                    344:          if (pos.vpos < 1)
                    345:            {
                    346:              cursX = max (XFASTINT (w->left), pos.hpos);
                    347:              if (interrupt_input)
                    348:                unrequest_sigio ();
                    349:              goto update;
                    350:            }
                    351:        }
                    352:       /* Text changed drastically or point moved off of line */
                    353:       cancel_line (this_line_vpos);
                    354:     }
                    355: 
                    356:   this_line_bufpos = 0;
                    357: 
                    358:   if (interrupt_input)
                    359:     unrequest_sigio ();
                    360: 
                    361:   if (all_windows)
                    362:     redisplay_all_windows ();
                    363:   else
                    364:     {
                    365:       inhibit_hairy_id = redisplay_window (selected_window, 1);
                    366:       if (XFASTINT (w->width) != screen_width)
                    367:        preserve_other_columns (w);
                    368:     }
                    369: 
                    370: update: 
                    371:   pause = update_screen (0, inhibit_hairy_id);
                    372: 
                    373:   /* If screen does not match, prevent doing single-line-update next time */
                    374:   if (pause)
                    375:     this_line_bufpos = 0;
                    376: 
                    377:   /* Now text on screen agrees with windows, so
                    378:      put info into the windows for partial redisplay to follow */
                    379: 
                    380:   if (!pause)
                    381:     {
                    382:       register struct buffer_text *t
                    383:        = XBUFFER (w->buffer) == bf_cur
                    384:          ? &bf_text : &XBUFFER (w->buffer)->text;
                    385: 
                    386:       blank_end_of_window = 0;
                    387:       clip_changed = 0;
                    388:       unchanged_modified = t->modified;
                    389:       beg_unchanged = t->size1, end_unchanged = t->size2;
                    390: 
                    391:       XFASTINT (w->last_point) = t->pointloc;
                    392:       XFASTINT (w->last_point_x) = cursX;
                    393:       XFASTINT (w->last_point_y) = cursY;
                    394: 
                    395:       if (all_windows)
                    396:        mark_window_display_accurate (XWINDOW (minibuf_window)->prev, 1);
                    397:       else
                    398:        {
                    399:          w->redo_mode_line = Qnil;
                    400:          XFASTINT (w->last_modified) = t->modified;
                    401:          if (XFASTINT (w->window_end_pos) < 0)
                    402:            XFASTINT (w->window_end_pos) = -1 - XFASTINT (w->window_end_pos);
                    403:        }
                    404:       RedoModes = 0;
                    405:       windows_or_buffers_changed = 0;
                    406:     }
                    407: 
                    408:   /* Start SIGIO interrupts coming again.
                    409:      Having them off during the code above
                    410:      makes it less likely one will discard output,
                    411:      but not impossible, since there might be stuff
                    412:      in the system buffer here.
                    413:      But it is much hairier to try to do anything about that.  */
                    414: 
                    415:   if (interrupt_input)
                    416:     request_sigio ();
                    417: }
                    418: 
                    419: mark_window_display_accurate (window, flag)
                    420:      Lisp_Object window;
                    421:      int flag;
                    422: {
                    423:   register struct window *w;
                    424: 
                    425:   for (;!NULL (window); window = w->next)
                    426:     {
                    427:       w = XWINDOW (window);
                    428: 
                    429:       XFASTINT (w->last_modified)
                    430:        = !flag ? 0
                    431:          : XBUFFER (w->buffer) == bf_cur
                    432:            ? bf_modified : XBUFFER (w->buffer)->text.modified;
                    433:       if (XFASTINT (w->window_end_pos) < 0)
                    434:        XFASTINT (w->window_end_pos) = -1 - XFASTINT (w->window_end_pos);
                    435:       w->redo_mode_line = Qnil;
                    436: 
                    437:       if (!NULL (w->vchild))
                    438:        mark_window_display_accurate (w->vchild, flag);
                    439:       if (!NULL (w->hchild))
                    440:        mark_window_display_accurate (w->hchild, flag);
                    441:     }
                    442: }
                    443: 
                    444: int do_id = 1;
                    445: 
                    446: /* Do full redisplay of one or all windows.
                    447:   This does not include updating the screen;
                    448:   just generating lines to pass to update_screen.  */
                    449: 
                    450: /* Entry point to redisplay all windows */
                    451: 
                    452: redisplay_all_windows ()
                    453: {
                    454:   buffer_shared = 0;
                    455: 
                    456:   redisplay_windows (XWINDOW (minibuf_window)->prev);
                    457: }
                    458: 
                    459: redisplay_windows (window)
                    460:      Lisp_Object window;
                    461: {
                    462:   for (; !NULL (window); window = XWINDOW (window)->next)
                    463:     redisplay_window (window, 0);
                    464: }
                    465: 
                    466: redisplay_window (window, just_this_one)
                    467:      Lisp_Object window;
                    468:      int just_this_one;
                    469: {
                    470:   register struct window *w = XWINDOW (window);
                    471:   int height;
                    472:   register int lpoint = point;
                    473:   struct buffer *old = bf_cur;
                    474:   register int width = XFASTINT (w->width) - 1
                    475:     - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width);
                    476:   register int startp = marker_position (w->start);
                    477:   register int hscroll = XINT (w->hscroll);
                    478:   struct position pos;
                    479:   int inhibit_hairy_id = 0;
                    480:   int opoint;
                    481:   int tem;
                    482: 
                    483:   if (screen_height == 0) abort (); /* Some bug zeros some core */
                    484: 
                    485:   /* If this is a combination window, do its children; that's all.  */
                    486: 
                    487:   if (!NULL (w->vchild))
                    488:     {
                    489:       redisplay_windows (w->vchild);
                    490:       return 0;
                    491:     }
                    492:   if (!NULL (w->hchild))
                    493:     {
                    494:       redisplay_windows (w->hchild);
                    495:       return 0;
                    496:     }
                    497:   if (NULL (w->buffer))
                    498:     abort ();
                    499: 
                    500:   if (RedoModes)
                    501:     w->redo_mode_line = Qt;
                    502: 
                    503:   /* Otherwise set up data on this window; select its buffer and point value */
                    504: 
                    505:   height = XFASTINT (w->height);
                    506:   if (w != XWINDOW (minibuf_window))
                    507:     height--;
                    508:   else if (minibuf_message)
                    509:     return 0;
                    510: 
                    511:   SetBfx (XBUFFER (w->buffer));
                    512:   opoint = point;
                    513: 
                    514:   if (!just_this_one
                    515:       && bf_cur == XBUFFER (XWINDOW (selected_window)->buffer))
                    516:     buffer_shared++;
                    517: 
                    518:   if (!EQ (window, selected_window))
                    519:     {
                    520:       SetPoint (marker_position (w->pointm));
                    521:       if (point < FirstCharacter)
                    522:        point = FirstCharacter;
                    523:       else if (point > NumCharacters)
                    524:        point = NumCharacters + 1;
                    525:     }
                    526: 
                    527:   /* Handle case where place to start displaying has been specified */
                    528: 
                    529:   if (!NULL (w->force_start))
                    530:     {
                    531:       w->redo_mode_line = Qt;
                    532:       w->force_start = Qnil;
                    533:       XFASTINT (w->last_modified) = 0;
                    534:       if (!try_window (window, startp))
                    535:        {
                    536:          /* If point does not appear, move point so it does appear */
                    537:          pos = *compute_motion (startp, 0,
                    538:                                ((EQ (window, minibuf_window) && startp == 1)
                    539:                                 ? minibuf_prompt_width : 0)
                    540:                                +
                    541:                                (hscroll ? 1 - hscroll : 0),
                    542:                                NumCharacters + 1, height / 2,
                    543:                                - (1 << (SHORTBITS - 1)),
                    544:                                width, hscroll, pos_tab_offset (w, startp));
                    545:          SetPoint (pos.bufpos);
                    546:          if (w != XWINDOW (selected_window))
                    547:            Fset_marker (w->pointm, make_number (point), Qnil);
                    548:          else
                    549:            lpoint = point;
                    550: 
                    551:          if (EQ (window, selected_window))
                    552:            {
                    553:              cursX = max (0, pos.hpos) + XFASTINT (w->left);
                    554:              cursY = pos.vpos + XFASTINT (w->top);
                    555:            }
                    556:        }
                    557:       goto done;
                    558:     }
                    559: 
                    560:   /* Handle case where text has not changed, only point,
                    561:      and it has not moved off the screen */
                    562: 
                    563:   /* This code is not used for minibuffer for the sake of
                    564:      the case of redisplaying to replace an echo area message;
                    565:      since in that case the minibuffer contents per se are usually unchanged.
                    566:      This code is of no real use in the minibuffer since
                    567:      the handling of tlbufpos, etc., in DoDsp handles the same cases.  */
                    568: 
                    569:   if (XFASTINT (w->last_modified) >= bf_modified
                    570:       && point >= startp && !clip_changed
                    571:       && (just_this_one || XFASTINT (w->width) == screen_width)
                    572:       && !EQ (window, minibuf_window))
                    573:     {
                    574:       pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0),
                    575:                            point, height + 1, 10000, width, hscroll,
                    576:                            pos_tab_offset (w, startp));
                    577: 
                    578:       if (pos.vpos < height)
                    579:        {
                    580:          /* Ok, point is still on screen */
                    581:          if (w == XWINDOW (selected_window))
                    582:            {
                    583:              /* These variables are supposed to be origin 1 */
                    584:              cursX = max (0, pos.hpos) + XFASTINT (w->left);
                    585:              cursY = pos.vpos + XFASTINT (w->top);
                    586:            }
                    587: /* This doesn't do the trick, because if a window to the right of
                    588:  this one must be redisplayed, this does nothing because there
                    589:  is nothing in DesiredScreen yet, and then the other window is
                    590:  redisplayed, making likes that are empty in this window's columns.
                    591:          if (XFASTINT (w->width) != screen_width)
                    592:            preserve_my_columns (w);
                    593: */
                    594:          goto done;
                    595:        }
                    596:       /* Don't bother trying redisplay with same start;
                    597:        we already know it will lose */
                    598:     }
                    599:   else if (just_this_one && !EQ (window, minibuf_window)
                    600:           && point >= startp
                    601:           && XFASTINT (w->last_modified)
                    602:           && XFASTINT (w->window_end_pos) >= 0
                    603:           && do_id && !clip_changed
                    604:           && !blank_end_of_window
                    605:           && XFASTINT (w->width) == screen_width
                    606:           && (tem = try_window_id (selected_window))
                    607:           && tem != -2)
                    608:     {
                    609:       /* tem > 0 means success.  tem == -1 means choose new start.
                    610:         tem == -2 means try again with same start,
                    611:          and nothing but whitespace follows the changed stuff.
                    612:         tem == 0 means try again with same start.  */
                    613:       if (tem > 0)
                    614:        {
                    615: /*       inhibit_hairy_id = 1;   */
                    616:          goto done;
                    617:        }
                    618:     }
                    619:   else if (startp >= FirstCharacter && startp <= NumCharacters + 1
                    620:           /* Avoid starting display at end of buffer! */
                    621:           && (startp <= NumCharacters || startp == FirstCharacter
                    622:               || (XFASTINT (w->last_modified) >= bf_modified)))
                    623:     {
                    624:       /* Try to redisplay starting at same place as before */
                    625:       /* If point has not moved off screen, accept the results */
                    626:       if (try_window (window, startp))
                    627:        goto done;
                    628:       else
                    629:        cancel_my_columns (w);
                    630:     }
                    631: 
                    632:   XFASTINT (w->last_modified) = 0;
                    633:   w->redo_mode_line = Qt;
                    634: 
                    635:   /* Try to scroll by specified few lines */
                    636: 
                    637:   if (scroll_step && !clip_changed)
                    638:     {
                    639:       if (point > startp)
                    640:        {
                    641:          pos = *vmotion (bf_s1 + bf_s2 + 1 - CURRENT_END_POS (w),
                    642:                          scroll_step, width, hscroll, window);
                    643:          if (pos.vpos >= height)
                    644:            goto scroll_fail;
                    645:        }
                    646: 
                    647:       pos = *vmotion (startp, point < startp ? - scroll_step : scroll_step,
                    648:                      width, hscroll, window);
                    649: 
                    650:       if (point >= pos.bufpos)
                    651:        {
                    652:          if (try_window (window, pos.bufpos))
                    653:            goto done;
                    654:          else
                    655:            cancel_my_columns (w);
                    656:        }
                    657:     scroll_fail: ;
                    658:     }
                    659: 
                    660:   /* Finally, just choose place to start which centers point */
                    661: 
                    662:   pos = *vmotion (point, - height / 2, width, hscroll, window);
                    663:   try_window (window, pos.bufpos);
                    664: 
                    665: done:
                    666:   /* If window not full width, must redo its mode line
                    667:      if the window to its side is being redone */
                    668:   if ((!NULL (w->redo_mode_line)
                    669:        || (!just_this_one && width < screen_width - 1))
                    670:       && !EQ (window, minibuf_window))
                    671:     display_mode_line (w);
                    672: 
                    673:   SetPoint (opoint);
                    674:   SetBfx (old);
                    675:   SetPoint (lpoint);
                    676: 
                    677:   return inhibit_hairy_id;
                    678: }
                    679: 
                    680: /* Do full redisplay on one window,
                    681:   starting at position `pos',
                    682:   and return nonzero if point appears in the displayed text */
                    683: 
                    684: try_window (window, pos)
                    685:      Lisp_Object window;
                    686:      register int pos;
                    687: {
                    688:   register struct window *w = XWINDOW (window);
                    689:   register int height = XFASTINT (w->height) - !EQ (window, minibuf_window);
                    690:   register int vpos = XFASTINT (w->top);
                    691:   register int last_text_vpos = vpos;
                    692:   int tab_offset = pos_tab_offset (w, pos);
                    693: 
                    694:   struct position val;
                    695: 
                    696:   Fset_marker (w->start, make_number (pos), Qnil);
                    697: 
                    698:   point_vpos = -1;
                    699:   val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
                    700: 
                    701:   while (--height >= 0)
                    702:     {
                    703:       val = *display_text_line (w, pos, vpos, val.hpos, tab_offset);
                    704:       tab_offset += XFASTINT (w->width) - 1;
                    705:       if (val.vpos) tab_offset = 0;
                    706:       vpos++;
                    707:       if (pos != val.bufpos)
                    708:        last_text_vpos
                    709:          /* Next line, unless prev line ended in end of buffer with no cr */
                    710:          = vpos - (val.vpos && CharAt (val.bufpos - 1) != '\n');
                    711:       pos = val.bufpos;
                    712:     }
                    713: 
                    714:   /* If last line is continued in middle of character,
                    715:      include the split character in the text considered on the screen */
                    716:   if (val.hpos < XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0)
                    717:     pos++;
                    718: 
                    719:   /* Make this -1 minus what it really should be, so that it is negative.
                    720:      That serves as a signal that it is not really valid.
                    721:      When screen updating is through,
                    722:      change this to its correct positive value */
                    723:   XFASTINT (w->window_end_pos) = -1 - (bf_s1 + bf_s2 + 1 - pos);
                    724:   XFASTINT (w->window_end_vpos) = last_text_vpos - XFASTINT (w->top);
                    725:   return point_vpos >= 0;
                    726: }
                    727: 
                    728: /* Try to redisplay when buffer is modified locally,
                    729:  computing insert/delete line to preserve text outside
                    730:  the bounds of the changes.
                    731:  Return 1 if successful, 0 if if cannot tell what to do,
                    732:  or -1 to tell caller to find a new window start,
                    733:  or -2 to tell caller that we did nothing because only whitespace
                    734:  appears below the changed part of the screen.  */
                    735: 
                    736: try_window_id (window)
                    737:      Lisp_Object window;
                    738: {
                    739:   int pos;
                    740:   register struct window *w = XWINDOW (window);
                    741:   register int height = XFASTINT (w->height) - !EQ (window, minibuf_window);
                    742:   int top = XFASTINT (w->top);
                    743:   int start = marker_position (w->start);
                    744:   int width = XFASTINT (w->width) - 1
                    745:     - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width);
                    746:   int hscroll = XINT (w->hscroll);
                    747:   int lmargin = hscroll > 0 ? 1 - hscroll : 0;
                    748:   register int vpos;
                    749:   register int i, tem;
                    750:   int last_text_vpos = 0;
                    751:   int stop_vpos;
                    752: 
                    753:   struct position val, bp, ep, xp, pp;
                    754:   int scroll_amount = 0;
                    755:   int delta;
                    756:   int tab_offset, epto;
                    757: 
                    758:   if (bf_s1 < beg_unchanged)
                    759:     beg_unchanged = bf_s1;
                    760:   if (bf_s2 < end_unchanged)
                    761:     end_unchanged = bf_s2;
                    762: 
                    763:   if (beg_unchanged + 1 < start)
                    764:     return 0;                  /* Give up if changes go above top of window */
                    765: 
                    766:   /* Find position before which nothing is changed.  */
                    767:   bp = *compute_motion (start, 0, lmargin,
                    768:                       beg_unchanged + 1, 10000, 10000, width, hscroll,
                    769:                       pos_tab_offset (w, start));
                    770:   if (bp.vpos >= height)
                    771:     return point < bp.bufpos && !bp.contin;
                    772: 
                    773:   vpos = bp.vpos;
                    774: 
                    775:   /* Find beginning of that screen line.  Must display from there.  */
                    776:   bp = *vmotion (bp.bufpos, 0, width, hscroll, window);
                    777: 
                    778:   pos = bp.bufpos;
                    779:   val.hpos = lmargin;
                    780:   if (pos < start)
                    781:     return -1;
                    782: 
                    783:   /* If about to start displaying at the beginning of a continuation line,
                    784:      really start with previous screen line, in case it was not
                    785:      continued when last redisplayed */
                    786:   if (bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
                    787:     {
                    788:       bp = *vmotion (bp.bufpos, -1, width, hscroll, window);
                    789:       --vpos;
                    790:       pos = bp.bufpos;
                    791:     }
                    792: 
                    793:   if (bp.contin && bp.hpos != lmargin)
                    794:     {
                    795:       val.hpos = bp.prevhpos - width + lmargin;
                    796:       pos--;
                    797:     }
                    798: 
                    799:   bp.vpos = vpos;
                    800: 
                    801:   /* Find first newline after which no more is changed */
                    802:   ep = *compute_motion (pos, vpos, val.hpos,
                    803:                       ScanBf ('\n',
                    804:                               bf_s1 + bf_s2 + 1 - max (end_unchanged, bf_tail_clip),
                    805:                               1),
                    806:                       height, - (1 << (SHORTBITS - 1)),
                    807:                       width, hscroll, pos_tab_offset (w, bp.bufpos));
                    808: 
                    809:   /* If changes reach past the text available on the screen,
                    810:      just display rest of screen.  */
                    811:   if (ep.bufpos > bf_s1 + bf_s2 + 1 - XFASTINT (w->window_end_pos))
                    812:     stop_vpos = height;
                    813:   else
                    814:     stop_vpos = ep.vpos;
                    815: 
                    816:   /* If no newline before ep, the line ep is on includes some changes
                    817:      that must be displayed.  Make sure we don't stop before it.  */
                    818:   /* Also, if changes reach all the way until ep.bufpos,
                    819:      it is possible that something was deleted after the
                    820:      newline before it, so the following line must be redrawn. */
                    821:   if (stop_vpos == ep.vpos
                    822:       && (ep.bufpos == FirstCharacter
                    823:          || CharAt (ep.bufpos - 1) != '\n'
                    824:          || ep.bufpos == bf_s1 + bf_s2 + 1 - end_unchanged))
                    825:     stop_vpos = ep.vpos + 1;
                    826: 
                    827:   point_vpos = -1;
                    828: 
                    829:   /* If changes do not reach to bottom of window,
                    830:      figure out how much to scroll the rest of the window */
                    831:   if (stop_vpos < height)
                    832:     {
                    833:       /* Now determine how far up or down the rest of the window has moved */
                    834:       epto = pos_tab_offset (w, ep.bufpos);
                    835:       xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
                    836:                           bf_s1 + bf_s2 + 1 - XFASTINT (w->window_end_pos),
                    837:                           10000, 0, width, hscroll, epto);
                    838:       scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
                    839: 
                    840:       /* Is everything on screen below the changes whitespace?
                    841:         If so, no scrolling is really necessary.  */
                    842:       for (i = ep.bufpos; i < xp.bufpos; i++)
                    843:        {
                    844:          tem = CharAt (i);
                    845:          if (tem != ' ' && tem != '\n' && tem != '\t')
                    846:            break;
                    847:        }
                    848:       if (i == xp.bufpos)
                    849:        return -2;
                    850: 
                    851:       XFASTINT (w->window_end_vpos) += scroll_amount;
                    852: 
                    853:       /* Before doing any scrolling, verify that point will be on screen. */
                    854:       if (point > ep.bufpos && !(point <= xp.bufpos && xp.bufpos < height))
                    855:        {
                    856:          if (point <= xp.bufpos)
                    857:            {
                    858:              pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos,
                    859:                                   point, height, - (1 << (SHORTBITS - 1)),
                    860:                                   width, hscroll, epto);
                    861:            }
                    862:          else
                    863:            {
                    864:              pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos,
                    865:                                   point, height, - (1 << (SHORTBITS - 1)),
                    866:                                   width, hscroll, pos_tab_offset (w, xp.bufpos));
                    867:            }
                    868:          if (pp.bufpos < point || pp.vpos == height)
                    869:            return 0;
                    870:          point_vpos = pp.vpos + top;
                    871:          point_hpos = pp.hpos + XFASTINT (w->left);
                    872:        }
                    873: 
                    874:       if (stop_vpos - scroll_amount >= height
                    875:          || ep.bufpos == xp.bufpos)
                    876:        {
                    877:          if (scroll_amount < 0)
                    878:            stop_vpos -= scroll_amount;
                    879:          scroll_amount = 0;
                    880:          /* In this path, we have altered window_end_vpos
                    881:             and not left it negative.
                    882:             We must make sure that, in case display is preempted
                    883:             before the screen changes to reflect what we do here,
                    884:             further updates will not come to try_window_id
                    885:             and assume the screen and window_end_vpos match.  */
                    886:          blank_end_of_window = 1;
                    887:        }
                    888:       else if (!scroll_amount)
                    889:        {}
                    890:       else if (bp.bufpos == bf_s1 + bf_s2 + 1 - end_unchanged)
                    891:        {
                    892:          /* If pure deletion, scroll up as many lines as possible.
                    893:             In common case of killing a line, this can save the
                    894:             following line from being overwritten by scrolling
                    895:             and therefore having to be redrawn.  */
                    896:          tem = scroll_screen_lines (bp.vpos + top - scroll_amount,
                    897:                                     top + height - max (0, scroll_amount),
                    898:                                     scroll_amount);
                    899:          if (!tem) stop_vpos = height;
                    900:        }
                    901:       else if (scroll_amount)
                    902:        {
                    903:          tem = scroll_screen_lines (ep.vpos + top - scroll_amount,
                    904:                                     top + height - max (0, scroll_amount),
                    905:                                     scroll_amount);
                    906:          if (!tem) stop_vpos = height;
                    907:        }
                    908:     }
                    909: 
                    910:   /* In any case, do not display past bottom of window */
                    911:   if (stop_vpos >= height)
                    912:     {
                    913:       stop_vpos = height;
                    914:       scroll_amount = 0;
                    915:     }
                    916: 
                    917:   /* Handle case where pos is before w->start --
                    918:      can happen if part of line had been clipped and is not clipped now */
                    919:   if (vpos == 0 && pos < marker_position (w->start))
                    920:     Fset_marker (w->start, make_number (pos), Qnil);
                    921: 
                    922:   /* Redisplay the lines where the text was changed */
                    923:   last_text_vpos = vpos;
                    924:   tab_offset = pos_tab_offset (w, pos);
                    925:   if (val.hpos < 0)
                    926:     tab_offset += XFASTINT (w->width) - 1;
                    927:   while (vpos < stop_vpos)
                    928:     {
                    929:       val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
                    930:       tab_offset += XFASTINT (w->width) - 1;
                    931:       if (val.vpos) tab_offset = 0;
                    932:       if (pos != val.bufpos)
                    933:        last_text_vpos
                    934:          /* Next line, unless prev line ended in end of buffer with no cr */
                    935:            = vpos - (val.vpos && CharAt (val.bufpos - 1) != '\n');
                    936:       pos = val.bufpos;
                    937:     }
                    938: 
                    939:   /* There are two cases:
                    940:      1) we have displayed down to the bottom of the window
                    941:      2) we have scrolled lines below stop_vpos by scroll_amount  */
                    942: 
                    943:   if (vpos == height)
                    944:     {
                    945:       /* If last line is continued in middle of character,
                    946:         include the split character in the text considered on the screen */
                    947:       if (val.hpos < lmargin)
                    948:        val.bufpos++;
                    949:       XFASTINT (w->window_end_vpos) = last_text_vpos;
                    950:       XFASTINT (w->window_end_pos) = -1 - (bf_s1 + bf_s2 + 1 - val.bufpos);
                    951:     }
                    952: 
                    953:   /* If scrolling made blank lines at window bottom,
                    954:      redisplay to fill those lines */
                    955:   if (scroll_amount < 0)
                    956:     {
                    957:       vpos = xp.vpos;
                    958:       pos = xp.bufpos;
                    959:       val.hpos = lmargin;
                    960:       if (pos == NumCharacters + 1)
                    961:        vpos = height + scroll_amount;
                    962:       else if (xp.contin && xp.hpos != lmargin)
                    963:        {
                    964:          val.hpos = xp.prevhpos - width + lmargin;
                    965:          pos--;
                    966:        }
                    967: 
                    968:       blank_end_of_window = 1;
                    969:       tab_offset = pos_tab_offset (w, pos);
                    970:       if (val.hpos < 0)
                    971:        tab_offset += XFASTINT (w->width) - 1;
                    972: 
                    973:       while (vpos < height)
                    974:        {
                    975:          val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset);
                    976:          tab_offset += XFASTINT (w->width) - 1;
                    977:          if (val.vpos) tab_offset = 0;
                    978:          pos = val.bufpos;
                    979:        }
                    980: 
                    981:       /* Here is a case where display_line_text sets point_vpos wrong.
                    982:         Make it be fixed up, below.  */
                    983:       if (xp.bufpos == NumCharacters + 1
                    984:          && xp.bufpos == point)
                    985:        point_vpos = -1;
                    986:     }
                    987: 
                    988:   /* Attempt to adjust end-of-text positions to new bottom line */
                    989:   if (scroll_amount)
                    990:     {
                    991:       delta = height - xp.vpos;
                    992:       if (delta < 0
                    993:          || (delta > 0 && xp.bufpos <= NumCharacters)
                    994:          || (delta == 0 && xp.hpos))
                    995:        {
                    996:          val = *vmotion (bf_s1 + bf_s2 + 1 - XFASTINT (w->window_end_pos),
                    997:                          delta, width, hscroll, window);
                    998:          XFASTINT (w->window_end_pos) = bf_s1 + bf_s2 + 1 - val.bufpos;
                    999:          XFASTINT (w->window_end_vpos) += val.vpos;
                   1000:        }
                   1001:     }
                   1002: 
                   1003:   /* If point was not in a line that was displayed, find it */
                   1004:   if (point_vpos < 0)
                   1005:     {
                   1006:       val = *compute_motion (start, 0, lmargin, point, 10000, 10000,
                   1007:                            width, hscroll, pos_tab_offset (w, start));
                   1008:       /* Admit failure if point is off screen now */
                   1009:       if (val.vpos >= height)
                   1010:        {
                   1011:          for (vpos = 0; vpos < height; vpos++)
                   1012:            cancel_line (vpos + top);
                   1013:          return 0;
                   1014:        }
                   1015:       point_vpos = val.vpos + top;
                   1016:       point_hpos = val.hpos + XFASTINT (w->left);
                   1017:     }
                   1018: 
                   1019:   cursX = max (0, point_hpos);
                   1020:   cursY = point_vpos;
                   1021: 
                   1022:   if (debug_end_pos)
                   1023:     {
                   1024:       val = *compute_motion (start, 0, lmargin, NumCharacters + 1,
                   1025:                            height, - (1 << (SHORTBITS - 1)),
                   1026:                            width, hscroll, pos_tab_offset (w, start));
                   1027:       if (val.vpos != XFASTINT (w->window_end_vpos))
                   1028:        abort ();
                   1029:       if ((XFASTINT (w->window_end_pos) < 0
                   1030:           ? -1 - XFASTINT (w->window_end_pos)
                   1031:           : XFASTINT (w->window_end_pos))
                   1032:          != bf_s1 + bf_s2 + 1 - val.bufpos)
                   1033:        abort ();
                   1034:     }
                   1035: 
                   1036:   return 1;
                   1037: }
                   1038: 
                   1039: /* Display one line of window w, starting at position `start' in w's buffer.
                   1040:  Display starting at horizontal position `hpos',
                   1041:   which is normally zero or negative.
                   1042:   A negative value causes output up to hpos = 0 to be discarded.
                   1043:   This is done for negative hscroll, or when this is a continuation line
                   1044:   and the continuation occurred in the middle of a multi-column character.
                   1045: 
                   1046:  `taboffset' is an offset for ostensible hpos, used in tab stop calculations.
                   1047: 
                   1048:  Display on position `vpos' on the screen.  (origin 0).
                   1049: 
                   1050:  Returns a `struct position' giving character to start next line with
                   1051:  and where to display it, including a zero or negative hpos.
                   1052:  The vpos field is not really a vpos; it is 1 unless the line is continued */
                   1053: 
                   1054: struct position val_display_text_line;
                   1055: 
                   1056: struct position *
                   1057: display_text_line (w, start, vpos, hpos, taboffset)
                   1058:      struct window *w;
                   1059:      int start;
                   1060:      int vpos;
                   1061:      int hpos;
                   1062:      int taboffset;
                   1063: {
                   1064:   register int pos = start;
                   1065:   register int c;
                   1066:   register char *p1;
                   1067:   int end;
                   1068:   register int pause;
                   1069:   register unsigned char *p;
                   1070:   char *endp;
                   1071:   register char *startp;
                   1072:   register char *p1prev;
                   1073:   register struct display_line *line;
                   1074:   int tab_width = XFASTINT (XBUFFER (w->buffer)->tab_width);
                   1075:   int ctl_arrow = !NULL (XBUFFER (w->buffer)->ctl_arrow);
                   1076:   int width = XFASTINT (w->width) - 1
                   1077:     - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width);
                   1078:   struct position val;
                   1079:   int lastpos;
                   1080:   int invis;
                   1081:   int hscroll = XINT (w->hscroll);
                   1082:   int truncate = hscroll
                   1083:     || (truncate_partial_width_windows
                   1084:        && XFASTINT (w->width) < screen_width)
                   1085:     || !NULL (XBUFFER (w->buffer)->truncate_lines);
                   1086:   int selective
                   1087:     = XTYPE (bf_cur->selective_display) == Lisp_Int
                   1088:       ? XINT (bf_cur->selective_display)
                   1089:        : !NULL (bf_cur->selective_display) ? -1 : 0;
                   1090: 
                   1091:   hpos += XFASTINT (w->left);
                   1092:   line = get_display_line (vpos, XFASTINT (w->left));
                   1093:   if (tab_width <= 0) tab_width = 1;
                   1094: 
                   1095:   if (w == XWINDOW (minibuf_window) && start == 1)
                   1096:     {
                   1097:       if (minibuf_prompt)
                   1098:        hpos = display_string (w, line, minibuf_prompt, hpos,
                   1099:                               !truncate ? '\\' : '$',
                   1100:                               0);
                   1101:       minibuf_prompt_width = hpos;
                   1102:     }
                   1103: 
                   1104:   p1 = line->body + hpos;
                   1105: 
                   1106:   end = NumCharacters + 1;
                   1107: 
                   1108:   startp = line->body + XFASTINT (w->left);
                   1109:   endp = startp + width;
                   1110: 
                   1111:   /* Loop generating characters.
                   1112:    Stop at end of buffer, before newline,
                   1113:    or if reach or pass continuation column.  */
                   1114: 
                   1115:   pause = pos;
                   1116:   while (p1 < endp)
                   1117:     {
                   1118:       p1prev = p1;
                   1119:       if (pos == pause)
                   1120:        {
                   1121:          if (pos == end)
                   1122:            break;
                   1123:          if (pos == point && point_vpos < 0)
                   1124:            {
                   1125:              point_vpos = vpos;
                   1126:              point_hpos = p1 - startp;
                   1127:            }
                   1128: 
                   1129:          pause = end;
                   1130:          if (pos < point && point < pause)
                   1131:            pause = point;
                   1132:          if (pos <= bf_s1 && bf_s1 + 1 < pause)
                   1133:            pause = bf_s1 + 1;
                   1134: 
                   1135:          p = &CharAt (pos);
                   1136:        }
                   1137:       c = *p++;
                   1138:       if (c >= 040 && c < 0177)
                   1139:        {
                   1140:          if (p1 >= startp)
                   1141:            *p1 = c;
                   1142:          p1++;
                   1143:        }
                   1144:       else if (c == '\n')
                   1145:        {
                   1146:          invis = 0;
                   1147:          while (pos < end
                   1148:                 && selective > 0
                   1149:                 && position_indentation (pos + 1) >= selective)
                   1150:            {
                   1151:              invis = 1;
                   1152:              pos = ScanBf ('\n', pos + 1, 1);
                   1153:              if (CharAt (pos - 1) == '\n')
                   1154:                pos--;
                   1155:            }
                   1156:          if (invis)
                   1157:            {
                   1158:              p1 += 4;
                   1159:              if (p1 - startp > width)
                   1160:                p1 = endp;
                   1161:              strncpy (p1prev, " ...", p1 - p1prev);
                   1162:            }
                   1163:          break;
                   1164:        }
                   1165:       else if (c == '\t')
                   1166:        {
                   1167:          do
                   1168:            {
                   1169:              if (p1 >= startp)
                   1170:                *p1 = ' ';
                   1171:              p1++;
                   1172:            }
                   1173:          while ((p1 - startp + taboffset + hscroll - (hscroll > 0))
                   1174:                 % tab_width);
                   1175:        }
                   1176:       else if (c == Ctl('M') && !NULL (bf_cur->selective_display))
                   1177:        {
                   1178:          pos = ScanBf ('\n', pos, 1);
                   1179:          if (CharAt (pos - 1) == '\n')
                   1180:            pos--;
                   1181:          break;
                   1182:        }
                   1183:       else if (c < 0200 && ctl_arrow)
                   1184:        {
                   1185:          if (p1 >= startp)
                   1186:            *p1 = '^';
                   1187:          p1++;
                   1188:          if (p1 >= startp)
                   1189:            *p1 = c ^ 0100;
                   1190:          p1++;
                   1191:        }
                   1192:       else
                   1193:        {
                   1194:          if (p1 >= startp)
                   1195:            *p1 = '\\';
                   1196:          p1++;
                   1197:          if (p1 >= startp)
                   1198:            *p1 = (c >> 6) + '0';
                   1199:          p1++;
                   1200:          if (p1 >= startp)
                   1201:            *p1 = (7 & (c >> 3)) + '0';
                   1202:          p1++;
                   1203:          if (p1 >= startp)
                   1204:            *p1 = (7 & c) + '0';
                   1205:          p1++;
                   1206:        }
                   1207:       pos++;
                   1208:     }
                   1209: 
                   1210:   val.hpos = - XINT (w->hscroll);
                   1211:   if (val.hpos)
                   1212:     {
                   1213:       val.hpos++;
                   1214:       /* If line not empty, insert truncation-at-left marker */
                   1215:       if (pos != start)
                   1216:        {
                   1217:          *startp = '$';
                   1218:          if (p1 <= startp)
                   1219:            p1 = startp + 1;
                   1220:          if (line->length <= XFASTINT (w->left))
                   1221:            line->length = XFASTINT (w->left) + 1;
                   1222:        }
                   1223:     }
                   1224:   val.vpos = 1;
                   1225: 
                   1226:   /* Handle continuation in middle of a character */
                   1227:   /* by backing up over it */
                   1228:   if (p1 > endp)
                   1229:     {
                   1230:       /* Start the next line with that same character */
                   1231:       pos--;
                   1232:       /* but at a negative hpos, to skip the columns output on this line.  */
                   1233:       val.hpos += p1prev - endp;
                   1234:       /* Keep in this line everything up to the continuation column.  */
                   1235:       p1 = endp;
                   1236:     }
                   1237: 
                   1238:   /* Finish deciding which character to start the next line on,
                   1239:      and what hpos to start it at.
                   1240:      Also set `lastpos' to the last position which counts as "on this line"
                   1241:      for cursor-positioning.  */
                   1242: 
                   1243:   lastpos = pos;
                   1244: 
                   1245:   if (pos < NumCharacters + 1)
                   1246:     {
                   1247:       if (CharAt (pos) == '\n')
                   1248:        /* If stopped due to a newline, start next line after it */
                   1249:        pos++;
                   1250:       else
                   1251:        /* Stopped due to right margin of window */
                   1252:        {
                   1253:          if (truncate)
                   1254:            {
                   1255:              *p1++ = '$';
                   1256:              /* Truncating => start next line after next newline,
                   1257:                 and point is on this line if it is before the newline,
                   1258:                 and skip none of first char of next line */
                   1259:              pos = ScanBf ('\n', pos, 1);
                   1260:              val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
                   1261: 
                   1262:              lastpos = pos - (CharAt (pos - 1) == '\n');
                   1263:            }
                   1264:          else
                   1265:            {
                   1266:              *p1++ = '\\';
                   1267:              val.vpos = 0;
                   1268:              lastpos = 0;
                   1269:            }
                   1270:        }
                   1271:     }
                   1272: 
                   1273:   if (start <= point && point <= lastpos && point_vpos < 0)
                   1274:     {
                   1275:       point_vpos = vpos;
                   1276:       point_hpos = p1 - startp;
                   1277:     }
                   1278: 
                   1279:   if (point_vpos == vpos)
                   1280:     {
                   1281:       if (point_hpos < 0) point_hpos = 0;
                   1282:       if (point_hpos > width) point_hpos = width;
                   1283:       point_hpos += XFASTINT (w->left);
                   1284:       if (w == XWINDOW (selected_window))
                   1285:        {
                   1286:          cursY = point_vpos;
                   1287:          cursX = point_hpos;
                   1288: 
                   1289:          /* Line is not continued and did not start in middle of character */
                   1290:          if (hpos == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0)
                   1291:              && val.vpos)
                   1292:            {
                   1293:              this_line_bufpos = start;
                   1294:              this_line_buffer = bf_cur;
                   1295:              this_line_vpos = vpos;
                   1296:              this_line_hpos = hpos;
                   1297:              this_line_endpos = bf_s1 + bf_s2 + 1 - lastpos;
                   1298:            }
                   1299:          else
                   1300:            this_line_bufpos = 0;
                   1301:        }
                   1302:     }
                   1303: 
                   1304:   if (XFASTINT (w->width) + XFASTINT (w->left) != screen_width)
                   1305:     {
                   1306:       endp++;
                   1307:       if (p1 < startp) p1 = startp;
                   1308:       while (p1 < endp) *p1++ = ' ';
                   1309:       *p1++ = '|';
                   1310:     }
                   1311:   line->length = max (line->length, p1 - line->body);
                   1312:   line->body[line->length] = 0;
                   1313: 
                   1314:   val.bufpos = pos;
                   1315:   val_display_text_line = val;
                   1316:   return &val_display_text_line;
                   1317: }
                   1318: 
                   1319: /* Display the mode line for window w */
                   1320: 
                   1321: display_mode_line (w)
                   1322:      struct window *w;
                   1323: {
                   1324:   int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
                   1325:   struct display_line *line = get_display_line (vpos, XFASTINT (w->left));
                   1326: 
                   1327:   register unsigned char *s = XSTRING (bf_cur->mode_line_format)->data;
                   1328: 
                   1329:   display_string (w, line, s, XFASTINT (w->left), 0, 1);
                   1330:   /* Make the mode line inverse video if the entire line
                   1331:      is made of mode lines.
                   1332:      I.e. if this window is full width,
                   1333:      or if it is the child of a full width window
                   1334:      (which implies that that window is split side-by-side
                   1335:      and the rest of this line is mode lines of the sibling windows).  */
                   1336:   if (XFASTINT (w->width) == screen_width
                   1337:       || XFASTINT (XWINDOW (w->parent)->width) == screen_width)
                   1338:     line->highlighted = mode_line_inverse_video;
                   1339: }
                   1340: 
                   1341: char fmodetrunc_buf[100];
                   1342: 
                   1343: char *
                   1344: fmodetrunc (str, width)
                   1345:      char *str;
                   1346:      long width;
                   1347: {
                   1348:   register char *buf = fmodetrunc_buf;
                   1349:   register char *bp = buf;
                   1350:   register long len;
                   1351:     
                   1352:   len = strlen(str);
                   1353:   if (width && width < len)
                   1354:     {
                   1355:       strcpy(buf,str+len-width);
                   1356:       if (buf[0] != '/')
                   1357:        while (*bp)
                   1358:          if (*bp++ == '/')
                   1359:            {
                   1360:              bp--;
                   1361:              *--bp = '$';
                   1362:              return bp;
                   1363:            }
                   1364:       buf[0] = '$';
                   1365:       return buf;
                   1366:     }
                   1367:   return str;
                   1368: }
                   1369: 
                   1370: char decode_mode_spec_buf[MScreenWidth + 1];
                   1371: 
                   1372: char *
                   1373: decode_mode_spec (w, string, data_ptr, len_ptr, max_ptr)
                   1374:      struct window *w;
                   1375:      register char *string;
                   1376:      char **data_ptr;
                   1377:      int *len_ptr;
                   1378:      int *max_ptr;
                   1379: {
                   1380:   register int width = 0;
                   1381:   register char c;
                   1382:   Lisp_Object lstr, proc, list;
                   1383:   register char *str;
                   1384:   int len;
                   1385:   int pos, total;
                   1386:   char *tbuf = decode_mode_spec_buf;
                   1387: #define tbufsize (sizeof decode_mode_spec_buf)
                   1388: 
                   1389:   lstr = Qnil, str = 0;
                   1390: 
                   1391:   while (isdigit (c = *string++))
                   1392:     width = width * 10 + (c - '0');
                   1393: 
                   1394:   switch (c)
                   1395:     {
                   1396:     case 'b': 
                   1397:       lstr = bf_cur->name;
                   1398:       if (width && XSTRING (lstr)->size > width)
                   1399:        width = min (2 * width, XSTRING (lstr)->size);
                   1400:       if (width && XSTRING (lstr)->size > width)
                   1401:        {
                   1402:          str = (char *) alloca (width + 1);
                   1403:          bcopy (XSTRING (lstr)->data, str, width - 3);
                   1404:          bcopy ("...", str + width - 3, 4);
                   1405:          lstr = Qnil;
                   1406:        }
                   1407:       break;
                   1408: 
                   1409:     case 'f': 
                   1410:       if (NULL (bf_cur->filename))
                   1411:        str = "[none]";
                   1412:       else if (XTYPE (bf_cur->filename) == Lisp_String)
                   1413:        str = fmodetrunc (XSTRING (bf_cur -> filename)->data, width);
                   1414:       break;
                   1415: 
                   1416:     case 'm': 
                   1417:       lstr = bf_cur->mode_name;
                   1418:       total = min (XSTRING (lstr)->size, tbufsize - 30);
                   1419:       if (total < 0) total = 0;
                   1420:       bcopy (XSTRING (lstr)->data, tbuf, total);
                   1421:       len = 0;
                   1422:       list = bf_cur->minor_modes;
                   1423:       while (1)
                   1424:        {
                   1425:          if (!LISTP (list) && !len)
                   1426:            {
                   1427:              list = Vglobal_minor_modes;
                   1428:              len = 1;
                   1429:            }
                   1430: 
                   1431:          if (!(total < tbufsize - 30 && LISTP (list)))
                   1432:            break;
                   1433: 
                   1434:          lstr = XCONS (list)->car;
                   1435:          if (!LISTP (lstr))
                   1436:            goto foo;
                   1437:          lstr = XCONS (lstr)->cdr;
                   1438:          if (XTYPE (lstr) != Lisp_String)
                   1439:            goto foo;
                   1440:          tbuf[total++] = ' ';
                   1441:          pos = min (XSTRING (lstr)->size, tbufsize - 30 - total);
                   1442:          if (pos < 0)
                   1443:            pos = 0;
                   1444:          bcopy (XSTRING (lstr)->data, tbuf + total, pos);
                   1445:          total += pos;
                   1446:        foo:
                   1447:          list = Fcdr (list);
                   1448:        }
                   1449:       str = tbuf;
                   1450:       tbuf[total] = 0;
                   1451: /*    if (bf_cur->abbrev_mode)
                   1452:        strcat (tbuf, " Abbrev"); */
                   1453:       if (bf_head_clip > 1 || bf_tail_clip > 0)
                   1454:        strcat (tbuf, " Narrow");
                   1455:       if (defining_kbd_macro)
                   1456:        strcat (tbuf, " Def");
                   1457:       lstr = Qnil;
                   1458:       break;
                   1459: 
                   1460:     case 'M': 
                   1461:       lstr = Vglobal_mode_string;
                   1462:       break;
                   1463: 
                   1464:     case '*': 
                   1465:       str = !NULL (bf_cur->read_only) ? "%"
                   1466:            : bf_modified > bf_cur->save_modified ? "*" :"-";
                   1467:       break;
                   1468: 
                   1469:     case 's':
                   1470:       /* status of process */
                   1471: #ifdef subprocesses
                   1472:       proc = Fget_buffer_process (Fcurrent_buffer ());
                   1473:       if (NULL (proc))
                   1474:        str = "no process";
                   1475:       else
                   1476:        lstr = Fsymbol_name (Fprocess_status (proc));
                   1477: #else
                   1478:       str = "no process";
                   1479: #endif /* subprocesses */
                   1480:       break;
                   1481: 
                   1482:     case 'p':
                   1483:       pos = marker_position (w->start);
                   1484:       total = NumCharacters + 1 - FirstCharacter;
                   1485: 
                   1486:       if ((XFASTINT (w->window_end_pos) < 0
                   1487:           ? -1 - XFASTINT (w->window_end_pos)
                   1488:           : XFASTINT (w->window_end_pos))
                   1489:          <= bf_tail_clip)
                   1490:        {
                   1491:          if (pos <= FirstCharacter)
                   1492:            str = "All";
                   1493:          else
                   1494:            str = "Bottom";
                   1495:        }
                   1496:       else if (pos <= FirstCharacter)
                   1497:        str = "Top";
                   1498:       else
                   1499:        {
                   1500:          total = ((pos - FirstCharacter) * 100 + total - 1) / total;
                   1501:          /* We can't normally display a 3-digit number,
                   1502:             so get us a 2-digit number that is close.  */
                   1503:          if (total == 100)
                   1504:            total = 99;
                   1505:          sprintf (tbuf, "%2d%%", total);
                   1506:          str = tbuf;
                   1507:        }
                   1508:       break;
                   1509: 
                   1510:     case '[': 
                   1511:       str = "[[[[[[[[[[" + 10 - (RecurseDepth - MinibufDepth);
                   1512:       if (RecurseDepth - MinibufDepth > 10)
                   1513:        str = "[[[... ";
                   1514:       break;
                   1515: 
                   1516:     case ']': 
                   1517:       str = "]]]]]]]]]]" + 10 - (RecurseDepth - MinibufDepth);
                   1518:       if (RecurseDepth - MinibufDepth > 10)
                   1519:        str = " ...]]]";
                   1520:       break;
                   1521: 
                   1522:     case '-':
                   1523:       str = "--------------------------------------------------------------------------------------------------------------------------------------------";
                   1524:     }
                   1525: 
                   1526:   /* Report the chosen mode item to the caller */
                   1527: 
                   1528:   if (str)
                   1529:     *data_ptr = str, *len_ptr = strlen (str);
                   1530:   else if (XTYPE (lstr) == Lisp_String)
                   1531:     *data_ptr = (char *) XSTRING (lstr)->data,
                   1532:     *len_ptr = XSTRING (lstr)->size;
                   1533:   else
                   1534:     *data_ptr = 0, *len_ptr = 0;
                   1535: 
                   1536:   /* Report specified truncation or padding */
                   1537: 
                   1538:   *max_ptr = width;
                   1539: 
                   1540:   /* Tell caller how much of mode line format was used up */
                   1541: 
                   1542:   return string;
                   1543: }
                   1544: 
                   1545: /* Display `string' on one line of window `w', starting at `hpos'.
                   1546:  Display on the display_line `line', which should have
                   1547:   been obtained by get_display_line (vpos, hpos)
                   1548:   or in some suitable manner.
                   1549: 
                   1550:  `truncate' is character to display at end if truncated.
                   1551:  `modeline' nonzero means substitute for % constructs.
                   1552: 
                   1553:  Returns ending hpos */
                   1554: 
                   1555: 
                   1556: display_string (w, line, string, hpos, truncate, modeline)
                   1557:      struct window *w;
                   1558:      register struct display_line *line;
                   1559:      unsigned char *string;
                   1560:      int hpos;
                   1561:      int truncate;
                   1562:      int modeline;
                   1563: {
                   1564:   register int c;
                   1565:   register unsigned char *p1;
                   1566:   int width = XFASTINT (w->width) - 1
                   1567:     - (XFASTINT (w->width) + XFASTINT (w->left) != screen_width);
                   1568:   int hscroll = XINT (w->hscroll);
                   1569:   int tab_width = 8;
                   1570:   register unsigned char *start;
                   1571:   register unsigned char *end;
                   1572:   char *modeeltstring;
                   1573:   int modeeltleft = 0;
                   1574:   int modeeltmax = 0;
                   1575: 
                   1576:   p1 = (unsigned char *) line->body + hpos;
                   1577:   start = (unsigned char *) line->body + XFASTINT (w->left);
                   1578:   end = start + width;
                   1579: 
                   1580:   while (p1 < end)
                   1581:     {
                   1582:       if (modeeltmax)
                   1583:        {
                   1584:          modeeltmax--;
                   1585:          if (modeeltleft-- > 0)
                   1586:            c = *modeeltstring++;
                   1587:          else
                   1588:            c = ' ';
                   1589:        }
                   1590:       else
                   1591:        {
                   1592:          c = *string++;
                   1593:          if (!c) break;
                   1594:          if (c == '%' && modeline)
                   1595:            {
                   1596:              string = (unsigned char *)
                   1597:                decode_mode_spec (w, string, &modeeltstring,
                   1598:                                  &modeeltleft, &modeeltmax);
                   1599: 
                   1600:              if (!modeeltmax)
                   1601:                modeeltmax = modeeltleft;
                   1602:              else if (modeeltleft > modeeltmax)
                   1603:                modeeltleft = modeeltmax;
                   1604: 
                   1605:              continue;
                   1606:            }
                   1607:        }
                   1608: 
                   1609:       if (c >= 040 && c < 0177)
                   1610:        {
                   1611:          if (p1 >= start)
                   1612:            *p1 = c;
                   1613:          p1++;
                   1614:        }
                   1615:       else if (c == '\t')
                   1616:        {
                   1617:          do
                   1618:            {
                   1619:              if (p1 >= start)
                   1620:                *p1 = ' ';
                   1621:              p1++;
                   1622:            }
                   1623:          while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
                   1624:        }
                   1625:       else if (c < 0200 && default_ctl_arrow)
                   1626:        {
                   1627:          if (p1 >= start)
                   1628:            *p1 = '^';
                   1629:          p1++;
                   1630:          if (p1 >= start)
                   1631:            *p1 = c ^ 0100;
                   1632:          p1++;
                   1633:        }
                   1634:       else
                   1635:        {
                   1636:          if (p1 >= start)
                   1637:            *p1 = '\\';
                   1638:          p1++;
                   1639:          if (p1 >= start)
                   1640:            *p1 = (c >> 6) + '0';
                   1641:          p1++;
                   1642:          if (p1 >= start)
                   1643:            *p1 = (7 & (c >> 3)) + '0';
                   1644:          p1++;
                   1645:          if (p1 >= start)
                   1646:            *p1 = (7 & c) + '0';
                   1647:          p1++;
                   1648:        }
                   1649:     }
                   1650: 
                   1651:   if (c)
                   1652:     {
                   1653:       p1 = end;
                   1654:       if (truncate) *p1++ = truncate;
                   1655:     }
                   1656: 
                   1657:   line->length = max (line->length, p1 - (unsigned char *) line->body);
                   1658:   line->body[line->length] = 0;
                   1659:   return p1 - (unsigned char *) line->body;
                   1660: }
                   1661: 
                   1662: syms_of_xdisp ()
                   1663: {
                   1664:   DefLispVar ("global-mode-string", &Vglobal_mode_string,
                   1665:     "String which mode line can display (if its format requests to).");
                   1666:   Vglobal_mode_string = Qnil;
                   1667: 
                   1668:   DefLispVar ("global-minor-modes", &Vglobal_minor_modes,
                   1669:     "Alist of minor modes that are not per buffer.\n\
                   1670: Cdr of each element is a string to display in mode line.");
                   1671: 
                   1672:   DefIntVar ("scroll-step", &scroll_step,
                   1673:     "*The number of lines to try scrolling a window by when point moves out.\n\
                   1674: If that fails to bring point back on screen, point is centered instead.\n\
                   1675: If this is zero, point is always centered after it moves off screen.");
                   1676: 
                   1677:   DefIntVar ("debug-end-pos", &debug_end_pos, "Don't ask");
                   1678: 
                   1679:   DefBoolVar ("truncate-partial-width-windows",
                   1680:             &truncate_partial_width_windows,
                   1681:     "*Non-nil means truncate lines in all windows less than full screen wide.");
                   1682:   truncate_partial_width_windows = 1;
                   1683: 
                   1684:   DefBoolVar ("mode-line-inverse-video", &mode_line_inverse_video,
                   1685:     "*Non-nil means use inverse video, or other suitable display mode, for the mode line.");
                   1686:   mode_line_inverse_video = 1;
                   1687: 
                   1688:   defsubr (&Sredraw_display);
                   1689: }
                   1690: 
                   1691: /* initialize the window system */
                   1692: init_xdisp ()
                   1693: {
                   1694:   Lisp_Object root_window;
                   1695: #ifndef COMPILER_REGISTER_BUG
                   1696:   register
                   1697: #endif COMPILER_REGISTER_BUG
                   1698:     struct window *mini_w;
                   1699: 
                   1700:   this_line_bufpos = 0;
                   1701: 
                   1702:   mini_w = XWINDOW (minibuf_window);
                   1703:   root_window = mini_w->prev;
                   1704: 
                   1705:   minibuf_message = 0;
                   1706:   prev_minibuf_message = 0;
                   1707: 
                   1708:   if (!noninteractive)
                   1709:     {
                   1710:       XFASTINT (XWINDOW (root_window)->top) = 0;
                   1711:       set_window_height (root_window, screen_height - 1, 0);
                   1712:       XFASTINT (mini_w->top) = screen_height - 1;
                   1713:       set_window_height (minibuf_window, 1, 0);
                   1714: 
                   1715:       XFASTINT (XWINDOW (root_window)->width) = screen_width;
                   1716:       XFASTINT (mini_w->width) = screen_width;
                   1717:     }
                   1718: }

unix.superglobalmegacorp.com

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