Annotation of 43BSDReno/contrib/emacs-18.55/src/dispnew.c, revision 1.1

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

unix.superglobalmegacorp.com

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