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

1.1     ! root        1: /* terminal control module for terminals described by TERMCAP
        !             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 <stdio.h>
        !            23: #include <ctype.h>
        !            24: #include "config.h"
        !            25: #include "termhooks.h"
        !            26: #include "termchar.h"
        !            27: #include "termopts.h"
        !            28: #include "cm.h"
        !            29: 
        !            30: #define max(a, b) ((a) > (b) ? (a) : (b))
        !            31: #define min(a, b) ((a) < (b) ? (a) : (b))
        !            32: 
        !            33: #define OUTPUT(a) tputs (a, screen_height - curY, cmputc)
        !            34: #define OUTPUT1(a) tputs (a, 1, cmputc)
        !            35: #define OUTPUTL(a, lines) tputs (a, lines, cmputc)
        !            36: #define OUTPUT_IF(a) { if (a) tputs (a, screen_height - curY, cmputc); }
        !            37: #define OUTPUT1_IF(a) { if (a) tputs (a, 1, cmputc); }
        !            38: 
        !            39: /* Terminal charateristics that higher levels want to look at.
        !            40:    These are all extern'd in termchar.h */
        !            41: 
        !            42: int screen_width;              /* Number of usable columns */
        !            43: int screen_height;             /* Number of lines */
        !            44: int must_write_spaces;         /* Nonzero means spaces in the text
        !            45:                                   must actually be output; can't just skip
        !            46:                                   over some columns to leave them blank.  */
        !            47: int min_padding_speed;         /* Speed below which no padding necessary */
        !            48: 
        !            49: int line_ins_del_ok;           /* Terminal can insert and delete lines */
        !            50: int char_ins_del_ok;           /* Terminal can insert and delete chars */
        !            51: int scroll_region_ok;          /* Terminal supports setting the scroll window */
        !            52: int memory_below_screen;       /* Terminal remembers lines scrolled off bottom */
        !            53: int fast_clear_end_of_line;    /* Terminal has a `ce' string */
        !            54: 
        !            55: int dont_calculate_costs;      /* Nonzero means don't bother computing */
        !            56:                                /* various cost tables; we won't use them.  */
        !            57: 
        !            58: /* DCICcost[n] is cost of inserting N characters.
        !            59:    DCICcost[-n] is cost of deleting N characters. */
        !            60: 
        !            61: #define DCICcost (&DC_ICcost[MScreenWidth])
        !            62: int DC_ICcost[1 + 2 * MScreenWidth];
        !            63: 
        !            64: 
        !            65: /* Hook functions that you can set to snap out the functions in this file.
        !            66:    These are all extern'd in termhooks.h  */
        !            67: 
        !            68: int (*topos_hook) ();
        !            69: int (*raw_topos_hook) ();
        !            70: 
        !            71: int (*clear_to_end_hook) ();
        !            72: int (*clear_screen_hook) ();
        !            73: int (*clear_end_of_line_hook) ();
        !            74: 
        !            75: int (*ins_del_lines_hook) ();
        !            76: 
        !            77: int (*change_line_highlight_hook) ();
        !            78: int (*reassert_line_highlight_hook) ();
        !            79: 
        !            80: int (*insert_chars_hook) ();
        !            81: int (*write_chars_hook) ();
        !            82: int (*delete_chars_hook) ();
        !            83: 
        !            84: int (*ring_bell_hook) ();
        !            85: 
        !            86: int (*reset_terminal_modes_hook) ();
        !            87: int (*set_terminal_modes_hook) ();
        !            88: int (*update_begin_hook) ();
        !            89: int (*update_end_hook) ();
        !            90: int (*set_terminal_window_hook) ();
        !            91: 
        !            92: int (*read_socket_hook) ();
        !            93: int (*fix_screen_hook) ();
        !            94: 
        !            95: /* Strings, numbers and flags taken from the termcap entry.  */
        !            96: 
        !            97: char *TS_ins_line;             /* termcap "al" */
        !            98: char *TS_ins_multi_lines;      /* "AL" (one parameter, # lines to insert) */
        !            99: char *TS_bell;                 /* "bl" */
        !           100: char *TS_clr_to_bottom;                /* "cd" */
        !           101: char *TS_clr_line;             /* "ce", clear to end of line */
        !           102: char *TS_clr_screen;           /* "cl" */
        !           103: char *TS_set_scroll_region;    /* "cs" (2 params, first line and last line) */
        !           104: char *TS_set_scroll_region_1;   /* "cS" (4 params: total lines,
        !           105:                                   lines above scroll region, lines below it,
        !           106:                                   total lines again) */
        !           107: char *TS_del_char;             /* "dc" */
        !           108: char *TS_del_multi_chars;      /* "DC" (one parameter, # chars to delete) */
        !           109: char *TS_del_line;             /* "dl" */
        !           110: char *TS_del_multi_lines;      /* "DL" (one parameter, # lines to delete) */
        !           111: char *TS_delete_mode;          /* "dm", enter character-delete mode */
        !           112: char *TS_end_delete_mode;      /* "ed", leave character-delete mode */
        !           113: char *TS_end_insert_mode;      /* "ei", leave character-insert mode */
        !           114: char *TS_ins_char;             /* "ic" */
        !           115: char *TS_ins_multi_chars;      /* "IC" (one parameter, # chars to insert) */
        !           116: char *TS_insert_mode;          /* "im", enter character-insert mode */
        !           117: char *TS_pad_inserted_char;    /* "ip".  Just padding, no commands.  */
        !           118: char *TS_end_keypad_mode;      /* "ke" */
        !           119: char *TS_keypad_mode;          /* "ks" */
        !           120: char *TS_pad_char;             /* "pc", char to use as padding */
        !           121: char *TS_repeat;               /* "rp" (2 params, # times to repeat
        !           122:                                   and character to be repeated) */
        !           123: char *TS_end_standout_mode;    /* "se" */
        !           124: char *TS_fwd_scroll;           /* "sf" */
        !           125: char *TS_standout_mode;                /* "so" */
        !           126: char *TS_rev_scroll;           /* "sr" */
        !           127: char *TS_end_termcap_modes;    /* "te" */
        !           128: char *TS_termcap_modes;                /* "ti" */
        !           129: char *TS_visible_bell;         /* "vb" */
        !           130: char *TS_end_visual_mode;      /* "ve" */
        !           131: char *TS_visual_mode;          /* "vi" */
        !           132: char *TS_set_window;           /* "wi" (4 params, start and end of window,
        !           133:                                   each as vpos and hpos) */
        !           134: 
        !           135: int TF_hazeltine;              /* termcap hz flag. */
        !           136: int TF_insmode_motion;         /* termcap mi flag: can move while in insert mode. */
        !           137: int TF_standout_motion;                /* termcap mi flag: can move while in standout mode. */
        !           138: int TF_underscore;             /* termcap ul flag: _ underlines if overstruck on
        !           139:                                   nonblank position.  Must clear before writing _.  */
        !           140: int TF_teleray;                        /* termcap xt flag: many weird consequences.  For t1061. */
        !           141: 
        !           142: int TN_standout_width;         /* termcap sg number: width occupied by standout markers */
        !           143: 
        !           144: static int RPov;               /* # chars to start a TS_repeat */
        !           145: 
        !           146: static int delete_in_insert_mode;              /* delete mode == insert mode */
        !           147: 
        !           148: static int se_is_so;           /* 1 if same string both enters and leaves standout mode */
        !           149: 
        !           150: /* internal state */
        !           151: 
        !           152: /* Number of chars of space used for standout marker at beginning of line,
        !           153:    or'd with 0100.  Zero if no standout marker at all.  */
        !           154: /* used iff TN_standout_width >= 0. */
        !           155: char chars_wasted[MScreenLength];
        !           156: 
        !           157: /* nonzero means supposed to write text in standout mode.  */
        !           158: int standout_requested;
        !           159: 
        !           160: int insert_mode;                       /* Nonzero when in insert mode.  */
        !           161: int standout_mode;                     /* Nonzero when in standout mode.  */
        !           162: 
        !           163: /* Size of window specified by higher levels.
        !           164:    This is the number of lines, starting from top of screen,
        !           165:    to participate in ins/del line operations.
        !           166:    Effectively it excludes the bottom
        !           167:       screen_height - specified_window_size
        !           168:    lines from those operations.  */
        !           169: 
        !           170: int specified_window;
        !           171: 
        !           172: ring_bell ()
        !           173: {
        !           174:   if (ring_bell_hook)
        !           175:     {
        !           176:       (*ring_bell_hook) ();
        !           177:       return;
        !           178:     }
        !           179:   OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell);
        !           180: }
        !           181: 
        !           182: set_terminal_modes ()
        !           183: {
        !           184:   if (set_terminal_modes_hook)
        !           185:     {
        !           186:       (*set_terminal_modes_hook) ();
        !           187:       return;
        !           188:     }
        !           189:   OUTPUT_IF (TS_termcap_modes);
        !           190:   OUTPUT_IF (TS_visual_mode);
        !           191:   OUTPUT_IF (TS_keypad_mode);
        !           192:   losecursor ();
        !           193: }
        !           194: 
        !           195: reset_terminal_modes ()
        !           196: {
        !           197:   if (reset_terminal_modes_hook)
        !           198:     {
        !           199:       (*reset_terminal_modes_hook) ();
        !           200:       return;
        !           201:     }
        !           202:   if (TN_standout_width < 0)
        !           203:     turn_off_highlight ();
        !           204:   turn_off_insert ();
        !           205:   OUTPUT_IF (TS_end_keypad_mode);
        !           206:   OUTPUT_IF (TS_end_visual_mode);
        !           207:   OUTPUT_IF (TS_end_termcap_modes);
        !           208: }
        !           209: 
        !           210: update_begin ()
        !           211: {
        !           212:   if (update_begin_hook)
        !           213:     (*update_begin_hook) ();
        !           214: }
        !           215: 
        !           216: update_end ()
        !           217: {
        !           218:   if (update_end_hook)
        !           219:     {
        !           220:       (*update_end_hook) ();
        !           221:       return;
        !           222:     }
        !           223:   turn_off_insert ();
        !           224:   background_highlight ();
        !           225:   standout_requested = 0;
        !           226: }
        !           227: 
        !           228: set_terminal_window (size)
        !           229:      int size;
        !           230: {
        !           231:   if (set_terminal_window_hook)
        !           232:     {
        !           233:       (*set_terminal_window_hook) (size);
        !           234:       return;
        !           235:     }
        !           236:   specified_window = size ? size : screen_height;
        !           237:   if (!scroll_region_ok)
        !           238:     return;
        !           239:   set_scroll_region (0, specified_window);
        !           240: }
        !           241: 
        !           242: set_scroll_region (start, stop)
        !           243:      int start, stop;
        !           244: {
        !           245:   char *buf;
        !           246:   if (TS_set_scroll_region)
        !           247:     {
        !           248:       buf = (char *) alloca (strlen (TS_set_scroll_region) + 10);
        !           249:       tparam (TS_set_scroll_region, buf, start, stop - 1);
        !           250:     }
        !           251:   else if (TS_set_scroll_region_1)
        !           252:     {
        !           253:       buf = (char *) alloca (strlen (TS_set_scroll_region_1) + 20);
        !           254:       tparam (TS_set_scroll_region_1, buf,
        !           255:              screen_height, start, screen_height - stop, screen_height);
        !           256:     }
        !           257:   else
        !           258:     {
        !           259:       buf = (char *) alloca (strlen (TS_set_window) + 20);
        !           260:       tparam (TS_set_window, buf, start, 0, stop, screen_width);
        !           261:     }
        !           262:   OUTPUT (buf);
        !           263:   losecursor ();
        !           264: }
        !           265: 
        !           266: turn_on_insert ()
        !           267: {
        !           268:   if (!insert_mode)
        !           269:     OUTPUT (TS_insert_mode);
        !           270:   insert_mode = 1;
        !           271: }
        !           272: 
        !           273: turn_off_insert ()
        !           274: {
        !           275:   if (insert_mode)
        !           276:     OUTPUT (TS_end_insert_mode);
        !           277:   insert_mode = 0;
        !           278: }
        !           279: 
        !           280: /* Handle highlighting when TN_standout_width (termcap sg) is not specified.
        !           281:    In these terminals, output is affected by the value of standout
        !           282:    mode when the output is written.
        !           283: 
        !           284:    These functions are called on all terminals, but do nothing
        !           285:    on terminals whose standout mode does not work that way.  */
        !           286: 
        !           287: turn_off_highlight ()
        !           288: {
        !           289:   if (TN_standout_width < 0)
        !           290:     {
        !           291:       if (standout_mode)
        !           292:        OUTPUT_IF (TS_end_standout_mode);
        !           293:       standout_mode = 0;
        !           294:     }
        !           295: }
        !           296: 
        !           297: turn_on_highlight ()
        !           298: {
        !           299:   if (TN_standout_width < 0)
        !           300:     {
        !           301:       if (!standout_mode)
        !           302:        OUTPUT_IF (TS_standout_mode);
        !           303:       standout_mode = 1;
        !           304:     }
        !           305: }
        !           306: 
        !           307: /* Set standout mode to the state it should be in for
        !           308:    empty space inside windows.  What this is,
        !           309:    depends on the user option inverse-video.  */
        !           310: 
        !           311: background_highlight ()
        !           312: {
        !           313:   if (TN_standout_width >= 0)
        !           314:     return;
        !           315:   if (inverse_video)
        !           316:     turn_on_highlight ();
        !           317:   else
        !           318:     turn_off_highlight ();
        !           319: }
        !           320: 
        !           321: /* Set standout mode to the mode specified for the text to be output.  */
        !           322: 
        !           323: static
        !           324: highlight_if_desired ()
        !           325: {
        !           326:   if (TN_standout_width >= 0)
        !           327:     return;
        !           328:   if (!inverse_video == !standout_requested)
        !           329:     turn_off_highlight ();
        !           330:   else
        !           331:     turn_on_highlight ();
        !           332: }
        !           333: 
        !           334: /* Handle standout mode for terminals in which TN_standout_width >= 0.
        !           335:    On these terminals, standout is controlled by markers that
        !           336:    live inside the screen memory.  TN_standout_width is the width
        !           337:    that the marker occupies in memory.  Standout runs from the marker
        !           338:    to the end of the line on some terminals, or to the next
        !           339:    turn-off-standout marker (TS_end_standout_mode) string
        !           340:    on other terminals.  */
        !           341: 
        !           342: /* Write a standout marker or end-standout marker at the front of the line
        !           343:    at vertical position vpos.  */
        !           344: 
        !           345: write_standout_marker (flag, vpos)
        !           346:      int flag, vpos;
        !           347: {
        !           348:   if (flag || (TS_end_standout_mode && !TF_teleray && !se_is_so))
        !           349:     {
        !           350:       cmgoto (vpos, 0);
        !           351:       cmplus (TN_standout_width);
        !           352:       OUTPUT (flag ? TS_standout_mode : TS_end_standout_mode);
        !           353:       chars_wasted[curY] = TN_standout_width | 0100;
        !           354:     }
        !           355: }
        !           356: 
        !           357: /* External interface to control of standout mode.
        !           358:    Call this when about to modify line at position VPOS
        !           359:    and not change whether it is highlighted.  */
        !           360: 
        !           361: reassert_line_highlight (highlight, vpos)
        !           362:      int highlight;
        !           363:      int vpos;
        !           364: {
        !           365:   if (reassert_line_highlight_hook)
        !           366:     {
        !           367:       (*reassert_line_highlight_hook) (highlight, vpos);
        !           368:       return;
        !           369:     }
        !           370:   if (TN_standout_width < 0)
        !           371:     /* Handle terminals where standout takes affect at output time */
        !           372:     standout_requested = highlight;
        !           373:   else if (chars_wasted[vpos] == 0)
        !           374:     /* For terminals with standout markers, write one on this line
        !           375:        if there isn't one already.  */
        !           376:     write_standout_marker (highlight, vpos);
        !           377: }
        !           378: 
        !           379: /* Call this when about to modify line at position VPOS
        !           380:    and change whether it is highlighted.  */
        !           381: 
        !           382: change_line_highlight (new_highlight, vpos, first_unused_hpos)
        !           383:      int new_highlight, vpos, first_unused_hpos;
        !           384: {
        !           385:   standout_requested = new_highlight;
        !           386:   if (change_line_highlight_hook)
        !           387:     {
        !           388:       (*change_line_highlight_hook) (new_highlight, vpos, first_unused_hpos);
        !           389:       return;
        !           390:     }
        !           391: 
        !           392:   topos (vpos, 0);
        !           393: 
        !           394:   if (TN_standout_width < 0)
        !           395:     background_highlight ();
        !           396:   /* If line starts with a marker, delete the marker */
        !           397:   else if (TS_clr_line && chars_wasted[curY])
        !           398:     {
        !           399:       turn_off_insert ();
        !           400:       /* On Teleray, make sure to erase the SO marker.  */
        !           401:       if (TF_teleray)
        !           402:        {
        !           403:          cmgoto (curY - 1, screen_width - 4);
        !           404:          OUTPUT ("\033S");
        !           405:          curY++;               /* ESC S moves to next line where the TS_standout_mode was */
        !           406:          curX = 0;
        !           407:        }
        !           408:       else
        !           409:        cmgoto (curY, 0);       /* reposition to kill standout marker */
        !           410:     }
        !           411:   clear_end_of_line_raw (first_unused_hpos);
        !           412:   reassert_line_highlight (new_highlight, curY);
        !           413: }
        !           414: 
        !           415: /* Move to absolute position, specified origin 0 */
        !           416: 
        !           417: topos (row, col)
        !           418: {
        !           419:   col += chars_wasted[row] & 077;
        !           420:   if (topos_hook)
        !           421:     {
        !           422:       (*topos_hook) (row, col);
        !           423:       return;
        !           424:     }
        !           425:   if (curY == row && curX == col)
        !           426:     return;
        !           427:   if (!TF_standout_motion)
        !           428:     background_highlight ();
        !           429:   if (!TF_insmode_motion)
        !           430:     turn_off_insert ();
        !           431:   cmgoto (row, col);
        !           432: }
        !           433: 
        !           434: /* Similar but don't take any account of the wasted characters.  */
        !           435: 
        !           436: raw_topos (row, col)
        !           437: {
        !           438:   if (raw_topos_hook)
        !           439:     {
        !           440:       (*raw_topos_hook) (row, col);
        !           441:       return;
        !           442:     }
        !           443:   if (curY == row && curX == col)
        !           444:     return;
        !           445:   if (!TF_standout_motion)
        !           446:     background_highlight ();
        !           447:   if (!TF_insmode_motion)
        !           448:     turn_off_insert ();
        !           449:   cmgoto (row, col);
        !           450: }
        !           451: 
        !           452: /* Erase operations */
        !           453: 
        !           454: /* clear from cursor to end of screen */
        !           455: clear_to_end ()
        !           456: {
        !           457:   register int i;
        !           458: 
        !           459:   if (clear_to_end_hook)
        !           460:     {
        !           461:       (*clear_to_end_hook) ();
        !           462:       return;
        !           463:     }
        !           464:   if (TS_clr_to_bottom)
        !           465:     {
        !           466:       background_highlight ();
        !           467:       OUTPUT (TS_clr_to_bottom);
        !           468:       bzero (chars_wasted + curY, screen_height - curY);
        !           469:     }
        !           470:   else
        !           471:     {
        !           472:       for (i = curY; i < screen_height; i++)
        !           473:        {
        !           474:          topos (i, 0);
        !           475:          clear_end_of_line_raw (screen_width);
        !           476:        }
        !           477:     }
        !           478: }
        !           479: 
        !           480: /* Clear entire screen */
        !           481: 
        !           482: clear_screen ()
        !           483: {
        !           484:   if (clear_screen_hook)
        !           485:     {
        !           486:       (*clear_screen_hook) ();
        !           487:       return;
        !           488:     }
        !           489:   if (TS_clr_screen)
        !           490:     {
        !           491:       background_highlight ();
        !           492:       OUTPUT (TS_clr_screen);
        !           493:       bzero (chars_wasted, screen_height);
        !           494:       cmat (0, 0);
        !           495:     }
        !           496:   else
        !           497:     {
        !           498:       topos (0, 0);
        !           499:       clear_to_end ();
        !           500:     }
        !           501: }
        !           502: 
        !           503: /* Clear to end of line, but do not clear any standout marker.
        !           504:    Assumes that the cursor is positioned at a character of real text,
        !           505:    which implies it cannot be before a standout marker
        !           506:    unless the marker has zero width.
        !           507: 
        !           508:    Note that the cursor may be moved.  */
        !           509: 
        !           510: clear_end_of_line (first_unused_hpos)
        !           511:      int first_unused_hpos;
        !           512: {
        !           513:   if (TN_standout_width == 0 && curX == 0 && chars_wasted[curY] != 0)
        !           514:     write_chars (" ", 1);
        !           515:   clear_end_of_line_raw (first_unused_hpos);
        !           516: }
        !           517: 
        !           518: /* Clear from cursor to end of line.
        !           519:    Assume that the line is already clear starting at column first_unused_hpos.
        !           520:    If the cursor is at a standout marker, erase the marker.
        !           521: 
        !           522:    Note that the cursor may be moved, on terminals lacking a `ce' string.  */
        !           523: 
        !           524: clear_end_of_line_raw (first_unused_hpos)
        !           525:      int first_unused_hpos;
        !           526: {
        !           527:   register int i;
        !           528:   first_unused_hpos += chars_wasted[curY] & 077;
        !           529:   if (clear_end_of_line_hook)
        !           530:     {
        !           531:       (*clear_end_of_line_hook) (first_unused_hpos);
        !           532:       return;
        !           533:     }
        !           534:   if (curX >= first_unused_hpos)
        !           535:     return;
        !           536:   /* Notice if we are erasing a magic cookie */
        !           537:   if (curX == 0)
        !           538:     chars_wasted[curY] = 0;
        !           539:   background_highlight ();
        !           540:   if (TS_clr_line)
        !           541:     {
        !           542:       OUTPUT1 (TS_clr_line);
        !           543:     }
        !           544:   else
        !           545:     {                  /* have to do it the hard way */
        !           546:       turn_off_insert ();
        !           547:       for (i = curX; i < first_unused_hpos; i++)
        !           548:        {
        !           549:          if (termscript)
        !           550:            fputc (' ', termscript);
        !           551:          putchar (' ');
        !           552:        }
        !           553:       cmplus (first_unused_hpos - curX);
        !           554:     }
        !           555: }
        !           556: 
        !           557: write_chars (start, len)
        !           558:      register char *start;
        !           559:      int len;
        !           560: {
        !           561:   register char *p;
        !           562:   register int n;
        !           563:   register char *buf;
        !           564:   register int c;
        !           565: 
        !           566:   if (write_chars_hook)
        !           567:     {
        !           568:       (*write_chars_hook) (start, len);
        !           569:       return;
        !           570:     }
        !           571:   highlight_if_desired ();
        !           572:   turn_off_insert ();
        !           573: 
        !           574:   /* Don't dare write in last column of bottom line, if AutoWrap,
        !           575:      since that would scroll the whole screen on some terminals.  */
        !           576:   if (AutoWrap && curY + 1 == screen_height
        !           577:       && curX + len == screen_width)
        !           578:     len --;
        !           579: 
        !           580:   cmplus (len);
        !           581: 
        !           582:   if (RPov > len && !TF_underscore && !TF_hazeltine)
        !           583:     {
        !           584:       fwrite (start, 1, len, stdout);
        !           585:       if (ferror (stdout))
        !           586:        clearerr (stdout);
        !           587:       if (termscript)
        !           588:        fwrite (start, 1, len, termscript);
        !           589:     }
        !           590:   else
        !           591:     while (--len >= 0)
        !           592:       {
        !           593:        if (RPov + 1 < len && *start == start[1])
        !           594:          {
        !           595:            p = start + 1;
        !           596: 
        !           597:            /* Now, len is number of chars left starting at p */
        !           598:            while (*p++ == *start);
        !           599:            /* n is number of identical chars in this run */
        !           600:            n = p - start;
        !           601:            if (n > RPov)
        !           602:              {
        !           603:                buf = (char *) alloca (strlen (TS_repeat) + 10);
        !           604:                tparam (TS_repeat, buf, *start, n);
        !           605:                tputs (buf, n, cmputc);
        !           606:                start = p;
        !           607:                len -= n - 1;
        !           608:                continue;
        !           609:              }
        !           610:          }
        !           611:        c = *start++;
        !           612:        if (c == '_' && TF_underscore)
        !           613:          {
        !           614:            if (termscript)
        !           615:              fputc (' ', termscript);
        !           616:            putchar (' ');
        !           617:            OUTPUT (Left);
        !           618:          }
        !           619:        if (TF_hazeltine && c == '~')
        !           620:          c = '`';
        !           621:        if (termscript)
        !           622:          fputc (c, termscript);
        !           623:        putchar (c);
        !           624:       }
        !           625: }
        !           626: 
        !           627: /* If start is zero, insert blanks instead of a string at start */
        !           628: 
        !           629: insert_chars (start, len)
        !           630:      register char *start;
        !           631:      int len;
        !           632: {
        !           633:   register char *buf;
        !           634:   register int c;
        !           635: 
        !           636:   if (insert_chars_hook)
        !           637:     {
        !           638:       (*insert_chars_hook) (start, len);
        !           639:       return;
        !           640:     }
        !           641:   highlight_if_desired ();
        !           642: 
        !           643:   if (TS_ins_multi_chars)
        !           644:     {
        !           645:       buf = (char *) alloca (strlen (TS_ins_multi_chars) + 10);
        !           646:       tparam (TS_ins_multi_chars, buf, len);
        !           647:       OUTPUT1 (buf);
        !           648:       if (start)
        !           649:        write_chars (start, len);
        !           650:       return;
        !           651:     }
        !           652: 
        !           653:   turn_on_insert ();
        !           654:   cmplus (len);
        !           655: 
        !           656:   if (!TF_underscore && !TF_hazeltine && start
        !           657:       && TS_pad_inserted_char == 0 && TS_ins_char == 0)
        !           658:     {
        !           659:       fwrite (start, 1, len, stdout);
        !           660:       if (termscript)
        !           661:        fwrite (start, 1, len, termscript);
        !           662:     }
        !           663:   else
        !           664:     while (--len >= 0)
        !           665:       {
        !           666:        OUTPUT1_IF (TS_ins_char);
        !           667:        if (!start)
        !           668:          c = ' ';
        !           669:        else
        !           670:          {
        !           671:            c = *start++;
        !           672:            if (TF_hazeltine && c == '~')
        !           673:              c = '`';
        !           674:          }
        !           675:        if (termscript)
        !           676:          fputc (c, termscript);
        !           677:        putchar (c);
        !           678:        OUTPUT1_IF (TS_pad_inserted_char);
        !           679:     }
        !           680: }
        !           681: 
        !           682: delete_chars (n)
        !           683:      register int n;
        !           684: {
        !           685:   char *buf;
        !           686:   register int i;
        !           687: 
        !           688:   if (delete_chars_hook)
        !           689:     {
        !           690:       (*delete_chars_hook) (n);
        !           691:       return;
        !           692:     }
        !           693: 
        !           694:   if (delete_in_insert_mode)
        !           695:     {
        !           696:       turn_on_insert ();
        !           697:     }
        !           698:   else
        !           699:     {
        !           700:       turn_off_insert ();
        !           701:       OUTPUT_IF (TS_delete_mode);
        !           702:     }
        !           703: 
        !           704:   if (TS_del_multi_chars)
        !           705:     {
        !           706:       buf = (char *) alloca (strlen (TS_del_multi_chars) + 10);
        !           707:       tparam (TS_del_multi_chars, buf, n);
        !           708:       OUTPUT1 (buf);
        !           709:     }
        !           710:   else
        !           711:     for (i = 0; i < n; i++)
        !           712:       OUTPUT1 (TS_del_char);
        !           713:   if (!delete_in_insert_mode)
        !           714:     OUTPUT_IF (TS_end_delete_mode);
        !           715: }
        !           716: 
        !           717: /* Insert N lines at vpos VPOS.  If N is negative, delete -N lines.  */
        !           718: 
        !           719: ins_del_lines (vpos, n)
        !           720:      int vpos, n;
        !           721: {
        !           722:   char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines;
        !           723:   char *single = n > 0 ? TS_ins_line : TS_del_line;
        !           724:   char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll;
        !           725: 
        !           726:   register int i = n > 0 ? n : -n;
        !           727:   register char *buf;
        !           728:   char copybuf[MScreenWidth];
        !           729: 
        !           730:   if (ins_del_lines_hook)
        !           731:     {
        !           732:       (*ins_del_lines_hook) (vpos, n);
        !           733:       return;
        !           734:     }
        !           735: 
        !           736:   /* If the lines below the insertion are being pushed
        !           737:      into the end of the window, this is the same as clearing;
        !           738:      and we know the lines are already clear, since the matching
        !           739:      deletion has already been done.  So can ignore this.  */
        !           740:   /* If the lines below the deletion are blank lines coming
        !           741:      out of the end of the window, don't bother,
        !           742:      as there will be a matching inslines later that will flush them. */
        !           743:   if (scroll_region_ok && vpos + i >= specified_window)
        !           744:     return;
        !           745:   if (!memory_below_screen && vpos + i >= screen_height)
        !           746:     return;
        !           747: 
        !           748:   if (multi)
        !           749:     {
        !           750:       raw_topos (vpos, 0);
        !           751:       background_highlight ();
        !           752:       buf = (char *) alloca (strlen (multi) + 10);
        !           753:       tparam (multi, buf, i);
        !           754:       OUTPUT (buf);
        !           755:     }
        !           756:   else if (single)
        !           757:     {
        !           758:       raw_topos (vpos, 0);
        !           759:       background_highlight ();
        !           760:       while (--i >= 0)
        !           761:        OUTPUT (single);
        !           762:       if (TF_teleray)
        !           763:        curX = 0;
        !           764:     }
        !           765:   else
        !           766:     {
        !           767:       set_scroll_region (vpos, specified_window);
        !           768:       if (n < 0)
        !           769:        raw_topos (specified_window - 1, 0);
        !           770:       else
        !           771:        raw_topos (vpos, 0);
        !           772:       background_highlight ();
        !           773:       while (--i >= 0)
        !           774:        OUTPUTL (scroll, specified_window - vpos);
        !           775:       set_scroll_region (0, specified_window);
        !           776:     }
        !           777: 
        !           778:   if (TN_standout_width >= 0)
        !           779:     {
        !           780:       if (n < 0)
        !           781:        {
        !           782:          bcopy (&chars_wasted[curY - n], &chars_wasted[curY], screen_height - curY + n);
        !           783:          bzero (&chars_wasted[screen_height + n], - n);
        !           784:        }
        !           785:       else
        !           786:        {
        !           787:          bcopy (&chars_wasted[curY], &copybuf[curY], screen_height - curY - n);
        !           788:          bcopy (&copybuf[curY], &chars_wasted[curY + n], screen_height - curY - n);
        !           789:          bzero (&chars_wasted[curY], n);
        !           790:        }
        !           791:     }
        !           792:   if (!scroll_region_ok && memory_below_screen && n < 0)
        !           793:     {
        !           794:       topos (screen_height + n, 0);
        !           795:       clear_to_end ();
        !           796:     }
        !           797: }
        !           798: 
        !           799: extern int cost;               /* In cm.c */
        !           800: extern evalcost ();
        !           801: 
        !           802: /* Compute cost of sending "str", in characters,
        !           803:    not counting any line-dependent padding.  */
        !           804: string_cost (str)
        !           805:      char *str;
        !           806: {
        !           807:   cost = 0;
        !           808:   if (str)
        !           809:     tputs (str, 0, evalcost);
        !           810:   return cost;
        !           811: }
        !           812: 
        !           813: /* Compute cost of sending "str", in characters,
        !           814:    counting any line-dependent padding at one line.  */
        !           815: string_cost_one_line (str)
        !           816:      char *str;
        !           817: {
        !           818:   cost = 0;
        !           819:   if (str)
        !           820:     tputs (str, 1, evalcost);
        !           821:   return cost;
        !           822: }
        !           823: 
        !           824: /* Compute per line amount of line-dependent padding,
        !           825:    in tenths of characters.  */
        !           826: per_line_cost (str)
        !           827:      register char *str;
        !           828: {
        !           829:   cost = 0;
        !           830:   if (str)
        !           831:     tputs (str, 0, evalcost);
        !           832:   cost = - cost;
        !           833:   if (str)
        !           834:     tputs (str, 10, evalcost);
        !           835:   return cost;
        !           836: }
        !           837: 
        !           838: /* ARGSUSED */
        !           839: calculate_ins_del_char_costs ()
        !           840: {
        !           841:   int ins_startup_cost, del_startup_cost;
        !           842:   int ins_cost_per_char, del_cost_per_char;
        !           843:   register int i;
        !           844:   register int *p;
        !           845: 
        !           846:   if (TS_ins_multi_chars)
        !           847:     {
        !           848:       ins_cost_per_char = 0;
        !           849:       ins_startup_cost = string_cost_one_line (TS_ins_multi_chars);
        !           850:     }
        !           851:   else if (TS_ins_char || TS_pad_inserted_char
        !           852:           || (TS_insert_mode && TS_end_insert_mode))
        !           853:     {
        !           854:       ins_startup_cost = 0.3 * (string_cost (TS_insert_mode) + string_cost (TS_end_insert_mode));
        !           855:       ins_cost_per_char = (string_cost_one_line (TS_ins_char)
        !           856:                           + string_cost_one_line (TS_pad_inserted_char));
        !           857:     }
        !           858:   else
        !           859:     {
        !           860:       ins_startup_cost = 9999;
        !           861:       ins_cost_per_char = 0;
        !           862:     }
        !           863: 
        !           864:   if (TS_del_multi_chars)
        !           865:     {
        !           866:       del_cost_per_char = 0;
        !           867:       del_startup_cost = string_cost_one_line (TS_del_multi_chars);
        !           868:     }
        !           869:   else if (TS_del_char)
        !           870:     {
        !           871:       del_startup_cost = (string_cost (TS_delete_mode)
        !           872:                          + string_cost (TS_end_delete_mode))
        !           873:        * (delete_in_insert_mode ? 0.5 : 1.0);
        !           874:       del_cost_per_char = string_cost_one_line (TS_del_char);
        !           875:     }
        !           876:   else
        !           877:     {
        !           878:       del_startup_cost = 9999;
        !           879:       del_cost_per_char = 0;
        !           880:     }
        !           881: 
        !           882:   /* Delete costs are at negative offsets */
        !           883:   p = &DCICcost[0];
        !           884:   for (i = screen_width; --i >= 0;)
        !           885:     *--p = (del_startup_cost += del_cost_per_char);
        !           886: 
        !           887:   /* Doing nothing is free */
        !           888:   p = &DCICcost[0];
        !           889:   *p++ = 0;
        !           890: 
        !           891:   /* Insert costs are at positive offsets */
        !           892:   for (i = screen_width; --i >= 0;)
        !           893:     *p++ = (ins_startup_cost += ins_cost_per_char);
        !           894: }
        !           895: 
        !           896: calculate_costs ()
        !           897: {
        !           898:   register char *s
        !           899:     = TS_set_scroll_region ? TS_set_scroll_region : TS_set_scroll_region_1;
        !           900: 
        !           901:   if (dont_calculate_costs)
        !           902:     return;
        !           903: 
        !           904:   if (s && (!TS_ins_line && !TS_del_line))
        !           905:     CalcIDCosts (TS_rev_scroll, TS_ins_multi_lines,
        !           906:                 TS_fwd_scroll, TS_del_multi_lines,
        !           907:                 s, s);
        !           908:   else
        !           909:     CalcIDCosts (TS_ins_line, TS_ins_multi_lines,
        !           910:                 TS_del_line, TS_del_multi_lines,
        !           911:                 0, 0);
        !           912: 
        !           913:   calculate_ins_del_char_costs ();
        !           914: 
        !           915:   /* Don't use TS_repeat if its padding is worse than sending the chars */
        !           916:   if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000)
        !           917:     RPov = string_cost (TS_repeat);
        !           918:   else
        !           919:     RPov = MScreenWidth;
        !           920: 
        !           921:   cmcostinit ();               /* set up cursor motion costs */
        !           922: }
        !           923: 
        !           924: term_init (terminal_type)
        !           925:      char *terminal_type;
        !           926: {
        !           927:   char *combuf;
        !           928:   char *fill;
        !           929:   char tbuf[2044];
        !           930:   register char *p;
        !           931: 
        !           932:   extern char *tgetstr ();
        !           933: 
        !           934:   Wcm_clear ();
        !           935:   dont_calculate_costs = 0;
        !           936: 
        !           937:   if (tgetent (tbuf, terminal_type) <= 0)
        !           938:     fatal ("Terminal type %s is not defined.\n", terminal_type);
        !           939: 
        !           940: #ifdef TERMINFO
        !           941:   combuf = (char *) malloc (2044);
        !           942: #else
        !           943:   combuf = (char *) malloc (strlen (tbuf));
        !           944: #endif /* not TERMINFO */
        !           945:   if (combuf == 0)
        !           946:     abort ();
        !           947:   fill = combuf;
        !           948: 
        !           949:   TS_ins_line = tgetstr ("al", &fill);
        !           950:   TS_ins_multi_lines = tgetstr ("AL", &fill);
        !           951:   Left = tgetstr ("bc", &fill);
        !           952:   TS_bell = tgetstr ("bl", &fill);
        !           953:   TS_clr_to_bottom = tgetstr ("cd", &fill);
        !           954:   TS_clr_line = tgetstr ("ce", &fill);
        !           955:   TS_clr_screen = tgetstr ("cl", &fill);
        !           956:   ColPosition = tgetstr ("ch", &fill);
        !           957:   AbsPosition = tgetstr ("cm", &fill);
        !           958:   CR = tgetstr ("cr", &fill);
        !           959:   TS_set_scroll_region = tgetstr ("cs", &fill);
        !           960:   TS_set_scroll_region_1 = tgetstr ("cS", &fill);
        !           961:   RowPosition = tgetstr ("cv", &fill);
        !           962:   TS_del_char = tgetstr ("dc", &fill);
        !           963:   TS_del_multi_chars = tgetstr ("DC", &fill);
        !           964:   TS_del_line = tgetstr ("dl", &fill);
        !           965:   TS_del_multi_lines = tgetstr ("DL", &fill);
        !           966:   TS_delete_mode = tgetstr ("dm", &fill);
        !           967:   TS_end_delete_mode = tgetstr ("ed", &fill);
        !           968:   TS_end_insert_mode = tgetstr ("ei", &fill);
        !           969:   Home = tgetstr ("ho", &fill);
        !           970:   TS_ins_char = tgetstr ("ic", &fill);
        !           971:   TS_ins_multi_chars = tgetstr ("IC", &fill);
        !           972:   TS_insert_mode = tgetstr ("im", &fill);
        !           973:   TS_pad_inserted_char = tgetstr ("ip", &fill);
        !           974:   TS_end_keypad_mode = tgetstr ("ke", &fill);
        !           975:   TS_keypad_mode = tgetstr ("ks", &fill);
        !           976:   LastLine = tgetstr ("ll", &fill);
        !           977:   Right = tgetstr ("nd", &fill);
        !           978:   Down = tgetstr ("nl", &fill);
        !           979:   TS_pad_char = tgetstr ("pc", &fill);
        !           980:   TS_repeat = tgetstr ("rp", &fill);
        !           981:   TS_end_standout_mode = tgetstr ("se", &fill);
        !           982:   TS_fwd_scroll = tgetstr ("sf", &fill);
        !           983:   TS_standout_mode = tgetstr ("so", &fill);
        !           984:   TS_rev_scroll = tgetstr ("sr", &fill);
        !           985:   Tab = tgetstr ("ta", &fill);
        !           986:   TS_end_termcap_modes = tgetstr ("te", &fill);
        !           987:   TS_termcap_modes = tgetstr ("ti", &fill);
        !           988:   Up = tgetstr ("up", &fill);
        !           989:   TS_visible_bell = tgetstr ("vb", &fill);
        !           990:   TS_end_visual_mode = tgetstr ("ve", &fill);
        !           991:   TS_visual_mode = tgetstr ("vs", &fill);
        !           992:   TS_set_window = tgetstr ("wi", &fill);
        !           993: 
        !           994:   AutoWrap = tgetflag ("am");
        !           995:   memory_below_screen = tgetflag ("db");
        !           996:   TF_hazeltine = tgetflag ("hz");
        !           997:   must_write_spaces = tgetflag ("in");
        !           998:   MetaFlag = tgetflag ("km") || tgetflag ("MT");
        !           999:   TF_insmode_motion = tgetflag ("mi");
        !          1000:   TF_standout_motion = tgetflag ("ms");
        !          1001:   TF_underscore = tgetflag ("ul");
        !          1002:   MagicWrap = tgetflag ("xn");
        !          1003:   TF_teleray = tgetflag ("xt");
        !          1004: 
        !          1005:   /* Get screen size fro system, or else from termcap.  */
        !          1006:   get_screen_size (&screen_width, &screen_height);
        !          1007:   if (screen_width <= 0)
        !          1008:     screen_width = tgetnum ("co");
        !          1009:   if (screen_height <= 0)
        !          1010:     screen_height = tgetnum ("li");
        !          1011: 
        !          1012:   min_padding_speed = tgetnum ("pb");
        !          1013:   TN_standout_width = tgetnum ("sg");
        !          1014:   TabWidth = tgetnum ("tw");
        !          1015: 
        !          1016:   if (tgetflag ("bs"))
        !          1017:     Left = "\b";               /* can't possibly be longer! */
        !          1018:   else if (!Left)
        !          1019:     Left = tgetstr ("le", &fill);
        !          1020: 
        !          1021:   if (!Down)
        !          1022:     Down = tgetstr ("do", &fill);
        !          1023: 
        !          1024:   if (!TS_bell)
        !          1025:     TS_bell = "\07";
        !          1026: 
        !          1027:   if (!TS_fwd_scroll)
        !          1028:     TS_fwd_scroll = Down;
        !          1029: 
        !          1030:   PC = TS_pad_char ? *TS_pad_char : 0;
        !          1031: 
        !          1032:   if (TabWidth < 0)
        !          1033:     TabWidth = 8;
        !          1034:   
        !          1035:   if (!Tab)
        !          1036:     Tab = "\t";
        !          1037: 
        !          1038:   if (TS_standout_mode == 0)
        !          1039:     {
        !          1040:       TN_standout_width = tgetnum ("ug");
        !          1041:       TS_end_standout_mode = tgetstr ("ue", &fill);
        !          1042:       TS_standout_mode = tgetstr ("us", &fill);
        !          1043:     }
        !          1044: 
        !          1045:   if (TF_teleray)
        !          1046:     {
        !          1047:       Tab = 0;
        !          1048:       /* Teleray: most programs want a space in front of TS_standout_mode,
        !          1049:           but Emacs can do without it (and give one extra column).  */
        !          1050:       TS_standout_mode = "\033RD";
        !          1051:       TN_standout_width = 1;
        !          1052:       /* But that means we cannot rely on ^M to go to column zero! */
        !          1053:       CR = 0;
        !          1054:       /* LF can't be trusted either -- can alter hpos */
        !          1055:       /* if move at column 0 thru a line with TS_standout_mode */
        !          1056:       Down = 0;
        !          1057:     }
        !          1058: 
        !          1059:   /* Special handling for certain terminal types known to need it */
        !          1060: 
        !          1061:   if (!strcmp (terminal_type, "supdup"))
        !          1062:     {
        !          1063:       memory_below_screen = 1;
        !          1064:       Wcm.cm_losewrap = 1;
        !          1065:     }
        !          1066:   if (!strncmp (terminal_type, "c10", 3)
        !          1067:       || !strcmp (terminal_type, "perq"))
        !          1068:     {
        !          1069:       /* Supply a makeshift :wi string.
        !          1070:         This string is not valid in general since it works only
        !          1071:         for windows starting at the upper left corner;
        !          1072:         but that is all Emacs uses.
        !          1073: 
        !          1074:         This string works only if the screen is using
        !          1075:         the top of the video memory, because addressing is memory-relative.
        !          1076:         So first check the :ti string to see if that is true.
        !          1077: 
        !          1078:         It would be simpler if the :wi string could go in the termcap
        !          1079:         entry, but it can't because it is not fully valid.
        !          1080:         If it were in the termcap entry, it would confuse other programs.  */
        !          1081:       if (!TS_set_window)
        !          1082:        {
        !          1083:          p = TS_termcap_modes;
        !          1084:          while (*p && strcmp (p, "\033v  "))
        !          1085:            p++;
        !          1086:          if (*p)
        !          1087:            TS_set_window = "\033v%C %C %C %C ";
        !          1088:        }
        !          1089:       /* Termcap entry often fails to have :in: flag */
        !          1090:       must_write_spaces = 1;
        !          1091:       /* :ti string typically fails to have \E^G! in it */
        !          1092:       /* This limits scope of insert-char to one line.  */
        !          1093:       strcpy (fill, TS_termcap_modes);
        !          1094:       strcat (fill, "\033\007!");
        !          1095:       TS_termcap_modes = fill;
        !          1096:       fill += strlen (fill) + 1;
        !          1097:       p = combuf;
        !          1098:       /* Change all %+ parameters to %C, to handle
        !          1099:         values above 96 correctly for the C100.  */
        !          1100:       while (p != fill)
        !          1101:        {
        !          1102:          if (p[0] == '%' && p[1] == '+')
        !          1103:            p[1] = 'C';
        !          1104:          p++;
        !          1105:        }
        !          1106:     }
        !          1107: 
        !          1108:   screen_height = min (screen_height, MScreenLength);
        !          1109:   screen_width = min (screen_width, MScreenWidth);
        !          1110: 
        !          1111:   ScreenRows = screen_height;
        !          1112:   ScreenCols = screen_width;
        !          1113:   specified_window = screen_height;
        !          1114: 
        !          1115:   if (Wcm_init ())     /* can't do cursor motion */
        !          1116:     fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\
        !          1117: It lacks the ability to position the cursor.\n\
        !          1118: If that is not the actual type of terminal you have,\n\
        !          1119: use the C-shell command `setenv TERM ...' to specify the correct type.\n",
        !          1120:           terminal_type);
        !          1121: 
        !          1122:   delete_in_insert_mode
        !          1123:     = TS_delete_mode && TS_insert_mode
        !          1124:       && !strcmp (TS_delete_mode, TS_insert_mode);
        !          1125: 
        !          1126:   se_is_so = TS_standout_mode && TS_end_standout_mode
        !          1127:     && !strcmp (TS_standout_mode, TS_end_standout_mode);
        !          1128: 
        !          1129:   /* Remove width of standout marker from usable width of line */
        !          1130:   if (TN_standout_width > 0)
        !          1131:     screen_width -= TN_standout_width;
        !          1132: 
        !          1133:   UseTabs = tabs_safe_p () && TabWidth == 8;
        !          1134: 
        !          1135:   scroll_region_ok = TS_set_window || TS_set_scroll_region
        !          1136:     || TS_set_scroll_region_1;
        !          1137: 
        !          1138:   line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines)
        !          1139:                      && (TS_del_line || TS_del_multi_lines))
        !          1140:                     || (scroll_region_ok
        !          1141:                         && TS_fwd_scroll
        !          1142:                         && TS_rev_scroll));
        !          1143: 
        !          1144:   char_ins_del_ok = ((TS_ins_char || TS_ins_multi_chars)
        !          1145:                     && (TS_del_char || TS_del_multi_chars));
        !          1146: 
        !          1147:   fast_clear_end_of_line = TS_clr_line != 0;
        !          1148: 
        !          1149:   init_baud_rate ();
        !          1150:   if (read_socket_hook)                /* Baudrate is somewhat */
        !          1151:                                /* meaningless in this case */
        !          1152:     baud_rate = 9600;
        !          1153: 
        !          1154:   calculate_costs ();
        !          1155: }
        !          1156: 
        !          1157: /* VARARGS 1 */
        !          1158: fatal (str, arg1, arg2)
        !          1159: {
        !          1160:   fprintf (stderr, "emacs: ");
        !          1161:   fprintf (stderr, str, arg1, arg2);
        !          1162:   exit (1);
        !          1163: }

unix.superglobalmegacorp.com

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