Annotation of 43BSD/contrib/emacs/src/dispnew.c, revision 1.1

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

unix.superglobalmegacorp.com

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