Annotation of GNUtools/emacs/src/dispnew.c, revision 1.1

1.1     ! root        1: /* Newly written part of redisplay code.
        !             2:    Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU Emacs.
        !             5: 
        !             6: GNU Emacs is free software; you can redistribute it and/or modify
        !             7: it under the terms of the GNU General Public License as published by
        !             8: the Free Software Foundation; either version 1, or (at your option)
        !             9: any later version.
        !            10: 
        !            11: GNU Emacs is distributed in the hope that it will be useful,
        !            12: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: GNU General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GNU Emacs; see the file COPYING.  If not, write to
        !            18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            19: 
        !            20: 
        !            21: /* This must precede sys/signal.h on certain machines.  */
        !            22: #include <sys/types.h>
        !            23: #include <signal.h>
        !            24: 
        !            25: #include "config.h"
        !            26: #include <stdio.h>
        !            27: #include <errno.h>
        !            28: 
        !            29: #ifdef HAVE_TIMEVAL
        !            30: #ifdef HPUX
        !            31: #include <time.h>
        !            32: #else
        !            33: #include <sys/time.h>
        !            34: #endif
        !            35: #endif
        !            36: 
        !            37: #ifdef HAVE_TERMIO
        !            38: #include <termio.h>
        !            39: #ifdef TCOUTQ
        !            40: #undef TIOCOUTQ
        !            41: #define TIOCOUTQ TCOUTQ
        !            42: #include <fcntl.h>
        !            43: #endif /* TCOUTQ defined */
        !            44: #else
        !            45: #ifndef VMS
        !            46: #include <sys/ioctl.h>
        !            47: #endif /* not VMS */
        !            48: #endif /* not HAVE_TERMIO */
        !            49: 
        !            50: /* Allow m- file to inhibit use of FIONREAD.  */
        !            51: #ifdef BROKEN_FIONREAD
        !            52: #undef FIONREAD
        !            53: #endif
        !            54: 
        !            55: /* We are unable to use interrupts if FIONREAD is not available,
        !            56:    so flush SIGIO so we won't try. */
        !            57: #ifndef FIONREAD
        !            58: #ifdef SIGIO
        !            59: #undef SIGIO
        !            60: #endif
        !            61: #endif
        !            62: 
        !            63: #undef NULL
        !            64: 
        !            65: #include "termchar.h"
        !            66: #include "termopts.h"
        !            67: #include "cm.h"
        !            68: #include "dispextern.h"
        !            69: #include "lisp.h"
        !            70: #include "buffer.h"
        !            71: #include "window.h"
        !            72: #include "commands.h"
        !            73: 
        !            74: #define max(a, b) ((a) > (b) ? (a) : (b))
        !            75: #define min(a, b) ((a) < (b) ? (a) : (b))
        !            76: 
        !            77: #ifndef PENDING_OUTPUT_COUNT
        !            78: /* Get number of chars of output now in the buffer of a stdio stream.
        !            79:    This ought to be built in in stdio, but it isn't.
        !            80:    Some s- files override this because their stdio internals differ.  */
        !            81: #ifdef __GNU_LIBRARY__
        !            82: #define        PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
        !            83: #else
        !            84: #define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
        !            85: #endif
        !            86: #endif /* No PENDING_OUTPUT_COUNT */
        !            87: 
        !            88: /* Nonzero means do not assume anything about current
        !            89:    contents of actual terminal screen */
        !            90: 
        !            91: int screen_garbaged;
        !            92: 
        !            93: /* Desired terminal cursor position (to show position of point),
        !            94:    origin zero */
        !            95: 
        !            96: int cursor_hpos, cursor_vpos;
        !            97: 
        !            98: /* Nonzero means last display completed and cursor is really at
        !            99:    cursor_hpos, cursor_vpos.  Zero means it was preempted. */
        !           100: 
        !           101: int display_completed;
        !           102: 
        !           103: /* Lisp variable visible-bell; enables use of screen-flash
        !           104:    instead of audible bell.  */
        !           105: 
        !           106: int visible_bell;
        !           107: 
        !           108: /* Invert the color of the whole screen, at a low level.  */
        !           109: 
        !           110: int inverse_video;
        !           111: 
        !           112: /* Line speed of the terminal.  */
        !           113: 
        !           114: int baud_rate;
        !           115: 
        !           116: /* nil or a symbol naming the window system
        !           117:    under which emacs is running
        !           118:    ('x is the only current possibility).  */
        !           119: 
        !           120: Lisp_Object Vwindow_system;
        !           121: 
        !           122: /* Version number of window system, or nil if no window system.  */
        !           123: 
        !           124: Lisp_Object Vwindow_system_version;
        !           125: 
        !           126: /* Nonzero means reading single-character input with prompt
        !           127:    so put cursor on minibuffer after the prompt.  */
        !           128: 
        !           129: int cursor_in_echo_area;
        !           130: 
        !           131: /* Nonzero means finish redisplay regardless of available input.
        !           132:    This is used with X windows to avoid a weird timing-dependent bug.  */
        !           133: 
        !           134: int force_redisplay;
        !           135: 
        !           136: /* Description of actual screen contents.  */
        !           137:  
        !           138: struct matrix *current_screen;
        !           139: 
        !           140: /* Description of desired screen contents.  */
        !           141: 
        !           142: struct matrix *new_screen;
        !           143: 
        !           144: /* Buffer sometimes used to hold partial screen contents.  */
        !           145: 
        !           146: struct matrix *temp_screen;
        !           147: 
        !           148: /* Stdio stream being used for copy of all terminal output.  */
        !           149: 
        !           150: FILE *termscript;
        !           151: 
        !           152: /* Structure for info on cursor positioning */
        !           153: 
        !           154: struct cm Wcm;
        !           155: 
        !           156: int delayed_size_change;  /* 1 means SIGWINCH happened when not safe.  */
        !           157: int delayed_screen_height;  /* Remembered new screen height.  */
        !           158: int delayed_screen_width;   /* Remembered new screen width.  */
        !           159: 
        !           160: /* This buffer records the history of display preemption.  */
        !           161: 
        !           162: struct preempt
        !           163: {
        !           164:   /* Number of keyboard characters read so far at preempt.  */
        !           165:   int keyboard_char_count;
        !           166:   /* Vertical position at which preemption occurred.  */
        !           167:   int vpos;
        !           168: };
        !           169: 
        !           170: #define N_PREEMPTIONS 50
        !           171: 
        !           172: /* Circular buffer recording recent display preemptions.  */
        !           173: struct preempt preemptions[N_PREEMPTIONS];
        !           174: 
        !           175: /* Index of next element in preemptions.  */
        !           176: int preemption_index;
        !           177: 
        !           178: /* Set these variables in the debugger to force a display preemption.  */
        !           179: int debug_preemption_vpos = -1;
        !           180: int debug_preemption_char_count = -1;
        !           181: 
        !           182: extern int num_input_chars;
        !           183: 
        !           184: /* Free and reallocate current_screen and new_screen.  */
        !           185: 
        !           186: struct matrix *make_screen_structure ();
        !           187: 
        !           188: remake_screen_structures ()
        !           189: {
        !           190:   int i;
        !           191: 
        !           192:   if (current_screen)
        !           193:     free_screen_structure (current_screen);
        !           194:   if (new_screen)
        !           195:     free_screen_structure (new_screen);
        !           196:   if (temp_screen)
        !           197:     free_screen_structure (temp_screen);
        !           198: 
        !           199:   current_screen = make_screen_structure (0);
        !           200:   new_screen = make_screen_structure (0);
        !           201:   temp_screen = make_screen_structure (1);
        !           202: 
        !           203:   if (message_buf)
        !           204:     {
        !           205:       /* The echo_area_contents, used by error and message, may be pointing at
        !           206:         the string we are replacing.  If so, update it.  */
        !           207:       int repair_echo_area_contents = echo_area_contents == message_buf;
        !           208: 
        !           209:       message_buf = (char *) xrealloc (message_buf, screen_width + 1);
        !           210: 
        !           211:       if (repair_echo_area_contents) echo_area_contents = message_buf;
        !           212:     } 
        !           213:   else
        !           214:     message_buf = (char *) xmalloc (screen_width + 1);
        !           215: 
        !           216:   /* This may fix a problem of occasionally displaying garbage in the echo area
        !           217:      after a resize in X Windows.  */
        !           218:   for (i = 0; i < screen_width; i++)
        !           219:     message_buf[i] = ' ';
        !           220:   message_buf[screen_width] = 0;
        !           221: }
        !           222: 
        !           223: struct matrix *
        !           224: make_screen_structure (empty)
        !           225:      int empty;
        !           226: {
        !           227:   int i;
        !           228:   struct matrix *new = (struct matrix *) xmalloc (sizeof (struct matrix));
        !           229: 
        !           230:   new->height = screen_height;
        !           231:   new->width = screen_width;
        !           232:   new->highlight = (char *) xmalloc (screen_height);
        !           233:   new->enable = (char *) xmalloc (screen_height);
        !           234:   new->contents = (unsigned char **) xmalloc (screen_height * sizeof (char *));
        !           235:   new->used = (int *) xmalloc (screen_height * sizeof (int));
        !           236:   if (empty)
        !           237:     {
        !           238:       /* Make the buffer used by decode_mode_spec.  */
        !           239:       new->total_contents = (unsigned char *) xmalloc (screen_width + 2);
        !           240:       for (i = 0; i < screen_width; i++)
        !           241:        new->total_contents[i] = ' ';
        !           242:       new->total_contents[screen_width] = 0;
        !           243:     }
        !           244:   else
        !           245:     {
        !           246:       /* Add 2 to leave extra bytes at beginning and end of each line.  */ 
        !           247:       new->total_contents = (unsigned char *) xmalloc (screen_height * (screen_width + 2));
        !           248:       for (i = 0; i < screen_height; i++)
        !           249:        {
        !           250:          int j;
        !           251: 
        !           252:          new->contents[i] = new->total_contents + i * (screen_width + 2) + 1;
        !           253:          new->contents[i][screen_width] = 0;
        !           254:          new->contents[i][-1] = 0;
        !           255:          for (j = 0; j < screen_width; j++)
        !           256:            new->contents[i][j] = ' ';
        !           257:        }
        !           258:     }
        !           259:   bzero (new->enable, screen_height);
        !           260:   return new;
        !           261: }
        !           262: 
        !           263: free_screen_structure (matrix)
        !           264:      struct matrix *matrix;
        !           265: {
        !           266:   if (matrix->total_contents)
        !           267:     free (matrix->total_contents);
        !           268:   free (matrix->contents);
        !           269:   free (matrix->highlight);
        !           270:   free (matrix->enable);
        !           271:   free (matrix->used);
        !           272:   free (matrix);
        !           273: }
        !           274: 
        !           275: /* Return the hash code of contents of line VPOS of screen-matrix M.  */
        !           276: 
        !           277: int
        !           278: line_hash_code (m, vpos)
        !           279:      struct matrix *m;
        !           280:      int vpos;
        !           281: {
        !           282:   register unsigned char *body;
        !           283:   register int h = 0;
        !           284:   /* Give all lighlighted lines the same hash code
        !           285:      so as to encourage scrolling to leave them in place.  */
        !           286:   if (m->highlight[vpos])
        !           287:     return -1;
        !           288: 
        !           289:   body = m->contents[vpos];
        !           290: 
        !           291:   if (must_write_spaces)
        !           292:     {
        !           293:       while (1)
        !           294:        {
        !           295:          int c = *body++;
        !           296:          if (c == 0)
        !           297:            break;
        !           298:          h = (((h << 4) + (h >> 24)) & 0x0fffffff) + c - ' ';
        !           299:        }
        !           300:     }
        !           301:   else
        !           302:     {
        !           303:       while (1)
        !           304:        {
        !           305:          int c = *body++;
        !           306:          if (c == 0)
        !           307:            break;
        !           308:          h = (((h << 4) + (h >> 24)) & 0x0fffffff) + c;
        !           309:        }
        !           310:     }
        !           311:   if (h)
        !           312:     return h;
        !           313:   return 1;
        !           314: }
        !           315: 
        !           316: /* Return number of characters in line in M at vpos VPOS,
        !           317:    except don't count leading and trailing spaces
        !           318:    unless the terminal requires those to be explicitly output.  */
        !           319: 
        !           320: int
        !           321: line_draw_cost (m, vpos)
        !           322:      struct matrix *m;
        !           323:      int vpos;
        !           324: {
        !           325:   register unsigned char *body;
        !           326:   register int i;
        !           327: 
        !           328:   if (must_write_spaces)
        !           329:     return m->used[vpos];
        !           330: 
        !           331:   body = m->contents[vpos];
        !           332:   for (i = m->used[vpos]; i > 0 && body[i - 2] == ' '; i--);
        !           333: 
        !           334:   i -= count_blanks (body);
        !           335:   return max (i, 0);
        !           336: }
        !           337: 
        !           338: /* The functions on this page are the interface from xdisp.c to redisplay.
        !           339: 
        !           340:  The only other interface into redisplay is through setting
        !           341:  cursor_hpos and cursor_vpos (in xdisp.c) and setting screen_garbaged. */
        !           342: 
        !           343: /* cancel_line eliminates any request to display a line at position `vpos' */
        !           344: 
        !           345: cancel_line (vpos)
        !           346:      int vpos;
        !           347: {
        !           348:   new_screen->enable[vpos] = 0;
        !           349: }
        !           350: 
        !           351: clear_screen_records ()
        !           352: {
        !           353:   int i;
        !           354: 
        !           355:   bzero (current_screen->enable, screen_height);
        !           356: }
        !           357: 
        !           358: /* Get ready to display on line `vpos'
        !           359:    and set it up for outputting starting at `hpos' within it.
        !           360:    Return the text string where that line is stored.  */
        !           361: 
        !           362: unsigned char *
        !           363: get_display_line (vpos, hpos)
        !           364:      int vpos;
        !           365:      register int hpos;
        !           366: {
        !           367:   if (new_screen->enable[vpos] && new_screen->used[vpos] > hpos)
        !           368:     abort ();
        !           369:   if (! new_screen->enable[vpos])
        !           370:     {
        !           371:       new_screen->used[vpos] = 0;
        !           372:       new_screen->highlight[vpos] = 0;
        !           373:       new_screen->enable[vpos] = 1;
        !           374:     }
        !           375: 
        !           376:   if (hpos > new_screen->used[vpos])
        !           377:     {
        !           378:       unsigned char *p = new_screen->contents[vpos] + new_screen->used[vpos];
        !           379:       unsigned char *end = new_screen->contents[vpos] + hpos;
        !           380:       new_screen->used[vpos] = hpos;
        !           381:       while (p != end)
        !           382:        *p++ = ' ';
        !           383:     }
        !           384: 
        !           385:   return new_screen->contents[vpos];
        !           386: }
        !           387: 
        !           388: /* Scroll lines from vpos `from' up to but not including vpos `end'
        !           389:  down by `amount' lines (`amount' may be negative).
        !           390:  Returns nonzero if done, zero if terminal cannot scroll them. */
        !           391: 
        !           392: int
        !           393: scroll_screen_lines (from, end, amount)
        !           394:      int from, end, amount;
        !           395: {
        !           396:   register int i;
        !           397: 
        !           398:   if (!line_ins_del_ok)
        !           399:     return 0;
        !           400: 
        !           401:   if (amount == 0)
        !           402:     return 1;
        !           403:   if (amount > 0)
        !           404:     {
        !           405:       set_terminal_window (end + amount);
        !           406:       if (!scroll_region_ok)
        !           407:        ins_del_lines (end, -amount);
        !           408:       ins_del_lines (from, amount);
        !           409:       set_terminal_window (0);
        !           410: 
        !           411:       rotate_vector (current_screen->contents + from,
        !           412:                     sizeof (char *) * (end + amount - from),
        !           413:                     amount * sizeof (char *));
        !           414:       safe_bcopy (current_screen->used + from,
        !           415:                  current_screen->used + from + amount,
        !           416:                  (end - from) * sizeof current_screen->used[0]);
        !           417:       safe_bcopy (current_screen->highlight + from,
        !           418:                  current_screen->highlight + from + amount,
        !           419:                  (end - from) * sizeof current_screen->highlight[0]);
        !           420:       safe_bcopy (current_screen->enable + from,
        !           421:                  current_screen->enable + from + amount,
        !           422:                  (end - from) * sizeof current_screen->enable[0]);
        !           423:       /* Mark the lines made empty by scrolling as enabled, empty and
        !           424:         normal video.  */
        !           425:       bzero (current_screen->used + from,
        !           426:             amount * sizeof current_screen->used[0]);
        !           427:       bzero (current_screen->highlight + from,
        !           428:             amount * sizeof current_screen->highlight[0]);
        !           429:       for (i = from; i < from + amount; i++)
        !           430:        {
        !           431:          current_screen->contents[i][0] = '\0';
        !           432:          current_screen->enable[i] = 1;
        !           433:        }
        !           434:     }
        !           435:   if (amount < 0)
        !           436:     {
        !           437:       set_terminal_window (end);
        !           438:       ins_del_lines (from + amount, amount);
        !           439:       if (!scroll_region_ok)
        !           440:        ins_del_lines (end + amount, -amount);
        !           441:       set_terminal_window (0);
        !           442: 
        !           443:       rotate_vector (current_screen->contents + from + amount,
        !           444:                     sizeof (char *) * (end - from - amount),
        !           445:                     (end - from) * sizeof (char *));
        !           446:       safe_bcopy (current_screen->used + from,
        !           447:                  current_screen->used + from + amount,
        !           448:                  (end - from) * sizeof current_screen->used[0]);
        !           449:       safe_bcopy (current_screen->highlight + from,
        !           450:                  current_screen->highlight + from + amount,
        !           451:                  (end - from) * sizeof current_screen->highlight[0]);
        !           452:       safe_bcopy (current_screen->enable + from,
        !           453:                  current_screen->enable + from + amount,
        !           454:                  (end - from) * sizeof current_screen->enable[0]);
        !           455:       /* Mark the lines made empty by scrolling as enabled, empty and
        !           456:         normal video.  */
        !           457:       bzero (current_screen->used + end + amount,
        !           458:             - amount * sizeof current_screen->used[0]);
        !           459:       bzero (current_screen->highlight + end + amount,
        !           460:             - amount * sizeof current_screen->highlight[0]);
        !           461:       for (i = end + amount; i < end; i++)
        !           462:        {
        !           463:          current_screen->contents[i][0] = '\0';
        !           464:          current_screen->enable[i] = 1;
        !           465:        }
        !           466:     }
        !           467:   return 1;
        !           468: }
        !           469: 
        !           470: /* Rotate a vector of SIZE bytes, by DISTANCE bytes.
        !           471:    DISTANCE may be negative.  */
        !           472: 
        !           473: rotate_vector (vector, size, distance)
        !           474:      char *vector;
        !           475:      int size;
        !           476:      int distance;
        !           477: {
        !           478:   char *temp = (char *) alloca (size);
        !           479: 
        !           480:   if (distance < 0)
        !           481:     distance += size;
        !           482: 
        !           483:   bcopy (vector, temp + distance, size - distance);
        !           484:   bcopy (vector + size - distance, temp, distance);
        !           485:   bcopy (temp, vector, size);
        !           486: }
        !           487: 
        !           488: /* Like bcopy except never gets confused by overlap.  */
        !           489: 
        !           490: safe_bcopy (from, to, size)
        !           491:      char *from, *to;
        !           492:      int size;
        !           493: {
        !           494:   register char *endf;
        !           495:   register char *endt;
        !           496: 
        !           497:   if (size == 0)
        !           498:     return;
        !           499:   if (from > to)
        !           500:     {
        !           501:       /* If destination is lower in memory, we can go from the beginning.  */
        !           502:       endf = from + size;
        !           503:       while (from != endf)
        !           504:        *to++ = *from++;
        !           505:       return;
        !           506:     }
        !           507: 
        !           508:   /* If destination is higher in memory, we can go backwards from the end.  */
        !           509:   endf = from + size;
        !           510:   endt = to + size;
        !           511: 
        !           512:   do
        !           513:     *--endt = *--endf;
        !           514:   while (endf != from);
        !           515: }
        !           516: 
        !           517: /* After updating a window w that isn't the full screen wide,
        !           518:  copy all the columns that w does not occupy
        !           519:  from current_screen to new_screen,
        !           520:  so that update_screen will not change those columns.  */
        !           521: 
        !           522: preserve_other_columns (w)
        !           523:      struct window *w;
        !           524: {
        !           525:   register int vpos;
        !           526:   int start = XFASTINT (w->left);
        !           527:   int end = XFASTINT (w->left) + XFASTINT (w->width);
        !           528:   int bot = XFASTINT (w->top) + XFASTINT (w->height);
        !           529: 
        !           530:   for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
        !           531:     {
        !           532:       if (current_screen->enable[vpos] && new_screen->enable[vpos])
        !           533:        {
        !           534:          if (start > 0)
        !           535:            {
        !           536:              int len;
        !           537: 
        !           538:              bcopy (current_screen->contents[vpos],
        !           539:                     new_screen->contents[vpos], start);
        !           540:              len = min (start, current_screen->used[vpos]);
        !           541:              if (new_screen->used[vpos] < len)
        !           542:                new_screen->used[vpos] = len;
        !           543:            }
        !           544:          if (current_screen->used[vpos] > end
        !           545:              && new_screen->used[vpos] < current_screen->used[vpos])
        !           546:            {
        !           547:              while (new_screen->used[vpos] < end)
        !           548:                new_screen->contents[vpos][new_screen->used[vpos]++] = ' ';
        !           549:              bcopy (current_screen->contents[vpos] + end,
        !           550:                     new_screen->contents[vpos] + end,
        !           551:                     current_screen->used[vpos] - end);
        !           552:              new_screen->used[vpos] = current_screen->used[vpos];
        !           553:            }
        !           554:        }
        !           555:     }
        !           556: }
        !           557: 
        !           558: /* On discovering that the redisplay for a window was no good,
        !           559:  cancel the columns of that window,
        !           560:  so that when the window is displayed over again
        !           561:  get_display_line will not complain. */
        !           562: 
        !           563: cancel_my_columns (w)
        !           564:      struct window *w;
        !           565: {
        !           566:   register int vpos;
        !           567:   register int start = XFASTINT (w->left);
        !           568:   register int bot = XFASTINT (w->top) + XFASTINT (w->height);
        !           569: 
        !           570:   for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
        !           571:     if (new_screen->enable[vpos] && new_screen->used[vpos] >= start)
        !           572:       new_screen->used[vpos] = start;
        !           573: }
        !           574: 
        !           575: /* These functions try to perform directly and immediately on the screen
        !           576:    the necessary output for one change in the buffer.
        !           577:    They may return 0 meaning nothing was done if anything is difficult,
        !           578:    or 1 meaning the output was performed properly.
        !           579:    They assume that the screen was up to date before the buffer
        !           580:    change being displayed.  THey make various other assumptions too;
        !           581:    see command_loop_1 where these are called.  */
        !           582: 
        !           583: int
        !           584: direct_output_for_insert (c)
        !           585:      int c;
        !           586: {
        !           587: #ifndef COMPILER_REGISTER_BUG
        !           588:   register
        !           589: #endif COMPILER_REGISTER_BUG
        !           590:     struct window *w = XWINDOW (selected_window);
        !           591: #ifndef COMPILER_REGISTER_BUG
        !           592:   register
        !           593: #endif COMPILER_REGISTER_BUG
        !           594:     int hpos = cursor_hpos;
        !           595: #ifndef COMPILER_REGISTER_BUG
        !           596:   register
        !           597: #endif COMPILER_REGISTER_BUG
        !           598:     int vpos = cursor_vpos;
        !           599: 
        !           600:   /* Give up if about to continue line */
        !           601:   if (hpos - XFASTINT (w->left) + 1 + 1 >= XFASTINT (w->width)
        !           602: 
        !           603:   /* Avoid losing if cursor is in invisible text off left margin */
        !           604:       || (XINT (w->hscroll) && hpos == XFASTINT (w->left))
        !           605:     
        !           606:   /* Give up if cursor outside window (in minibuf, probably) */
        !           607:       || cursor_vpos < XFASTINT (w->top)
        !           608:       || cursor_vpos >= XFASTINT (w->top) + XFASTINT (w->height)
        !           609: 
        !           610:   /* Give up if cursor not really at cursor_hpos, cursor_vpos */
        !           611:       || !display_completed
        !           612: 
        !           613:   /* Give up if w is minibuffer and a message is being displayed there */
        !           614:       || (EQ (selected_window, minibuf_window) && echo_area_contents))
        !           615:     return 0;
        !           616: 
        !           617:   current_screen->contents[vpos][hpos] = c;
        !           618:   unchanged_modified = MODIFF;
        !           619:   beg_unchanged = GPT - BEG;
        !           620:   XFASTINT (w->last_point) = point;
        !           621:   XFASTINT (w->last_point_x) = cursor_hpos;
        !           622:   XFASTINT (w->last_modified) = MODIFF;
        !           623: 
        !           624:   reassert_line_highlight (0, cursor_vpos);
        !           625:   output_chars (&current_screen->contents[vpos][hpos], 1);
        !           626:   fflush (stdout);
        !           627:   ++cursor_hpos;
        !           628:   if (hpos == current_screen->used[vpos])
        !           629:     {
        !           630:       current_screen->used[vpos] = hpos + 1;
        !           631:       current_screen->contents[vpos][hpos + 1] = 0;
        !           632:     }
        !           633:   return 1;
        !           634: }
        !           635: 
        !           636: int
        !           637: direct_output_forward_char (n)
        !           638:      int n;
        !           639: {
        !           640:   register struct window *w = XWINDOW (selected_window);
        !           641: 
        !           642:   /* Avoid losing if cursor is in invisible text off left margin */
        !           643:   if (XINT (w->hscroll) && cursor_hpos == XFASTINT (w->left))
        !           644:     return 0;
        !           645:   /* Don't lose if we are in the truncated text at the end.  */
        !           646:   if (cursor_hpos >= XFASTINT (w->left) + XFASTINT (w->width) - 1)
        !           647:     return 0;
        !           648:   /* Don't move past the window edges.  */
        !           649:   if (cursor_hpos + n >= XFASTINT (w->left) + XFASTINT (w->width) - 1)
        !           650:     return 0;
        !           651:   if (cursor_hpos + n <= XFASTINT (w->left))
        !           652:     return 0;
        !           653: 
        !           654:   cursor_hpos += n;
        !           655:   XFASTINT (w->last_point_x) = cursor_hpos;
        !           656:   XFASTINT (w->last_point) = point;
        !           657:   move_cursor (cursor_vpos, cursor_hpos);
        !           658:   fflush (stdout);
        !           659:   return 1;
        !           660: }
        !           661: 
        !           662: /* Update the actual terminal screen based on the data in new_screen.
        !           663:    Value is nonzero if redisplay stopped due to pending input.
        !           664:    FORCE nonzero means do not stop for pending input.  */
        !           665: 
        !           666: update_screen (force, inhibit_hairy_id)
        !           667:      int force;
        !           668:      int inhibit_hairy_id;
        !           669: {
        !           670:   register struct display_line **p;
        !           671:   register struct display_line *l, *lnew;
        !           672:   register int i;
        !           673:   int pause;
        !           674:   int preempt_count = baud_rate / 2400 + 1;
        !           675:   extern input_pending;
        !           676: 
        !           677:   if (screen_height == 0) abort (); /* Some bug zeros some core */
        !           678: 
        !           679:   if (force_redisplay)
        !           680:     force = 1;
        !           681: 
        !           682:   if (!force)
        !           683:     detect_input_pending ();
        !           684:   if (!force
        !           685:       && ((num_input_chars == debug_preemption_char_count
        !           686:           && debug_preemption_vpos == screen_height - 1)
        !           687:          || input_pending))
        !           688:     {
        !           689:       pause = screen_height;
        !           690:       goto do_pause;
        !           691:     }
        !           692: 
        !           693:   update_begin ();
        !           694: 
        !           695:   if (!line_ins_del_ok)
        !           696:     inhibit_hairy_id = 1;
        !           697: 
        !           698:   /* Don't compute for i/d line if just want cursor motion. */
        !           699:   for (i = 0; i < screen_height; i++)
        !           700:     if (new_screen->enable)
        !           701:       break;
        !           702: 
        !           703:   /* Try doing i/d line, if not yet inhibited.  */
        !           704:   if (!inhibit_hairy_id && i < screen_height)
        !           705:     force |= scrolling ();
        !           706: 
        !           707:   /* Update the individual lines as needed.  Do bottom line first.  */
        !           708: 
        !           709:   if (new_screen->enable[screen_height - 1])
        !           710:     update_line (screen_height - 1);
        !           711:   for (i = 0; i < screen_height - 1 && (force || !input_pending); i++)
        !           712:     {
        !           713:       if (!force && num_input_chars == debug_preemption_char_count
        !           714:          && debug_preemption_vpos == i)
        !           715:        break;
        !           716:       if (new_screen->enable[i])
        !           717:        {
        !           718:          /* Flush out every so many lines.
        !           719:             Also flush out if likely to have more than 1k buffered
        !           720:             otherwise.   I'm told that telnet connections get really
        !           721:             screwed by more than 1k output at once.  */
        !           722:          int outq = PENDING_OUTPUT_COUNT (stdout);
        !           723:          if (outq > 900
        !           724:              || (outq > 20 && ((i - 1) % preempt_count == 0)))
        !           725:            {
        !           726:              fflush (stdout);
        !           727:              if (preempt_count == 1)
        !           728:                {
        !           729: #ifdef TIOCOUTQ
        !           730:                  if (ioctl (0, TIOCOUTQ, &outq) < 0)
        !           731:                    /* Probably not a tty.  Ignore the error and reset
        !           732:                     * the outq count. */
        !           733:                    outq = PENDING_OUTPUT_COUNT (stdout);
        !           734: #endif
        !           735:                  outq *= 10;
        !           736:                  sleep (outq / baud_rate);
        !           737:                }
        !           738:            }
        !           739:          if ((i - 1) % preempt_count == 0 && !force)
        !           740:            detect_input_pending ();
        !           741:          /* Now update this line.  */
        !           742:          update_line (i);
        !           743:        }
        !           744:     }
        !           745:   pause = (i < screen_height - 1) ? i + 1 : 0;
        !           746: 
        !           747:   /* Now just clean up termcap drivers and set cursor, etc.  */
        !           748:   if (!pause)
        !           749:     {
        !           750:       if (cursor_in_echo_area < 0)
        !           751:        move_cursor (screen_height - 1, 0);
        !           752:       else if (cursor_in_echo_area > 0
        !           753:               && !current_screen->enable[screen_height - 1])
        !           754:        move_cursor (screen_height - 1, 0);
        !           755:       else if (cursor_in_echo_area)
        !           756:        move_cursor (screen_height - 1,
        !           757:                     min (screen_width - 1,
        !           758:                          current_screen->used[screen_height - 1]));
        !           759:       else
        !           760:        move_cursor (cursor_vpos, max (min (cursor_hpos, screen_width - 1), 0));
        !           761:     }
        !           762: 
        !           763:   update_end ();
        !           764: 
        !           765:   if (termscript)
        !           766:     fflush (termscript);
        !           767:   fflush (stdout);
        !           768: 
        !           769:   /* Here if output is preempted because input is detected.  */
        !           770:  do_pause:
        !           771: 
        !           772:   if (screen_height == 0) abort (); /* Some bug zeros some core */
        !           773:   display_completed = !pause;
        !           774:   if (pause)
        !           775:     {
        !           776:       preemptions[preemption_index].vpos = pause - 1;
        !           777:       preemptions[preemption_index].keyboard_char_count = num_input_chars;
        !           778:       preemption_index++;
        !           779:       if (preemption_index == N_PREEMPTIONS)
        !           780:        preemption_index = 0;
        !           781:     }
        !           782: 
        !           783:   bzero (new_screen->enable, screen_height);
        !           784:   return pause;
        !           785: }
        !           786: 
        !           787: /* Called when about to quit, to check for doing so
        !           788:    at an improper time.  */
        !           789: 
        !           790: void
        !           791: quit_error_check ()
        !           792: {
        !           793:   if (new_screen == 0)
        !           794:     return;
        !           795:   if (new_screen->enable[0])
        !           796:     abort ();
        !           797:   if (new_screen->enable[screen_height - 1])
        !           798:     abort ();
        !           799: }
        !           800: 
        !           801: /* Decide what insert/delete line to do, and do it */
        !           802: 
        !           803: scrolling ()
        !           804: {
        !           805:   int unchanged_at_top, unchanged_at_bottom;
        !           806:   int window_size;
        !           807:   int changed_lines;
        !           808:   int *old_hash = (int *) alloca (screen_height * sizeof (int));
        !           809:   int *new_hash = (int *) alloca (screen_height * sizeof (int));
        !           810:   int *draw_cost = (int *) alloca (screen_height * sizeof (int));
        !           811:   register int i;
        !           812:   int free_at_end_vpos = screen_height;
        !           813:   
        !           814:   /* Compute hash codes of all the lines.
        !           815:      Also calculate number of changed lines,
        !           816:      number of unchanged lines at the beginning,
        !           817:      and number of unchanged lines at the end.  */
        !           818: 
        !           819:   changed_lines = 0;
        !           820:   unchanged_at_top = 0;
        !           821:   unchanged_at_bottom = screen_height;
        !           822:   for (i = 0; i < screen_height; i++)
        !           823:     {
        !           824:       /* Give up on this scrolling if some old lines are not enabled.  */
        !           825:       if (!current_screen->enable[i])
        !           826:        return 0;
        !           827:       old_hash[i] = line_hash_code (current_screen, i);
        !           828:       if (!new_screen->enable[i])
        !           829:        new_hash[i] = old_hash[i];
        !           830:       else
        !           831:        new_hash[i] = line_hash_code (new_screen, i);
        !           832:       if (old_hash[i] != new_hash[i])
        !           833:        {
        !           834:          changed_lines++;
        !           835:          unchanged_at_bottom = screen_height - i - 1;
        !           836:        }
        !           837:       else if (i == unchanged_at_top)
        !           838:        unchanged_at_top++;
        !           839:       /* If line is not changing, its redraw cost is infinite,
        !           840:         since we can't redraw it.  */
        !           841:       if (!new_screen->enable[i])
        !           842:        draw_cost[i] = INFINITY;
        !           843:       else
        !           844:        draw_cost[i] = line_draw_cost (new_screen, i);
        !           845:     }
        !           846: 
        !           847:   /* If changed lines are few, don't allow preemption, don't scroll.  */
        !           848:   if (changed_lines < baud_rate / 2400 || unchanged_at_bottom == screen_height)
        !           849:     return 1;
        !           850: 
        !           851:   window_size = screen_height - unchanged_at_top - unchanged_at_bottom;
        !           852: 
        !           853:   if (scroll_region_ok)
        !           854:     free_at_end_vpos -= unchanged_at_bottom;
        !           855:   else if (memory_below_screen)
        !           856:     free_at_end_vpos = -1;
        !           857: 
        !           858:   /* If large window, fast terminal and few lines in common between
        !           859:      current_screen and new_screen, don't bother with i/d calc.  */
        !           860:   if (window_size >= 18 && baud_rate > 2400
        !           861:       && (window_size >=
        !           862:          10 * scrolling_max_lines_saved (unchanged_at_top,
        !           863:                                          screen_height - unchanged_at_bottom,
        !           864:                                          old_hash, new_hash, draw_cost)))
        !           865:     return 0;
        !           866: 
        !           867:   scrolling_1 (window_size, unchanged_at_top, unchanged_at_bottom,
        !           868:               draw_cost + unchanged_at_top - 1,
        !           869:               old_hash + unchanged_at_top - 1,
        !           870:               new_hash + unchanged_at_top - 1,
        !           871:               free_at_end_vpos - unchanged_at_top);
        !           872: 
        !           873:   return 0;
        !           874: }
        !           875: 
        !           876: update_line (vpos)
        !           877:      int vpos;
        !           878: {
        !           879:   register unsigned char *obody, *nbody, *op1, *op2, *np1;
        !           880:   int tem;
        !           881:   int osp, nsp, begmatch, endmatch, olen, nlen;
        !           882:   int save;
        !           883:   unsigned char *temp;
        !           884: 
        !           885:   /* Check for highlighting change.  */
        !           886:   if (new_screen->highlight[vpos]
        !           887:       != (current_screen->enable[vpos] && current_screen->highlight[vpos]))
        !           888:     {
        !           889:       change_line_highlight (new_screen->highlight[vpos], vpos,
        !           890:                             (current_screen->enable[vpos]
        !           891:                              ? current_screen->used[vpos] : 0));
        !           892:       current_screen->enable[vpos] = 0;
        !           893:     }
        !           894:   else
        !           895:     reassert_line_highlight (new_screen->highlight[vpos], vpos);
        !           896: 
        !           897:   /* ??? */
        !           898:   if (! current_screen->enable[vpos])
        !           899:     {
        !           900:       olen = 0;
        !           901:     }
        !           902:   else
        !           903:     {
        !           904:       obody = current_screen->contents[vpos];
        !           905:       olen = current_screen->used[vpos];
        !           906: 
        !           907:       /* Check for bugs that clobber obody[-1].
        !           908:         Such bugs might well clobber more than that,
        !           909:         so we need to find them, not try to ignore them.  */
        !           910:       if (obody[-1] != 0)
        !           911:        abort ();
        !           912: 
        !           913:       if (! current_screen->highlight[vpos])
        !           914:        {
        !           915:          /* Note obody[-1] is always 0.  */
        !           916:          if (!must_write_spaces)
        !           917:            while (obody[olen - 1] == ' ')
        !           918:              olen--;
        !           919:        }
        !           920:       else
        !           921:        {
        !           922:          /* For an inverse-video line, remember we gave it
        !           923:             spaces all the way to the screen edge
        !           924:             so that the reverse video extends all the way across.  */
        !           925:          while (olen < screen_width - 1)
        !           926:            obody[olen++] = ' ';
        !           927:        }
        !           928:     }
        !           929: 
        !           930:   /* One way or another, this will enable the line being updated.  */
        !           931:   current_screen->enable[vpos] = 1;
        !           932:   current_screen->used[vpos] = new_screen->used[vpos];
        !           933: #if !defined (ALLIANT) || defined (ALLIANT_2800)
        !           934:   current_screen->highlight[vpos] = new_screen->highlight[vpos];
        !           935: #else
        !           936:   {
        !           937:     /* Work around for compiler bug in cc on FX/80 which causes
        !           938:        "dispnew.c", line 896: compiler error: no table entry for op OREG.  */
        !           939:     char tmp;
        !           940:     tmp = new_screen->highlight[vpos];
        !           941:     current_screen->highlight[vpos] = tmp;
        !           942:   }
        !           943: #endif
        !           944: 
        !           945:   if (!new_screen->enable[vpos])
        !           946:     {
        !           947:       nlen = 0;
        !           948:       goto just_erase;
        !           949:     }
        !           950: 
        !           951:   nbody = new_screen->contents[vpos];
        !           952:   nlen = new_screen->used[vpos];
        !           953: 
        !           954:   /* Pretend trailing spaces are not there at all,
        !           955:      unless for one reason or another we must write all spaces.  */
        !           956:   /* We know that the previous character byte contains 0.  */
        !           957:   if (! new_screen->highlight[vpos])
        !           958:     {
        !           959:       if (!must_write_spaces)
        !           960:        while (nlen > 0 && nbody[nlen - 1] == ' ')
        !           961:          nlen--;
        !           962:       if (nlen == 0)
        !           963:        goto just_erase;
        !           964:     }
        !           965:   else
        !           966:     {
        !           967:       /* For an inverse-video line, give it extra trailing spaces
        !           968:         all the way to the screen edge
        !           969:         so that the reverse video extends all the way across.  */
        !           970:       while (nlen < screen_width - 1)
        !           971:        nbody[nlen++] = ' ';
        !           972:     }
        !           973: 
        !           974:   /* If there's no i/d char, quickly do the best we can without it.  */
        !           975:   if (!char_ins_del_ok)
        !           976:     {
        !           977:       int i,j;
        !           978: 
        !           979:       for (i = 0; i < nlen; i++)
        !           980:        {
        !           981:          if (i >= olen || nbody[i] != obody[i])
        !           982:            {
        !           983:              /* We found a non-matching char.  */
        !           984:              move_cursor (vpos, i);
        !           985:              for (j = 1; (i + j < nlen &&
        !           986:                           (i + j >= olen || nbody[i+j] != obody[i+j]));
        !           987:                   j++);
        !           988:              /* Output this run of non-matching chars.  */ 
        !           989:              output_chars (nbody + i, j);
        !           990:              i += j - 1;
        !           991:              /* Now find the next non-match.  */
        !           992:            }
        !           993:        }
        !           994:       /* Clear the rest of the line, or the non-clear part of it.  */
        !           995:       if (olen > nlen)
        !           996:        {
        !           997:          move_cursor (vpos, nlen);
        !           998:          clear_end_of_line (olen);
        !           999:        }
        !          1000: 
        !          1001:       /* Exchange contents between current_screen and new_screen.  */
        !          1002:       temp = new_screen->contents[vpos];
        !          1003:       new_screen->contents[vpos] = current_screen->contents[vpos];
        !          1004:       current_screen->contents[vpos] = temp;
        !          1005:       return;
        !          1006:     }
        !          1007: 
        !          1008:   if (!olen)
        !          1009:     {
        !          1010:       nsp = (must_write_spaces || new_screen->highlight[vpos])
        !          1011:              ? 0 : count_blanks (nbody);
        !          1012:       if (nlen > nsp)
        !          1013:        {
        !          1014:          move_cursor (vpos, nsp);
        !          1015:          output_chars (nbody + nsp, nlen - nsp);
        !          1016:        }
        !          1017: 
        !          1018:       /* Exchange contents between current_screen and new_screen.  */
        !          1019:       temp = new_screen->contents[vpos];
        !          1020:       new_screen->contents[vpos] = current_screen->contents[vpos];
        !          1021:       current_screen->contents[vpos] = temp;
        !          1022:       return;
        !          1023:     }
        !          1024: 
        !          1025:   obody[olen] = 1;
        !          1026:   save = nbody[nlen];
        !          1027:   nbody[nlen] = 0;
        !          1028: 
        !          1029:   /* Compute number of leading blanks in old and new contents.  */
        !          1030:   osp = count_blanks (obody);
        !          1031:   if (!new_screen->highlight[vpos])
        !          1032:     nsp = count_blanks (nbody);
        !          1033:   else
        !          1034:     nsp = 0;
        !          1035: 
        !          1036:   /* Compute number of matching chars starting with first nonblank.  */
        !          1037:   begmatch = count_match (obody + osp, nbody + nsp);
        !          1038: 
        !          1039:   /* Spaces in new match implicit space past the end of old.  */
        !          1040:   /* A bug causing this to be a no-op was fixed in 18.29.  */
        !          1041:   if (!must_write_spaces && osp + begmatch == olen)
        !          1042:     {
        !          1043:       np1 = nbody + nsp;
        !          1044:       while (np1[begmatch] == ' ')
        !          1045:        begmatch++;
        !          1046:     }
        !          1047: 
        !          1048:   /* Avoid doing insert/delete char
        !          1049:      just cause number of leading spaces differs
        !          1050:      when the following text does not match. */
        !          1051:   if (begmatch == 0 && osp != nsp)
        !          1052:     osp = nsp = min (osp, nsp);
        !          1053: 
        !          1054:   /* Find matching characters at end of line */
        !          1055:   op1 = obody + olen;
        !          1056:   np1 = nbody + nlen;
        !          1057:   op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
        !          1058:   while (op1 > op2 && op1[-1] == np1[-1])
        !          1059:     {
        !          1060:       op1--;
        !          1061:       np1--;
        !          1062:     }
        !          1063:   endmatch = obody + olen - op1;
        !          1064: 
        !          1065:   /* Put correct value back in nbody[nlen].
        !          1066:      This is important because direct_output_for_insert
        !          1067:      can write into the line at a later point.  */
        !          1068:   nbody[nlen] = save;
        !          1069:   /* Likewise, make sure that the null after the usable space in obody
        !          1070:      always remains a null.  */
        !          1071:   obody[olen] = 0;
        !          1072: 
        !          1073:   /* tem gets the distance to insert or delete.
        !          1074:      endmatch is how many characters we save by doing so.
        !          1075:      Is it worth it?  */
        !          1076: 
        !          1077:   tem = (nlen - nsp) - (olen - osp);
        !          1078:   if (endmatch && tem && endmatch <= DCICcost[tem])
        !          1079:     endmatch = 0;
        !          1080: 
        !          1081:   /* nsp - osp is the distance to insert or delete.
        !          1082:      begmatch + endmatch is how much we save by doing so.
        !          1083:      Is it worth it?  */
        !          1084: 
        !          1085:   if (begmatch + endmatch > 0 && nsp != osp
        !          1086:       && begmatch + endmatch <= DCICcost[nsp - osp])
        !          1087:     {
        !          1088:       begmatch = 0;
        !          1089:       endmatch = 0;
        !          1090:       osp = nsp = min (osp, nsp);
        !          1091:     }
        !          1092: 
        !          1093:   /* Now go through the line, inserting, writing and deleting as appropriate.  */
        !          1094: 
        !          1095:   if (osp > nsp)
        !          1096:     {
        !          1097:       move_cursor (vpos, nsp);
        !          1098:       delete_chars (osp - nsp);
        !          1099:     }
        !          1100:   else if (nsp > osp)
        !          1101:     {
        !          1102:       /* If going to delete chars later in line
        !          1103:         and insert earlier in the line,
        !          1104:         must delete first to avoid losing data in the insert */
        !          1105:       if (endmatch && nlen < olen + nsp - osp)
        !          1106:        {
        !          1107:          move_cursor (vpos, nlen - endmatch + osp - nsp);
        !          1108:          delete_chars (olen + nsp - osp - nlen);
        !          1109:          olen = nlen - (nsp - osp);
        !          1110:        }
        !          1111:       move_cursor (vpos, osp);
        !          1112:       insert_chars ((char *)0, nsp - osp);
        !          1113:     }
        !          1114:   olen += nsp - osp;
        !          1115: 
        !          1116:   tem = nsp + begmatch + endmatch;
        !          1117:   if (nlen != tem || olen != tem)
        !          1118:     {
        !          1119:       move_cursor (vpos, nsp + begmatch);
        !          1120:       if (!endmatch || nlen == olen)
        !          1121:        {
        !          1122:          /* If new text being written reaches right margin,
        !          1123:             there is no need to do clear-to-eol at the end.
        !          1124:             (and it would not be safe, since cursor is not
        !          1125:             going to be "at the margin" after the text is done) */
        !          1126:          if (nlen == screen_width)
        !          1127:            olen = 0;
        !          1128:          output_chars (nbody + nsp + begmatch, nlen - tem);
        !          1129: #ifdef obsolete
        !          1130: /* the following code loses disastrously if tem == nlen.
        !          1131:    Rather than trying to fix that case, I am trying the simpler
        !          1132:    solution found above.  */
        !          1133:          /* If the text reaches to the right margin,
        !          1134:             it will lose one way or another (depending on AutoWrap)
        !          1135:             to clear to end of line after outputting all the text.
        !          1136:             So pause with one character to go and clear the line then.  */
        !          1137:          if (nlen == screen_width && fast_clear_end_of_line && olen > nlen)
        !          1138:            {
        !          1139:              /* endmatch must be zero, and tem must equal nsp + begmatch */
        !          1140:              output_chars (nbody + tem, nlen - tem - 1);
        !          1141:              clear_end_of_line (olen);
        !          1142:              olen = 0;         /* Don't let it be cleared again later */
        !          1143:              output_chars (nbody + nlen - 1, 1);
        !          1144:            }
        !          1145:          else
        !          1146:            output_chars (nbody + nsp + begmatch, nlen - tem);
        !          1147: #endif
        !          1148:        }
        !          1149:       else if (nlen > olen)
        !          1150:        {
        !          1151:          output_chars (nbody + nsp + begmatch, olen - tem);
        !          1152:          insert_chars (nbody + nsp + begmatch + olen - tem, nlen - olen);
        !          1153:          olen = nlen;
        !          1154:        }
        !          1155:       else if (olen > nlen)
        !          1156:        {
        !          1157:          output_chars (nbody + nsp + begmatch, nlen - tem);
        !          1158:          delete_chars (olen - nlen);
        !          1159:          olen = nlen;
        !          1160:        }
        !          1161:     }
        !          1162: 
        !          1163:  just_erase:
        !          1164:   /* If any unerased characters remain after the new line, erase them.  */
        !          1165:   if (olen > nlen)
        !          1166:     {
        !          1167:       move_cursor (vpos, nlen);
        !          1168:       clear_end_of_line (olen);
        !          1169:     }
        !          1170:   
        !          1171:   /* Exchange contents between current_screen and new_screen.  */
        !          1172:   temp = new_screen->contents[vpos];
        !          1173:   new_screen->contents[vpos] = current_screen->contents[vpos];
        !          1174:   current_screen->contents[vpos] = temp;
        !          1175: }
        !          1176: 
        !          1177: count_blanks (str)
        !          1178:      char *str;
        !          1179: {
        !          1180:   register char *p = str;
        !          1181:   while (*str++ == ' ');
        !          1182:   return str - p - 1;
        !          1183: }
        !          1184: 
        !          1185: count_match (str1, str2)
        !          1186:      char *str1, *str2;
        !          1187: {
        !          1188:   register char *p1 = str1;
        !          1189:   register char *p2 = str2;
        !          1190:   while (*p1++ == *p2++);
        !          1191:   return p1 - str1 - 1;
        !          1192: }
        !          1193: 
        !          1194: DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
        !          1195:   1, 1, "FOpen termscript file: ",
        !          1196:   "Start writing all terminal output to FILE as well as the terminal.\n\
        !          1197: FILE = nil means just close any termscript file currently open.")
        !          1198:   (file)
        !          1199:      Lisp_Object file;
        !          1200: {
        !          1201:   if (termscript != 0) fclose (termscript);
        !          1202:   termscript = 0;
        !          1203: 
        !          1204:   if (! NULL (file))
        !          1205:     {
        !          1206:       file = Fexpand_file_name (file, Qnil);
        !          1207:       termscript = fopen (XSTRING (file)->data, "w");
        !          1208:       if (termscript == 0)
        !          1209:        report_file_error ("Opening termscript", Fcons (file, Qnil));
        !          1210:     }
        !          1211:   return Qnil;
        !          1212: }
        !          1213: 
        !          1214: DEFUN ("set-screen-height", Fset_screen_height, Sset_screen_height, 1, 2, 0,
        !          1215:   "Tell redisplay that the screen has LINES lines.\n\
        !          1216: Optional second arg non-nil means that redisplay should use LINES lines\n\
        !          1217: but that the idea of the actual height of the screen should not be changed.")
        !          1218:   (n, pretend)
        !          1219:      Lisp_Object n, pretend;
        !          1220: {
        !          1221:   CHECK_NUMBER (n, 0);
        !          1222:   change_screen_size (XINT (n), 0, !NULL (pretend), 0, 0);
        !          1223:   return Qnil;
        !          1224: }
        !          1225: 
        !          1226: DEFUN ("set-screen-width", Fset_screen_width, Sset_screen_width, 1, 2, 0,
        !          1227:   "Tell redisplay that the screen has COLS columns.\n\
        !          1228: Optional second arg non-nil means that redisplay should use COLS columns\n\
        !          1229: but that the idea of the actual width of the screen should not be changed.")
        !          1230:   (n, pretend)
        !          1231:      Lisp_Object n, pretend;
        !          1232: {
        !          1233:   CHECK_NUMBER (n, 0);
        !          1234:   change_screen_size (0, XINT (n), !NULL (pretend), 0, 0);
        !          1235:   return Qnil;
        !          1236: }
        !          1237: 
        !          1238: DEFUN ("screen-height", Fscreen_height, Sscreen_height, 0, 0, 0,
        !          1239:   "Return number of lines on screen available for display.")
        !          1240:   ()
        !          1241: {
        !          1242:   return make_number (screen_height);
        !          1243: }
        !          1244: 
        !          1245: DEFUN ("screen-width", Fscreen_width, Sscreen_width, 0, 0, 0,
        !          1246:   "Return number of columns on screen available for display.")
        !          1247:   ()
        !          1248: {
        !          1249:   return make_number (screen_width);
        !          1250: }
        !          1251: 
        !          1252: #ifdef SIGWINCH
        !          1253: window_change_signal ()
        !          1254: {
        !          1255:   int width, height;
        !          1256:   extern int errno;
        !          1257:   int old_errno = errno;
        !          1258: 
        !          1259:   get_screen_size (&width, &height);
        !          1260:   /* Record the new size, but don't reallocate the data structures now.
        !          1261:      Let that be done later outside of the signal handler.  */
        !          1262:   change_screen_size (height, width, 0, 1, 0);
        !          1263:   signal (SIGWINCH, window_change_signal);
        !          1264: 
        !          1265:   errno = old_errno;
        !          1266: }
        !          1267: #endif /* SIGWINCH */
        !          1268: 
        !          1269: /* Do any change in screen size that was requested by a signal.  */
        !          1270: 
        !          1271: do_pending_window_change ()
        !          1272: {
        !          1273:   /* If change_screen_size should have run before, run it now.  */
        !          1274:   while (delayed_size_change)
        !          1275:     {
        !          1276:       int newwidth = delayed_screen_width;
        !          1277:       int newheight = delayed_screen_height;
        !          1278:       delayed_size_change = 0;
        !          1279:       change_screen_size_1 (newheight, newwidth, 0, 0);
        !          1280:     }
        !          1281: }
        !          1282: 
        !          1283: /* Change the screen height and/or width.  Values may be given as zero to
        !          1284:    indicate no change is to take place.
        !          1285: 
        !          1286:    PRETEND is normally 0; 1 means change used-size only but don't
        !          1287:    change the size used for calculations; -1 means don't redisplay.
        !          1288: 
        !          1289:    If DELAYED, don't change the screen size now; just record the new
        !          1290:    size and do the actual change at a more convenient time.  The
        !          1291:    SIGWINCH handler and the X Windows ConfigureNotify code use this,
        !          1292:    because they can both be called at inconvenient times.
        !          1293: 
        !          1294:    FORCE means finish redisplay now regardless of pending input.
        !          1295:    This is effective only is DELAYED is not set.  */
        !          1296: 
        !          1297: change_screen_size (newlength, newwidth, pretend, delayed, force)
        !          1298:      register int newlength, newwidth, pretend, delayed, force;
        !          1299: {
        !          1300:   /* Don't queue a size change if we won't really do anything.  */
        !          1301:   if ((newlength == 0 || newlength == screen_height)
        !          1302:       && (newwidth == 0 || newwidth == screen_width))
        !          1303:     return;
        !          1304:   /* If we can't deal with the change now, queue it for later.  */
        !          1305:   if (delayed)
        !          1306:     {
        !          1307:       delayed_screen_width = newwidth;
        !          1308:       delayed_screen_height = newlength;
        !          1309:       delayed_size_change = 1;
        !          1310:     }
        !          1311:   else
        !          1312:     {
        !          1313:       delayed_size_change = 0;
        !          1314:       change_screen_size_1 (newlength, newwidth, pretend, force);
        !          1315:     }
        !          1316: }
        !          1317: 
        !          1318: change_screen_size_1 (newlength, newwidth, pretend, force)
        !          1319:      register int newlength, newwidth, pretend, force;
        !          1320: {
        !          1321:   if ((newlength == 0 || newlength == screen_height)
        !          1322:       && (newwidth == 0 || newwidth == screen_width))
        !          1323:     return;
        !          1324:   if (newlength && newlength != screen_height)
        !          1325:     {
        !          1326:       set_window_height (XWINDOW (minibuf_window)->prev, newlength - 1, 0);
        !          1327:       XFASTINT (XWINDOW (minibuf_window)->top) = newlength - 1;
        !          1328:       set_window_height (minibuf_window, 1, 0);
        !          1329:       screen_height = newlength;
        !          1330:       if (pretend <= 0)
        !          1331:        ScreenRows = newlength;
        !          1332:       set_terminal_window (0);
        !          1333:     }
        !          1334:   if (newwidth && newwidth != screen_width)
        !          1335:     {
        !          1336:       set_window_width (XWINDOW (minibuf_window)->prev, newwidth, 0);
        !          1337:       set_window_width (minibuf_window, newwidth, 0);
        !          1338:       screen_width = newwidth;
        !          1339:       if (pretend <= 0)
        !          1340:        ScreenCols = newwidth;
        !          1341:     }
        !          1342:   remake_screen_structures ();
        !          1343:   screen_garbaged = 1;
        !          1344:   calculate_costs ();
        !          1345:   force_redisplay += force;
        !          1346:   if (pretend >= 0)
        !          1347:     redisplay_preserve_echo_area ();
        !          1348:   force_redisplay -= force;
        !          1349: }
        !          1350: 
        !          1351: DEFUN ("baud-rate", Fbaud_rate, Sbaud_rate, 0, 0, 0,
        !          1352:   "Return the output baud rate of the terminal.")
        !          1353:   ()
        !          1354: {
        !          1355:   Lisp_Object temp;
        !          1356:   XSET (temp, Lisp_Int, baud_rate);
        !          1357:   return temp;
        !          1358: }
        !          1359: 
        !          1360: DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
        !          1361:   Ssend_string_to_terminal, 1, 1, 0,
        !          1362:   "Send STRING to the terminal without alteration.\n\
        !          1363: Control characters in STRING will have terminal-dependent effects.")
        !          1364:   (str)
        !          1365:      Lisp_Object str;
        !          1366: {
        !          1367:   CHECK_STRING (str, 0);
        !          1368:   fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, stdout);
        !          1369:   fflush (stdout);
        !          1370:   if (termscript)
        !          1371:     {
        !          1372:       fwrite (XSTRING (str)->data, 1, XSTRING (str)->size, termscript);
        !          1373:       fflush (termscript);
        !          1374:     }
        !          1375:   return Qnil;
        !          1376: }
        !          1377: 
        !          1378: DEFUN ("ding", Fding, Sding, 0, 1, 0,
        !          1379:   "Beep, or flash the screen.\n\
        !          1380: Terminates any keyboard macro currently executing unless an argument\n\
        !          1381: is given.")
        !          1382:   (arg)
        !          1383:   Lisp_Object arg;
        !          1384: {
        !          1385:   if (!NULL (arg))
        !          1386:     {
        !          1387:       if (noninteractive)
        !          1388:        putchar (07);
        !          1389:       else
        !          1390:        ring_bell ();
        !          1391:       fflush (stdout);
        !          1392:     }
        !          1393:   else
        !          1394:     bell ();
        !          1395:   return Qnil;
        !          1396: }
        !          1397: 
        !          1398: bell ()
        !          1399: {
        !          1400:   if (noninteractive)
        !          1401:     putchar (07);
        !          1402:   else if (!FROM_KBD)  /* Stop executing a keyboard macro. */
        !          1403:     error ("Keyboard macro terminated by a command ringing the bell");
        !          1404:   else
        !          1405:     ring_bell ();
        !          1406:   fflush (stdout);
        !          1407: }
        !          1408: 
        !          1409: DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 1, 0,
        !          1410:   "Pause, without updating display, for ARG seconds.")
        !          1411:   (n)
        !          1412:      Lisp_Object n;
        !          1413: {
        !          1414:   register int t;
        !          1415: #ifndef subprocesses
        !          1416: #ifdef HAVE_TIMEVAL
        !          1417:   struct timeval timeout, end_time, garbage1;
        !          1418: #endif /* HAVE_TIMEVAL */
        !          1419: #endif /* no subprocesses */
        !          1420: 
        !          1421:   CHECK_NUMBER (n, 0);
        !          1422:   t = XINT (n);
        !          1423:   if (t <= 0)
        !          1424:     return Qnil;
        !          1425: 
        !          1426: #ifdef subprocesses
        !          1427:   wait_reading_process_input (t, 0, 0);
        !          1428: #else /* No subprocesses */
        !          1429:   immediate_quit = 1;
        !          1430:   QUIT;
        !          1431: 
        !          1432: #ifdef VMS
        !          1433:   sys_sleep (t);
        !          1434: #else /* not VMS */
        !          1435: /* The reason this is done this way 
        !          1436:     (rather than defined (H_S) && defined (H_T))
        !          1437:    is because the VMS preprocessor doesn't grok `defined' */
        !          1438: #ifdef HAVE_SELECT
        !          1439: #ifdef HAVE_TIMEVAL
        !          1440:   gettimeofday (&end_time, &garbage1);
        !          1441:   end_time.tv_sec += t;
        !          1442: 
        !          1443:   while (1)
        !          1444:     {
        !          1445:       gettimeofday (&timeout, &garbage1);
        !          1446: 
        !          1447:       /* In effect, timeout = end_time - timeout.
        !          1448:         Break if result would be negative.  */
        !          1449:       if (timeval_subtract (&timeout, end_time, timeout))
        !          1450:        break;
        !          1451: 
        !          1452:       if (!select (1, 0, 0, 0, &timeout))
        !          1453:        break;
        !          1454:     }
        !          1455: #else /* not HAVE_TIMEVAL */
        !          1456:   /* Is it safe to quit out of `sleep'?  I'm afraid to trust it.  */
        !          1457:   sleep (t);
        !          1458: #endif /* HAVE_TIMEVAL */
        !          1459: #else /* not HAVE_SELECT */
        !          1460:   sleep (t);
        !          1461: #endif /* HAVE_SELECT */
        !          1462: #endif /* not VMS */
        !          1463:   
        !          1464:   immediate_quit = 0;
        !          1465: #endif /* no subprocesses */
        !          1466:   return Qnil;
        !          1467: }
        !          1468: 
        !          1469: #ifdef HAVE_TIMEVAL
        !          1470: 
        !          1471: /* Subtract the `struct timeval' values X and Y,
        !          1472:    storing the result in RESULT.
        !          1473:    Return 1 if the difference is negative, otherwise 0.  */
        !          1474: 
        !          1475: int
        !          1476: timeval_subtract (result, x, y)
        !          1477:      struct timeval *result, x, y;
        !          1478: {
        !          1479:   /* Perform the carry for the later subtraction by updating y.
        !          1480:      This is safer because on some systems
        !          1481:      the tv_sec member is unsigned.  */
        !          1482:   if (x.tv_usec < y.tv_usec)
        !          1483:     {
        !          1484:       int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
        !          1485:       y.tv_usec -= 1000000 * nsec;
        !          1486:       y.tv_sec += nsec;
        !          1487:     }
        !          1488:   if (x.tv_usec - y.tv_usec > 1000000)
        !          1489:     {
        !          1490:       int nsec = (y.tv_usec - x.tv_usec) / 1000000;
        !          1491:       y.tv_usec += 1000000 * nsec;
        !          1492:       y.tv_sec -= nsec;
        !          1493:     }
        !          1494: 
        !          1495:   /* Compute the time remaining to wait.  tv_usec is certainly positive.  */
        !          1496:   result->tv_sec = x.tv_sec - y.tv_sec;
        !          1497:   result->tv_usec = x.tv_usec - y.tv_usec;
        !          1498: 
        !          1499:   /* Return indication of whether the result should be considered negative.  */
        !          1500:   return x.tv_sec < y.tv_sec;
        !          1501: }
        !          1502: #endif /* HAVE_TIMEVAL */
        !          1503: 
        !          1504: DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 2, 0,
        !          1505:   "Perform redisplay, then wait for ARG seconds or until input is available.\n\
        !          1506: Optional second arg non-nil means don't redisplay.\n\
        !          1507: Redisplay is preempted as always if input arrives, and does not happen\n\
        !          1508: if input is available before it starts.\n\
        !          1509: Value is t if waited the full time with no input arriving.")
        !          1510:   (n, nodisp)
        !          1511:      Lisp_Object n, nodisp;
        !          1512: {
        !          1513: #ifndef subprocesses
        !          1514: #ifdef HAVE_TIMEVAL
        !          1515:   struct timeval timeout;
        !          1516: #else
        !          1517:   int timeout_sec;
        !          1518: #endif
        !          1519:   int waitchannels;
        !          1520: #endif /* no subprocesses */
        !          1521: 
        !          1522:   CHECK_NUMBER (n, 0);
        !          1523: 
        !          1524:   if (detect_input_pending ())
        !          1525:     return Qnil;
        !          1526: 
        !          1527:   if (EQ (nodisp, Qnil))
        !          1528:     redisplay_preserve_echo_area ();
        !          1529:   if (XINT (n) > 0)
        !          1530:     {
        !          1531: #ifdef subprocesses
        !          1532: #ifdef SIGIO
        !          1533:       gobble_input ();
        !          1534: #endif                         /* SIGIO */
        !          1535:       wait_reading_process_input (XINT (n), 1, 1);
        !          1536: #else /* not subprocesses */
        !          1537:       immediate_quit = 1;
        !          1538:       QUIT;
        !          1539: 
        !          1540:       waitchannels = 1;
        !          1541: #ifdef VMS
        !          1542:       input_wait_timeout (XINT (n));
        !          1543: #else /* not VMS */
        !          1544: #ifndef HAVE_TIMEVAL
        !          1545:       timeout_sec = XINT (n);
        !          1546:       select (1, &waitchannels, 0, 0, &timeout_sec);
        !          1547: #else /* HAVE_TIMEVAL */
        !          1548:       timeout.tv_sec = XINT (n);  
        !          1549:       timeout.tv_usec = 0;
        !          1550:       select (1, &waitchannels, 0, 0, &timeout);
        !          1551: #endif /* HAVE_TIMEVAL */
        !          1552: #endif /* not VMS */
        !          1553: 
        !          1554:       immediate_quit = 0;
        !          1555: #endif /* not subprocesses */
        !          1556:     }
        !          1557:   return detect_input_pending () ? Qnil : Qt;
        !          1558: }
        !          1559: 
        !          1560: char *terminal_type;
        !          1561: 
        !          1562: /* Initialization done when Emacs fork is started, before doing stty. */
        !          1563: /* Determine terminal type and set terminal_driver */
        !          1564: /* Then invoke its decoding routine to set up variables
        !          1565:   in the terminal package */
        !          1566: 
        !          1567: init_display ()
        !          1568: {
        !          1569: #ifdef HAVE_X_WINDOWS
        !          1570:   extern Lisp_Object Vxterm;
        !          1571:   Vxterm = Qnil;
        !          1572: #endif
        !          1573: 
        !          1574:   Vwindow_system = Qnil;
        !          1575:   meta_key = 0;
        !          1576:   inverse_video = 0;
        !          1577:   cursor_in_echo_area = 0;
        !          1578:   terminal_type = (char *) 0;
        !          1579: 
        !          1580:   if (!inhibit_window_system)
        !          1581:     {
        !          1582: #ifdef HAVE_X_WINDOWS
        !          1583:       extern char *alternate_display;
        !          1584:       char *disp = (char *) egetenv ("DISPLAY");
        !          1585: 
        !          1586:       /* Note KSH likes to provide an empty string as an envvar value.  */
        !          1587:       if (alternate_display || (disp && *disp))
        !          1588:        {
        !          1589:          x_term_init ();
        !          1590:          Vxterm = Qt;
        !          1591:          Vwindow_system = intern ("x");
        !          1592: #ifdef X11
        !          1593:          Vwindow_system_version = make_number (11);
        !          1594: #else
        !          1595:          Vwindow_system_version = make_number (10);
        !          1596: #endif
        !          1597:          goto term_init_done;
        !          1598:        }
        !          1599: #endif /* HAVE_X_WINDOWS */
        !          1600:       ;
        !          1601:     }
        !          1602:   /* Record we aren't using a window system.  */
        !          1603:   inhibit_window_system = 1;
        !          1604: 
        !          1605:   /* Look at the TERM variable */
        !          1606:   terminal_type = (char *) getenv ("TERM");
        !          1607:   if (!terminal_type)
        !          1608:     {
        !          1609: #ifdef VMS
        !          1610:       fprintf (stderr, "Please specify your terminal type.\n\
        !          1611: For types defined in VMS, use  set term /device=TYPE.\n\
        !          1612: For types not defined in VMS, use  define emacs_term \"TYPE\".\n\
        !          1613: \(The quotation marks are necessary since terminal types are lower case.)\n");
        !          1614: #else
        !          1615:       fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
        !          1616: #endif
        !          1617:       exit (1);
        !          1618:     }
        !          1619:   term_init (terminal_type);
        !          1620: 
        !          1621:  term_init_done:
        !          1622:   remake_screen_structures ();
        !          1623:   calculate_costs ();
        !          1624: 
        !          1625: #ifdef SIGWINCH
        !          1626: #ifndef CANNOT_DUMP
        !          1627:   if (initialized)
        !          1628: #endif /* CANNOT_DUMP */
        !          1629:     if (inhibit_window_system)
        !          1630:       signal (SIGWINCH, window_change_signal);
        !          1631: #endif /* SIGWINCH */
        !          1632: }
        !          1633: 
        !          1634: syms_of_display ()
        !          1635: {
        !          1636:   defsubr (&Sopen_termscript);
        !          1637:   defsubr (&Sding);
        !          1638:   defsubr (&Ssit_for);
        !          1639:   defsubr (&Sscreen_height);
        !          1640:   defsubr (&Sscreen_width);
        !          1641:   defsubr (&Sset_screen_height);
        !          1642:   defsubr (&Sset_screen_width);
        !          1643:   defsubr (&Ssleep_for);
        !          1644:   defsubr (&Sbaud_rate);
        !          1645:   defsubr (&Ssend_string_to_terminal);
        !          1646: 
        !          1647:   DEFVAR_BOOL ("inverse-video", &inverse_video,
        !          1648:     "*Non-nil means use inverse-video.");
        !          1649:   DEFVAR_BOOL ("visible-bell", &visible_bell,
        !          1650:     "*Non-nil means try to flash the screen to represent a bell.\n\
        !          1651: Note: for X windows, you must use x-set-bell instead.");
        !          1652:   DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
        !          1653:     "*Non-nil means no need to redraw entire screen after suspending.\n\
        !          1654: It is up to you to set this variable to inform Emacs.");
        !          1655:   DEFVAR_LISP ("window-system", &Vwindow_system,
        !          1656:     "A symbol naming the window-system under which Emacs is running,\n\
        !          1657: \(such as `x'), or nil if emacs is running on an ordinary terminal.");
        !          1658:   DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
        !          1659:     "Version number of the window system Emacs is running under.");
        !          1660:   DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
        !          1661:     "Non-nil means put cursor in minibuffer after any message displayed there.");
        !          1662: 
        !          1663:   /* Initialize `window-system', unless init_display already decided it.  */
        !          1664: #ifdef CANNOT_DUMP
        !          1665:   if (noninteractive)
        !          1666: #endif
        !          1667:     {
        !          1668:       Vwindow_system_version = Qnil;
        !          1669:       Vwindow_system = Qnil;
        !          1670:     }
        !          1671: }

unix.superglobalmegacorp.com

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