Annotation of 43BSDReno/contrib/emacs-18.55/src/dispnew.c, revision 1.1.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.