Annotation of 43BSD/contrib/emacs/src/xdisp.c, revision 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.