Annotation of 43BSDTahoe/new/B/src/bed/vtrm.c, revision 1.1

1.1     ! root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
        !             2: static char rcsid[] = "$Header: vtrm.c,v 1.3 85/08/30 10:11:04 timo Exp $";
        !             3: 
        !             4: /* History:
        !             5:  *     21-aug-85 GvR   added support for AL and DL (parametrized al and dl).
        !             6:  *     The Epoch tk    created and modified.
        !             7:  */
        !             8: 
        !             9: /*
        !            10:  * Virtual TeRMinal package.
        !            11:  *
        !            12:  * This package uses termcap to determine the terminal capabilities.
        !            13:  *
        !            14:  * The lines and columns of our virtual terminal are numbered 
        !            15:  *     y = {0...lines-1} from top to bottom, and
        !            16:  *     x = {0...cols-1} from left to right,
        !            17:  * respectively.
        !            18:  *
        !            19:  * The Visible Procedures in this package are:
        !            20:  *
        !            21:  * trmstart(&lines, &cols, &flags)
        !            22:  *     Obligatory initialization call (sets tty modes etc.),
        !            23:  *     Returns the height and width of the screen to the integers
        !            24:  *     whose addresses are passed as parameters, and a flag that
        !            25:  *     describes some capabilities.
        !            26:  *     Function return value: Yes if all went well, No if the terminal
        !            27:  *     is not supported.  An error message has already been displayed.
        !            28:  *
        !            29:  * trmundefined()
        !            30:  *     Sets internal representation of screen and attributes to undefined.
        !            31:  *     This is necessary for a hard redraw, which would get optimised to
        !            32:  *     oblivion,
        !            33:  *
        !            34:  * trmsense(&y, &x)
        !            35:  *     Returns the cursor position through its parameters
        !            36:  *     after a possible manual change by the user.
        !            37:  *
        !            38:  * trmputdata(yfirst, ylast, indent, data)
        !            39:  *     Fill lines {yfirst..ylast} with data, after skipping the initial
        !            40:  *     'indent' positions. It is assumed that these positions do not contain
        !            41:  *     anything dangerous (like standout cookies or null characters).
        !            42:  *
        !            43:  * trmscrollup(yfirst, ylast, by)
        !            44:  *     Shift lines {yfirst..ylast} up by lines (down |by| if by < 0).
        !            45:  *
        !            46:  * trmsync(y, x)
        !            47:  *     Call to output data to the terminal and set cursor position.
        !            48:  *
        !            49:  * trmbell()
        !            50:  *     Send a (possibly visible) bell, immediately (flushing stdout).
        !            51:  *
        !            52:  * trmend()
        !            53:  *     Obligatory termination call (resets tty modes etc.).
        !            54:  *
        !            55:  * You may call these as one or more cycles of:
        !            56:  *     + trmstart
        !            57:  *     +    zero or more times any of the other routines
        !            58:  *     + trmend
        !            59:  * To catch interrupts and the like, you may call trmend even in the middle
        !            60:  * of trmstart.
        !            61:  */
        !            62: 
        !            63: 
        !            64: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !            65: /* Includes and data definitions.                                           */
        !            66: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !            67: 
        !            68: #include <stdio.h>
        !            69: #include <setjmp.h>
        !            70: #ifndef TERMIO
        !            71: #include <sgtty.h>
        !            72: #else
        !            73: #include <termio.h>
        !            74: #endif TERMIO
        !            75: #include <signal.h>
        !            76: #include <ctype.h>             /* for isprint() */
        !            77: 
        !            78: #include "vtrm.h"
        !            79: 
        !            80: #ifdef lint
        !            81: #define VOID (void)
        !            82: #else
        !            83: #define VOID
        !            84: #endif
        !            85: 
        !            86: #define Forward
        !            87: #define Visible
        !            88: #define Hidden static
        !            89: #define Procedure
        !            90: 
        !            91: typedef short intlet;
        !            92: typedef char *string;
        !            93: typedef char bool;
        !            94: #define Yes ((bool) 1)
        !            95: #define No  ((bool) 0)
        !            96: 
        !            97: #define Min(a,b) ((a) <= (b) ? (a) : (b))
        !            98: 
        !            99: /* tty modes */
        !           100: #ifndef TERMIO
        !           101: /* v7/BSD tty control */
        !           102: Hidden struct sgttyb oldtty, newtty;
        !           103: /* to enable type ahead for abled persons on systems that provide this: */
        !           104: #ifdef TIOCSETN
        !           105: #define stty(fd,bp) VOID ioctl(fd, TIOCSETN, bp)
        !           106: #endif
        !           107: #else
        !           108: /* AT&T tty control */
        !           109: Hidden struct termio oldtty, newtty;
        !           110: #define gtty(fd,bp) ioctl(fd, TCGETA, bp)
        !           111: #define stty(fd,bp) VOID ioctl(fd, TCSETAW, bp)
        !           112: #endif TERMIO
        !           113: Hidden bool know_ttys = No;
        !           114: 
        !           115: /* visible data for termcap */
        !           116: char PC;
        !           117: char *BC;
        !           118: char *UP;
        !           119: short ospeed;
        !           120: 
        !           121: Forward int outchar();                 /* procedure for termcap's tputs */
        !           122: #define Putstr(str)    tputs((str), 1, outchar)
        !           123: extern char *tgoto();
        !           124: 
        !           125: /* termcap terminal capabilities */
        !           126: 
        !           127: Hidden int lines;
        !           128: Hidden int cols;
        !           129: 
        !           130: Hidden bool has_am;            /* has automatic margins */
        !           131: Hidden bool has_da;            /* display may be retained above screen */
        !           132: Hidden bool has_db;            /* display may be retained below screen */
        !           133: Hidden bool has_in;            /* not save to have null chars on the screen */
        !           134: Hidden bool has_mi;            /* move safely in insert (and delete?) mode */
        !           135: Hidden bool has_ms;            /* move safely in standout mode */
        !           136: Hidden bool has_xs;            /* standout not erased by overwriting */
        !           137: 
        !           138: Hidden char *al_str;           /* add new blank line */
        !           139: Hidden char *par_al_str;       /* parametrized al (AL) */
        !           140: Hidden char *cd_str;           /* clear to end of display */
        !           141: Hidden char *ce_str;           /* clear to end of line */
        !           142: Hidden char *cl_str;           /* cursor home and clear screen */
        !           143: Hidden char *cm_str;           /* cursor motion */
        !           144: Hidden char *cr_str;           /* carriage return */
        !           145: Hidden char *cs_str;           /* change scrolling region */
        !           146: Hidden char *dc_str;           /* delete character */
        !           147: Hidden char *dl_str;           /* delete line */
        !           148: Hidden char *par_dl_str;       /* parametrized dl (DL) */
        !           149: Hidden char *do_str;           /* cursor down one line */
        !           150: Hidden char *dm_str;           /* enter delete mode */
        !           151: Hidden char *ed_str;           /* end delete mode */
        !           152: Hidden char *ei_str;           /* end insert mode */
        !           153: Hidden char *ho_str;           /* cursor home */
        !           154: Hidden char *ic_str;           /* insert character (iff necessary, maybe pad) */
        !           155: Hidden char *im_str;           /* enter insert mode */
        !           156: Hidden char *le_str;           /* cursor left */
        !           157: Hidden char *nd_str;           /* cursor right (non-destructive space) */
        !           158: Hidden char *se_str;           /* end standout mode */
        !           159: Hidden char *sf_str;           /* scroll text up (from bottom of region) */
        !           160: Hidden char *so_str;           /* begin standout mode */
        !           161: Hidden char *sr_str;           /* scroll text down (from top of region) */
        !           162: Hidden char *te_str;           /* end termcap */
        !           163: Hidden char *ti_str;           /* start termcap */
        !           164: Hidden char *up_str;           /* cursor up */
        !           165: Hidden char *vb_str;           /* visible bell */
        !           166: Hidden char *ve_str;           /* make cursor visible again */
        !           167: Hidden char *vi_str;           /* make cursor invisible */
        !           168: 
        !           169: /* sense cursor position, addition to termcap */
        !           170: Hidden char *cp_str;           /* format of returned Cursor Position string */
        !           171: Hidden char *sp_str;           /* Sense cursor Position from terminal */
        !           172: 
        !           173: /* terminal status */
        !           174: 
        !           175: /* calling order of Visible Procs */
        !           176: Hidden bool started = No;
        !           177: 
        !           178: /* to exports the capabilities mentioned in vtrm.h: */
        !           179: Hidden int flags = 0;
        !           180: 
        !           181: /* cost for impossible operations */
        !           182: #define Infinity 9999
        !           183:        /* Allow for adding Infinity+Infinity within range */
        !           184:        /* (Range is assumed at least 2**15 - 1) */
        !           185: 
        !           186: /* The following for all sorts of undefined things (except for UNKNOWN char) */
        !           187: #define Undefined (-1)
        !           188: 
        !           189: /* current mode of putting char's */
        !           190: #define Normal 0
        !           191: #define Insert 1
        !           192: #define        Delete  2
        !           193: Hidden short mode = Normal;
        !           194: 
        !           195: /* current standout mode */
        !           196: #define Off    0
        !           197: #define On     0200
        !           198: Hidden short so_mode = Off;
        !           199: 
        !           200: /* masks for char's and intlet's */
        !           201: #define NULCHAR        '\000'
        !           202: #define CHAR   0177
        !           203: #define SOBIT  On
        !           204: #define SOCHAR 0377
        !           205: /* if (has_xs) record cookies placed on screen in extra bit */
        !           206: /* type of cookie is determined by the SO bit */
        !           207: #define XSBIT  0400
        !           208: #define SOCOOK 0600
        !           209: #define COOKBITS SOCOOK
        !           210: #define UNKNOWN        1
        !           211: #define NOCOOK UNKNOWN
        !           212: 
        !           213: /* current cursor position */
        !           214: Hidden intlet cur_y = Undefined, cur_x = Undefined;
        !           215: 
        !           216: /* "line[y][x]" holds the char on the terminal, with the SOBIT and XSBIT.
        !           217:  * the SOBIT tells whether the character is standing out, the XSBIT whether
        !           218:  * there is a cookie on the screen at this position.
        !           219:  * In particular a standend-cookie may be recorded AFTER the line
        !           220:  * (just in case some trmputdata will write after that position).
        !           221:  * "lenline[y]" holds the length of the line.
        !           222:  * Unknown chars will be 1, so the optimising compare in putline will fail.
        !           223:  * (Partially) empty lines are distinghuished by "lenline[y] < cols".
        !           224:  */
        !           225: Hidden intlet **line = 0, *lenline = 0;
        !           226: 
        !           227: /* Clear the screen initially iff only memory cursor addressing available */
        !           228: Hidden bool mustclear = No;
        !           229: 
        !           230: /* Make the cursor invisible when trmsync() tries to move outside the screen */
        !           231: Hidden bool no_cursor = No;
        !           232: 
        !           233: /* Optimise cursor motion */
        !           234: Hidden int abs_cost;           /* cost of absolute cursor motion */
        !           235: Hidden int cr_cost;            /* cost of carriage return */
        !           236: Hidden int do_cost;            /* cost of down */
        !           237: Hidden int le_cost;            /* cost of left */
        !           238: Hidden int nd_cost;            /* cost of right */
        !           239: Hidden int up_cost;            /* cost of up */
        !           240: 
        !           241: /* Optimise trailing match in put_line, iff the terminal can insert and delete
        !           242:  * characters; the cost per n characters will be:
        !           243:  *     n * MultiplyFactor + OverHead
        !           244:  */
        !           245: Hidden int ins_mf, ins_oh, del_mf, del_oh;
        !           246: Hidden int ed_cost, ei_cost;           /* used in move() */
        !           247: 
        !           248: /* The type of scrolling possible determines which routines get used;
        !           249:  * these may be:
        !           250:  * (1) with addline and deleteline (termcap: al_str & dl_str);
        !           251:  * (2) with a settable scrolling region, like VT100 (cs_str, sr_str, sf_str);
        !           252:  * (3) no scrolling available. (NOT YET IMPLEMENTED)
        !           253:  */
        !           254: Hidden Procedure (*scr_up)();
        !           255: Hidden Procedure (*scr_down)();
        !           256: Forward Procedure scr1up();
        !           257: Forward Procedure scr1down();
        !           258: Forward Procedure scr2up();
        !           259: Forward Procedure scr2down();
        !           260: /*Forward Procedure scr3up(); */
        !           261: /*Forward Procedure scr3down(); */
        !           262: 
        !           263: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !           264: /* Starting, Ending and (fatal) Error.                                      */
        !           265: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !           266: 
        !           267: /* 
        !           268:  * Initialization call.
        !           269:  * Determine terminal capabilities from termcap.
        !           270:  * Set up tty modes.
        !           271:  * Start up terminal and internal administration.
        !           272:  * Return Yes if succeeded, No if trouble (e.g., bad terminal type).
        !           273:  */
        !           274: Visible int
        !           275: trmstart(plines, pcols, pflags)
        !           276: int *plines;
        !           277: int *pcols;
        !           278: int *pflags;
        !           279: {
        !           280: #ifdef TRACE
        !           281: fprintf(stderr, "\ttrmstart(&li, &co, &fl);\n");
        !           282: #endif
        !           283:        if (started)
        !           284:                trmerr("trmstart called twice in succession");
        !           285:        if (!gettermcaps())
        !           286:                return No;
        !           287:        if (!setttymode())
        !           288:                return No;
        !           289:        start_trm();
        !           290: 
        !           291:        *plines = lines;
        !           292:        *pcols = cols;
        !           293:        *pflags = flags;
        !           294:        
        !           295:        started = Yes;
        !           296:        return Yes;
        !           297: }
        !           298: 
        !           299: /*
        !           300:  * Termination call.
        !           301:  * Reset tty modes, etc.
        !           302:  * Beware that it might be called by a catched interrupt even in the middle
        !           303:  * of trmstart()!
        !           304:  */
        !           305: Visible Procedure
        !           306: trmend()
        !           307: {
        !           308: #ifdef TRACE
        !           309: fprintf(stderr, "\ttrmend();\n");
        !           310: #endif
        !           311:        set_mode(Normal);
        !           312:        if (so_mode != Off)
        !           313:                standend();
        !           314:        Putstr(te_str);
        !           315:        VOID fflush(stdout);
        !           316:        resetttymode();
        !           317: 
        !           318:        started = No;
        !           319: }
        !           320: 
        !           321: /*
        !           322:  * Set all internal statuses to undefined, especially the contents of
        !           323:  * the screen, so a hard redraw will not be optimised to heaven.
        !           324:  */
        !           325: Visible Procedure
        !           326: trmundefined()
        !           327: {
        !           328:        register int y, x;
        !           329: #ifdef TRACE
        !           330: fprintf(stderr, "\ttrmundefined();\n");
        !           331: #endif
        !           332: 
        !           333:        cur_y = cur_x = Undefined;
        !           334:        mode = so_mode = Undefined;
        !           335:        
        !           336:        for (y = 0; y < lines; y++) {
        !           337:                for (x = 0; x <= cols; x++)
        !           338:                        line[y][x] = 1; /* impossible char, no so bits */
        !           339:                lenline[y] = cols;
        !           340:        }
        !           341: }
        !           342: 
        !           343: /* 
        !           344:  * Give an error message, and abort.
        !           345:  * The abort can be catched by the calling process.
        !           346:  */
        !           347: Hidden Procedure
        !           348: trmerr(mess)
        !           349: string mess;
        !           350: {
        !           351:        trmreset();
        !           352:        fprintf(stderr,
        !           353:                "*** System error in screen output module:\n*** %s\n", mess);
        !           354:        VOID fflush(stderr);
        !           355:        abort();
        !           356: }
        !           357: 
        !           358: /*
        !           359:  * Give an error message and reset the tty modes (but don't abort).
        !           360:  */
        !           361: Hidden Procedure trmmess(mess)
        !           362: string mess;
        !           363: {
        !           364:        trmreset();
        !           365:        fprintf(stderr, "*** Fatal error: %s\n", mess);
        !           366:        VOID fflush(stderr);
        !           367: }
        !           368: 
        !           369: /*
        !           370:  * Complain about a missing terminal feature.  Otherwise like trmmess.
        !           371:  */
        !           372: Hidden Procedure
        !           373: trmsorry(mess)
        !           374: string mess;
        !           375: {
        !           376:     trmreset();
        !           377:     fprintf(stderr, (
        !           378: #ifdef BED
        !           379:       "*** Sorry, this terminal isn't powerful enough to run the B editor.\n"
        !           380: #else
        !           381:       "*** Sorry, this terminal isn't powerful emough.\n"
        !           382: #endif
        !           383:     ));
        !           384:     fprintf(stderr, "*** The problem is: %s.\n", mess);
        !           385: #ifdef BED
        !           386:     fprintf(stderr,
        !           387:       "*** (You might try 'b -e' to use a standard editor instead.)\n");
        !           388: #endif
        !           389:     VOID fflush(stderr);
        !           390: }
        !           391: 
        !           392: /*
        !           393:  * Prepare for giving a (more or less fatal) error message.
        !           394:  */
        !           395: Hidden Procedure
        !           396: trmreset()
        !           397: {
        !           398:        if (started) {
        !           399:                move(lines-1, 0);
        !           400:                clear_lines(lines-1, lines-1);
        !           401:        }
        !           402:        VOID fflush(stdout);
        !           403:        resetttymode();
        !           404: }
        !           405: 
        !           406: Hidden Procedure
        !           407: check_started(m)
        !           408: char *m;
        !           409: {
        !           410:        char s[80];
        !           411:        
        !           412:        if (!started) {
        !           413:                VOID sprintf(s, "%s called outside trmstart/trmend", m);
        !           414:                trmerr(s);
        !           415:        }
        !           416: }
        !           417: 
        !           418: int ccc;
        !           419: 
        !           420: /*ARGSUSED*/
        !           421: Hidden Procedure
        !           422: countchar(ch)
        !           423: char ch;
        !           424: {
        !           425:        ccc++;
        !           426: }
        !           427: 
        !           428: Hidden int
        !           429: strcost(str)
        !           430: char *str;
        !           431: {
        !           432:        if (str == NULL)
        !           433:                return Infinity;
        !           434:        return str0cost(str);
        !           435: }
        !           436: 
        !           437: Hidden int
        !           438: str0cost(str)
        !           439: char *str;
        !           440: {
        !           441:        ccc = 0;
        !           442:        tputs(str, 1, countchar);
        !           443:        return ccc;
        !           444: }
        !           445: 
        !           446: Hidden int
        !           447: gettermcaps()                  /* get terminal capabilities from termcap
        !           448:                                 * and related static properties
        !           449:                                 */
        !           450: {
        !           451:        string trmname;
        !           452:        char tc_buf[1024];
        !           453:        static char strbuf[1024];
        !           454:        char *area = strbuf;
        !           455:        char *xPC;
        !           456:        char *getenv();
        !           457:        int tgetent();
        !           458:        int tgetnum();
        !           459:        int tgetflag();
        !           460:        char *tgetstr();
        !           461:        int sg;
        !           462:        static bool tc_initialized = No;
        !           463: #ifdef TIOCGWINSZ
        !           464:        struct winsize win;
        !           465: #endif
        !           466:        
        !           467:        if (tc_initialized)
        !           468:                return Yes;
        !           469:        
        !           470:        if ((trmname=getenv("TERM")) == NULL) {
        !           471:                trmmess("terminal type not exported in $TERM variable");
        !           472:                return No;
        !           473:        }
        !           474:        if (tgetent(tc_buf, trmname) != 1) {
        !           475:                trmmess("unknown terminal type in $TERM envariable");
        !           476:                return No;
        !           477:        }
        !           478:        
        !           479:        if (tgetflag("hc")) {
        !           480:                trmsorry("can't use a hardcopy terminal");
        !           481:                return No;
        !           482:        }
        !           483: 
        !           484:        BC = tgetstr("le", &area);
        !           485:        if (BC == NULL)
        !           486:                BC = tgetstr("bc", &area);
        !           487:        if (BC == NULL)
        !           488:                if (tgetflag("bs"))
        !           489:                        BC="\b";
        !           490:                else {
        !           491:                        trmsorry("no LEFT cursor motion");
        !           492:                        return No;
        !           493:                }
        !           494:        UP = tgetstr("up", &area);
        !           495:        if (UP == NULL) {
        !           496:                trmsorry("no UP cursor motion");
        !           497:                return No;
        !           498:        }
        !           499:        xPC = tgetstr("pc", &area);
        !           500:        PC = (xPC != NULL? xPC[0] : NULCHAR);
        !           501: 
        !           502:        ho_str = tgetstr("ho", &area);
        !           503:        do_str = tgetstr("do", &area);
        !           504:        nd_str = tgetstr("nd", &area);
        !           505:        cm_str = tgetstr("cm", &area);
        !           506:        if (cm_str == NULL) {
        !           507:                cm_str = tgetstr("CM", &area);
        !           508:                if (cm_str == NULL) {
        !           509:                        if (ho_str == NULL || do_str == NULL || nd_str == NULL) {
        !           510:                                trmsorry("no absolute cursor motion");
        !           511:                                return No;
        !           512:                        }
        !           513:                }
        !           514:                else
        !           515:                        mustclear = Yes;
        !           516:        }
        !           517: 
        !           518:        al_str = tgetstr("al", &area);
        !           519:        dl_str = tgetstr("dl", &area);
        !           520:        par_al_str = tgetstr("AL", &area);
        !           521:        par_dl_str = tgetstr("DL", &area);
        !           522:        if (al_str && dl_str) {
        !           523:                scr_up = scr1up;
        !           524:                scr_down = scr1down;
        !           525:                flags |= CAN_SCROLL;
        !           526:        }
        !           527:        else {
        !           528:                cs_str = tgetstr("cs", &area);
        !           529:                sf_str = tgetstr("sf", &area);
        !           530:                if (sf_str == NULL)
        !           531:                        sf_str = "\n";
        !           532:                sr_str = tgetstr("sr", &area);
        !           533:                if (cs_str && sr_str) {
        !           534:                        scr_up = scr2up;
        !           535:                        scr_down = scr2down;
        !           536:                        flags |= CAN_SCROLL;
        !           537:                }
        !           538:                else {
        !           539:                        trmsorry("can't scroll");
        !           540:                        return No;
        !           541:                }
        !           542:        }
        !           543:                
        !           544:        lines = tgetnum("li");
        !           545:        cols = tgetnum("co");
        !           546: #ifdef TIOCGWINSZ
        !           547:        if (ioctl (0, TIOCGWINSZ, &win) == 0) {
        !           548:                if (win.ws_col)
        !           549:                        cols = win.ws_col;
        !           550:                if (win.ws_row)
        !           551:                        lines = win.ws_row;
        !           552:        }
        !           553: #endif
        !           554:        if (lines == -1) lines = 24;
        !           555:        if (cols == -1) cols = 80;
        !           556:        
        !           557:        has_am = tgetflag("am");
        !           558:        has_db = tgetflag("db");
        !           559:        has_in = tgetflag("in");
        !           560:        has_mi = tgetflag("mi");
        !           561:        has_ms = tgetflag("ms");
        !           562:        has_xs = tgetflag("xs");
        !           563:        if ((sg=tgetnum("sg")) == 0)
        !           564:                has_xs = Yes;
        !           565:        else if (sg > 0) {
        !           566:                trmsorry("video attributes take up space on the screen");
        !           567:                return No;
        !           568:        }
        !           569:        
        !           570:        cd_str = tgetstr("cd", &area);
        !           571:        ce_str = tgetstr("ce", &area);
        !           572:        if (!ce_str) {
        !           573:                trmsorry("can't clear to end of line");
        !           574:                return No;
        !           575:        }
        !           576:        cl_str = tgetstr("cl", &area);
        !           577:        cr_str = tgetstr("cr", &area);
        !           578:        if (cr_str == NULL) cr_str = "\r";
        !           579:        dc_str = tgetstr("dc", &area);
        !           580:        dm_str = tgetstr("dm", &area);
        !           581:        if (do_str == NULL) do_str = tgetstr("nl", &area);
        !           582:        if (do_str == NULL) do_str = "\n";
        !           583:        ed_str = tgetstr("ed", &area);
        !           584:        ei_str = tgetstr("ei", &area);
        !           585:        ic_str = tgetstr("ic", &area);
        !           586:        im_str = tgetstr("im", &area);
        !           587:        le_str = BC;
        !           588:        se_str = tgetstr("se", &area);
        !           589:        so_str = tgetstr("so", &area);
        !           590:        te_str = tgetstr("te", &area);
        !           591:        ti_str = tgetstr("ti", &area);
        !           592:        up_str = UP;
        !           593:        vb_str = tgetstr("vb", &area);
        !           594:        if (vb_str == NULL)     /* then we will do with the audible bell */
        !           595:                vb_str = "\007";
        !           596:        ve_str = tgetstr("ve", &area);
        !           597:        vi_str = tgetstr("vi", &area);
        !           598:        
        !           599:        /* cursor sensing (non standard) */
        !           600:        cp_str = tgetstr("cp", &area);
        !           601:        sp_str = tgetstr("sp", &area);
        !           602:        if (cp_str != NULL && sp_str != NULL)
        !           603:                flags |= CAN_SENSE;
        !           604: 
        !           605:        if (so_str != NULL && se_str != NULL)
        !           606:                flags |= HAS_STANDOUT;
        !           607: 
        !           608:        /* calculate costs of local and absolute cursor motions */
        !           609:        if (cm_str == NULL)
        !           610:                abs_cost = Infinity;
        !           611:        else
        !           612:                abs_cost = strcost(tgoto(cm_str, 0, 0));
        !           613:        cr_cost = strcost(cr_str);
        !           614:        do_cost = strcost(do_str);
        !           615:        le_cost = strcost(le_str);
        !           616:        nd_cost = strcost(nd_str);
        !           617:        up_cost = strcost(up_str);
        !           618: 
        !           619:        /* cost of leaving insert or delete mode, used in move() */
        !           620:        ei_cost = str0cost(ei_str);
        !           621:        ed_cost = str0cost(ed_str);
        !           622:        
        !           623:        /* calculate insert and delete cost multiply_factor and overhead */
        !           624:        if (((im_str && ei_str) || ic_str) && dc_str) {
        !           625:                flags |= CAN_OPTIMISE;
        !           626:                ins_mf = 1 + str0cost(ic_str);
        !           627:                ins_oh = str0cost(im_str) + ei_cost;
        !           628:                del_mf = str0cost(dc_str);
        !           629:                del_oh = str0cost(dm_str) + ed_cost;
        !           630:        }
        !           631:                
        !           632:        tc_initialized = Yes;
        !           633:        return Yes;
        !           634: }
        !           635: 
        !           636: Hidden int
        !           637: setttymode()
        !           638: {
        !           639:        if (!know_ttys) {
        !           640:                if (gtty(1, &oldtty) != 0 || gtty(1, &newtty) != 0) {
        !           641:                        trmmess("can't get tty modes (output not a terminal)");
        !           642:                        return No;
        !           643:                }
        !           644: #ifndef TERMIO
        !           645:                ospeed = oldtty.sg_ospeed;
        !           646: #ifdef PWB
        !           647:                newtty.sg_flags = (newtty.sg_flags & ~ECHO & ~CRMOD & ~XTABS)
        !           648:                                  | RAW;
        !           649: #else PWB
        !           650:                newtty.sg_flags = (newtty.sg_flags & ~ECHO & ~CRMOD & ~XTABS)
        !           651:                                  | CBREAK;
        !           652: #endif PWB
        !           653: #else TERMIO
        !           654:                ospeed= oldtty.c_lflag & CBAUD;
        !           655:                newtty.c_iflag &= ~ICRNL; /* No CR->NL mapping on input */
        !           656:                newtty.c_oflag &= ~ONLCR; /* NL doesn't output CR */
        !           657:                newtty.c_lflag &= ~(ICANON|ECHO); /* No line editing, no echo */
        !           658:                newtty.c_cc[VMIN]= 3; /* wait for 3 characters */
        !           659:                newtty.c_cc[VTIME]= 1; /* or 0.1 sec. */
        !           660: #endif TERMIO
        !           661:                know_ttys = Yes;
        !           662:        }
        !           663:        stty(1, &newtty);
        !           664:        return Yes;
        !           665: }
        !           666: 
        !           667: Hidden Procedure
        !           668: resetttymode()
        !           669: {
        !           670:        if (know_ttys)
        !           671:                stty(1, &oldtty);
        !           672: }
        !           673: 
        !           674: Hidden char*
        !           675: lalloc(size)
        !           676: unsigned size;
        !           677: {
        !           678:        char *l;
        !           679:        char *malloc();
        !           680:        
        !           681:        l = malloc(size);
        !           682:        if (l == NULL)
        !           683:                trmerr("not enough memory for screen buffer");
        !           684:        return l;
        !           685: }
        !           686: 
        !           687: Hidden Procedure
        !           688: start_trm()
        !           689: {
        !           690:        register int y;
        !           691:        
        !           692:        if (line == 0) {
        !           693:                line = (intlet**) lalloc((unsigned) lines * sizeof(intlet*));
        !           694:                for (y = 0; y < lines; y++)
        !           695:                        line[y] = (intlet*) lalloc((unsigned) ((cols+1)*sizeof(intlet)));
        !           696:        }
        !           697:        if (lenline == 0)
        !           698:                lenline = (intlet*) lalloc((unsigned) lines * sizeof(intlet));
        !           699: 
        !           700:        
        !           701:        trmundefined();
        !           702:        
        !           703:        Putstr(ti_str);
        !           704:        if (cs_str)
        !           705:                Putstr(tgoto(cs_str, lines-1, 0));
        !           706:        if (mustclear)
        !           707:                clear_lines(0, lines-1);
        !           708: }
        !           709: 
        !           710: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !           711: /* Sensing and moving the cursor.                                           */
        !           712: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !           713: 
        !           714: /*
        !           715:  * Sense the current (y, x) cursor position, after a possible manual
        !           716:  * change by the user with local cursor motions.
        !           717:  * If the terminal cannot be asked for the current cursor position,
        !           718:  * or if the string returned by the terminal is garbled,
        !           719:  * the position is made Undefined.
        !           720:  */
        !           721: Visible Procedure
        !           722: trmsense(py, px)
        !           723:        int *py;
        !           724:        int *px;
        !           725: {
        !           726:        bool getpos();
        !           727: 
        !           728: #ifdef TRACE
        !           729: fprintf(stderr, "\ttrmsense(&yy, &xx);\n");
        !           730: #endif
        !           731:        check_started("trmsense");
        !           732: 
        !           733:        *py = *px = Undefined;
        !           734:        set_mode(Normal);
        !           735:        if (so_mode != Off)
        !           736:                standend();
        !           737:        
        !           738:        if (flags&CAN_SENSE && getpos(py, px)) {
        !           739:                if (*py < 0 || lines <= *py || *px < 0 || cols <= *px)
        !           740:                        *py = *px = Undefined;
        !           741:        }
        !           742:        cur_y = *py;
        !           743:        cur_x = *px;
        !           744: }
        !           745: 
        !           746: Hidden bool
        !           747: getpos(py, px)
        !           748: int *py, *px;
        !           749: {
        !           750:        char *format = cp_str;
        !           751:        int fc;                 /* current format character */
        !           752:        int ic;                 /* current input character */
        !           753:        int num;
        !           754:        int on_y = 1;
        !           755:        bool incr_orig = No;
        !           756:        int i, ni;
        !           757: 
        !           758:        Putstr(sp_str);
        !           759:        VOID fflush(stdout);
        !           760: 
        !           761:        while (fc = *format++) {
        !           762:                if (fc != '%') {
        !           763:                        if (getchar() != fc)
        !           764:                                return No;
        !           765:                }
        !           766:                else {
        !           767:                        switch (fc = *format++) {
        !           768:                        case '%':
        !           769:                                if (getchar() != '%')
        !           770:                                        return No;
        !           771:                                continue;
        !           772:                        case 'r':
        !           773:                                on_y = 1 - on_y;
        !           774:                                continue;
        !           775:                        case 'i':
        !           776:                                incr_orig = Yes;
        !           777:                                continue;
        !           778:                        case 'd':
        !           779:                                ic = getchar();
        !           780:                                if (!isdigit(ic))
        !           781:                                        return No;
        !           782:                                num = ic - '0';
        !           783:                                while (isdigit(ic=getchar()))
        !           784:                                        num = 10*num + ic - '0';
        !           785:                                VOID ungetc(ic, stdin);
        !           786:                                break;
        !           787:                        case '2':
        !           788:                        case '3':
        !           789:                                ni = fc - '0';
        !           790:                                num = 0;
        !           791:                                for (i=0; i<ni; i++) {
        !           792:                                        ic = getchar();
        !           793:                                        if (isdigit(ic))
        !           794:                                                num = 10*num + ic - '0';
        !           795:                                        else
        !           796:                                                return No;
        !           797:                                }
        !           798:                                break;
        !           799:                        case '+':
        !           800:                                num = getchar() - *format++;
        !           801:                                break;
        !           802:                        case '-':
        !           803:                                num = getchar() + *format++;
        !           804:                                break;
        !           805:                        default:
        !           806:                                return No;
        !           807:                        }
        !           808:                        /* assign num to parameter */
        !           809:                        if (incr_orig)
        !           810:                                num--;
        !           811:                        if (on_y)
        !           812:                                *py = num;
        !           813:                        else
        !           814:                                *px = num;
        !           815:                        on_y = 1 - on_y;
        !           816:                }
        !           817:        }
        !           818: 
        !           819:        return Yes;
        !           820: }
        !           821:                
        !           822: /* 
        !           823:  * To move over characters by rewriting them, we have to check:
        !           824:  * (1) that the screen has been initialised on these positions;
        !           825:  * (2) we do not screw up characters
        !           826:  * when rewriting line[y] from x_from upto x_to
        !           827:  */
        !           828: Hidden bool
        !           829: rewrite_ok(y, xfrom, xto)
        !           830: int y, xfrom, xto;
        !           831: {
        !           832:        register intlet *plnyx, *plnyto;
        !           833:        
        !           834:        if (xto > lenline[y])
        !           835:                return No;
        !           836: 
        !           837:        plnyto = &line[y][xto];
        !           838:        for (plnyx = &line[y][xfrom]; plnyx <= plnyto; plnyx++)
        !           839:                if (*plnyx == UNKNOWN
        !           840:                    ||
        !           841:                    (!has_xs && (*plnyx & SOBIT) != so_mode)
        !           842:                   )
        !           843:                        return No;
        !           844:        return Yes;
        !           845: }
        !           846:                
        !           847: /*
        !           848:  * Move to position y,x on the screen
        !           849:  */
        !           850: /* possible move types for y and x respectively: */
        !           851: #define None   0
        !           852: #define Down   1
        !           853: #define Up     2
        !           854: #define Right  1
        !           855: #define ReWrite        2
        !           856: #define Left   3
        !           857: #define CrWrite        4
        !           858: 
        !           859: Hidden Procedure
        !           860: move(y, x)
        !           861: int y, x;
        !           862: {
        !           863:        int dy, dx;
        !           864:        int y_cost, x_cost, y_move, x_move;
        !           865:        int mode_cost;
        !           866:        int xi;
        !           867:        
        !           868:        if (cur_y == y && cur_x == x)
        !           869:                return;
        !           870:        
        !           871:        if (!has_mi || mode == Undefined)
        !           872:                set_mode(Normal);
        !           873:        if (!has_xs && ((!has_ms && so_mode != Off) || so_mode == Undefined))
        !           874:                standend();
        !           875:        
        !           876:        if (cur_y == Undefined || cur_x == Undefined)
        !           877:                goto absmove;
        !           878:        
        !           879:        dy = y - cur_y;
        !           880:        dx = x - cur_x;
        !           881: 
        !           882:        if (dy > 0) {
        !           883:                y_move = Down;
        !           884:                y_cost = dy * do_cost;
        !           885:        }
        !           886:        else if (dy < 0) {
        !           887:                y_move = Up;
        !           888:                y_cost = -dy * up_cost;
        !           889:        }
        !           890:        else {
        !           891:                y_move = None;
        !           892:                y_cost = 0;
        !           893:        }
        !           894:        if (y_cost < abs_cost) {
        !           895:                switch (mode) {
        !           896:                case Normal:
        !           897:                        mode_cost = 0;
        !           898:                        break;
        !           899:                case Insert:
        !           900:                        mode_cost = ei_cost;
        !           901:                        break;
        !           902:                case Delete:
        !           903:                        mode_cost = ed_cost;
        !           904:                        break;
        !           905:                }
        !           906:                if (dx > 0) {
        !           907:                        x_cost = dx + mode_cost;
        !           908:                        if (dx*nd_cost < x_cost || !rewrite_ok(y, cur_x, x)) {
        !           909:                                x_cost = dx * nd_cost;
        !           910:                                x_move = Right;
        !           911:                        }
        !           912:                        else
        !           913:                                x_move = ReWrite;
        !           914:                }
        !           915:                else if (dx < 0) {
        !           916:                        x_cost = -dx * le_cost;
        !           917:                        x_move = Left;
        !           918:                }
        !           919:                else {
        !           920:                        x_cost = 0;
        !           921:                        x_move = None;
        !           922:                }
        !           923:                if (cr_cost + x + mode_cost < x_cost && rewrite_ok(y, 0, x)) {
        !           924:                        x_move = CrWrite;
        !           925:                        x_cost = cr_cost + x + mode_cost;
        !           926:                }
        !           927:        }
        !           928:        else
        !           929:                x_cost = abs_cost;
        !           930: 
        !           931:        if (y_cost + x_cost < abs_cost) {
        !           932:                switch (y_move) {
        !           933:                case Down:
        !           934:                        while (dy-- > 0) Putstr(do_str);
        !           935:                        break;
        !           936:                case Up:
        !           937:                        while (dy++ < 0) Putstr(up_str);
        !           938:                        break;
        !           939:                }
        !           940:                switch (x_move) {
        !           941:                case Right:
        !           942:                        while (dx-- > 0) Putstr(nd_str);
        !           943:                        break;
        !           944:                case Left:
        !           945:                        while (dx++ < 0) Putstr(le_str);
        !           946:                        break;
        !           947:                case CrWrite:
        !           948:                        Putstr(cr_str);
        !           949:                        cur_x = 0;
        !           950:                        /* FALL THROUGH */
        !           951:                case ReWrite:
        !           952:                        set_mode(Normal);
        !           953:                        for (xi = cur_x; xi < x; xi++)
        !           954:                                putchar(line[y][xi]);
        !           955:                        break;
        !           956:                }
        !           957:        }
        !           958:        else
        !           959:        {
        !           960:     absmove:
        !           961:                if (cm_str == NULL) {
        !           962:                        Putstr(ho_str);
        !           963:                        for (cur_y = 0; cur_y < y; ++cur_y)
        !           964:                                Putstr(do_str);
        !           965:                        /* Should try to use tabs here: */
        !           966:                        for (cur_x = 0; cur_x < x; ++cur_x)
        !           967:                                Putstr(nd_str);
        !           968:                }
        !           969:                else
        !           970:                        Putstr(tgoto(cm_str, x, y));
        !           971:        }
        !           972:        
        !           973:        cur_y = y;
        !           974:        cur_x = x;
        !           975: }
        !           976: 
        !           977: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !           978: /* Putting data on the screen.                                              */
        !           979: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !           980: 
        !           981: /*
        !           982:  * Fill screen area with given data.
        !           983:  * Characters with the SO-bit (0200) set are put in standout mode.
        !           984:  */
        !           985: Visible Procedure
        !           986: trmputdata(yfirst, ylast, indent, data)
        !           987: int yfirst;
        !           988: int ylast;
        !           989: register int indent;
        !           990: register string data;
        !           991: {
        !           992:        register int y;
        !           993:        int x, len, lendata, space;
        !           994:                
        !           995: #ifdef TRACE
        !           996: fprintf(stderr, "\ttrmputdata(%d, %d, %d, \"%s\");\n", yfirst, ylast, indent, data);
        !           997: #endif
        !           998:        check_started("trmputdata");
        !           999:        
        !          1000:        if (yfirst < 0)
        !          1001:                yfirst = 0;
        !          1002:        if (ylast >= lines)
        !          1003:                ylast = lines-1;
        !          1004:        space = cols*(ylast-yfirst+1) - indent;
        !          1005:        if (space <= 0)
        !          1006:                return;
        !          1007:        yfirst += indent/cols;
        !          1008:        indent %= cols;
        !          1009:        if (data) {
        !          1010:                x = indent;
        !          1011:                lendata = strlen(data);
        !          1012:                if (ylast == lines-1 && lendata >= space)
        !          1013:                        lendata = space - 1;
        !          1014:                len = Min(lendata, cols-x);
        !          1015:                for (y = yfirst; y <= ylast; ) {
        !          1016:                        put_line(y, x, data, len);
        !          1017:                        y++;
        !          1018:                        lendata -= len;
        !          1019:                        if (lendata > 0) {
        !          1020:                                x = 0;
        !          1021:                                data += len;
        !          1022:                                len = Min(lendata, cols);
        !          1023:                        }
        !          1024:                        else
        !          1025:                                break;
        !          1026:                }
        !          1027:        }
        !          1028:        if (y <= ylast)
        !          1029:                clear_lines(y, ylast);
        !          1030: }
        !          1031: 
        !          1032: /* 
        !          1033:  * We will first try to get the picture:
        !          1034:  *
        !          1035:  *                  op>>>>>>>>>>>op          oq<<<<<<<<<<<<<<<<<<<<<<<<oq
        !          1036:  *                  ^            ^           ^                         ^
        !          1037:  *           <xskip><-----m1----><----od-----><-----------m2----------->
        !          1038:  *   OLD:   "You're in a maze of twisty little pieces of code, all alike"
        !          1039:  *   NEW:          "in a maze of little twisting pieces of code, all alike"
        !          1040:  *                  <-----m1----><-----nd------><-----------m2----------->
        !          1041:  *                  ^            ^             ^                         ^
        !          1042:  *                  np>>>>>>>>>>>np            nq<<<<<<<<<<<<<<<<<<<<<<<<nq
        !          1043:  * where
        !          1044:  *     op, oq, np, nq are pointers to start and end of Old and New data,
        !          1045:  * and
        !          1046:  *     xskip = length of indent to be skipped,
        !          1047:  *     m1 = length of Matching part at start,
        !          1048:  *     od = length of Differing mid on screen,
        !          1049:  *     nd = length of Differing mid in data to be put,
        !          1050:  *     m2 = length of Matching trail.
        !          1051:  *
        !          1052:  * Then we will try to find a long blank-or-cleared piece in <nd+m2>:
        !          1053:  *
        !          1054:  *    <---m1---><---d1---><---nb---><---d2---><---m2--->
        !          1055:  *              ^         ^         ^        ^         ^
        !          1056:  *              np        bp        bq1      nq        nend
        !          1057:  * where
        !          1058:  *     bp, bq are pointers to start and AFTER end of blank piece,
        !          1059:  * and
        !          1060:  *     d1 = length of differing part before blank piece,
        !          1061:  *     nb = length of blank piece to be skipped,
        !          1062:  *     d2 = length of differing part after blank piece.
        !          1063:  * Remarks:
        !          1064:  *     d1 + nb + d2 == nd,
        !          1065:  * and
        !          1066:  *     d2 maybe less than 0.
        !          1067:  */
        !          1068: Hidden int
        !          1069: put_line(y, xskip, data, len)
        !          1070: int y, xskip;
        !          1071: string data;
        !          1072: int len;
        !          1073: {
        !          1074:        register intlet *op, *oq;
        !          1075:        register char *np, *nq, *nend;
        !          1076:        char *bp, *bq1, *p, *q;
        !          1077:        int m1, m2, od, nd, delta, dd, d1, nb, d2;
        !          1078:        bool skipping;
        !          1079:        int cost, o_cost;       /* normal and optimising cost */
        !          1080:        
        !          1081:        /* calculate the magic parameters */
        !          1082:        op = &line[y][xskip];
        !          1083:        oq = &line[y][lenline[y]-1];
        !          1084:        np = data;
        !          1085:        nq = nend = data + len - 1;
        !          1086:        m1 = m2 = 0;
        !          1087:        while ((*op&SOCHAR) == (((intlet)*np)&SOCHAR) && op <= oq && np <= nq)
        !          1088:                op++, np++, m1++;
        !          1089:        if (flags & CAN_OPTIMISE)
        !          1090:                while ((*oq&SOCHAR) == (((intlet)*nq)&SOCHAR) && op <= oq && np <= nq)
        !          1091:                        oq--, nq--, m2++;
        !          1092:        od = oq - op + 1;
        !          1093:        nd = nq - np + 1;
        !          1094:        /* now we have the first picture above */
        !          1095: 
        !          1096:        if (od==0 && nd==0)
        !          1097:                return;
        !          1098:        delta = nd - od;
        !          1099: 
        !          1100:        /* find the blank piece */
        !          1101:        p = q = bp = bq1 = np;
        !          1102:        oq += m2;               /* back to current eol */
        !          1103:        if (!has_in) {
        !          1104:                while (p <= nend) {
        !          1105:                        while (q<=nend && *q==' ' && (op>oq || *op==' '))
        !          1106:                                q++, op++;
        !          1107:                        if (q - p > bq1 - bp)
        !          1108:                                bp = p, bq1 = q;
        !          1109:                        p = ++q;
        !          1110:                        op++;
        !          1111:                }
        !          1112:        }
        !          1113:        d1 = bp - np;
        !          1114:        nb = bq1 - bp;
        !          1115:        d2 = nq - bq1 + 1;
        !          1116:        
        !          1117:        /* what is cheapest:
        !          1118:         *      normal: put nd+m2;                         (dd = nd+m2)
        !          1119:         *      skipping: put d1, skip nb, put d2+m2;      (dd = d2+m2)
        !          1120:         *      optimise: put dd, insert or delete delta.  (dd = min(od,nd))
        !          1121:         */
        !          1122:        cost = nd + m2;         /* normal cost */
        !          1123:        if (nb > abs_cost || (d1 == 0 && nb > 0)) {
        !          1124:                skipping = Yes;
        !          1125:                cost -= nb - (d1>0 ? abs_cost : 0); /* skipping cost */
        !          1126:                dd = d2;
        !          1127:        }
        !          1128:        else {
        !          1129:                skipping = No;
        !          1130:                dd = nd;
        !          1131:        }
        !          1132:        
        !          1133:        if (m2 != 0) {
        !          1134:                /* try optimising */
        !          1135:                o_cost = Min(od, nd);
        !          1136:                if (delta > 0)
        !          1137:                        o_cost += delta * ins_mf + ins_oh;
        !          1138:                else if (delta < 0)
        !          1139:                        o_cost += -delta * del_mf + del_oh;
        !          1140:                if (o_cost >= cost) {
        !          1141:                        /* discard m2, no optimise */
        !          1142:                        dd += m2;
        !          1143:                        m2 = 0;
        !          1144:                }
        !          1145:                else {
        !          1146:                        dd = Min(od, nd);
        !          1147:                        skipping = No;
        !          1148:                }
        !          1149:        }
        !          1150: 
        !          1151:        /* and now for the real work */
        !          1152:        if (!skipping || d1 > 0)
        !          1153:                move(y, xskip + m1);
        !          1154: 
        !          1155:        if (has_xs)
        !          1156:                get_so_mode();
        !          1157:        
        !          1158:        if (skipping) {
        !          1159:                if (d1 > 0) {
        !          1160:                        set_mode(Normal);
        !          1161:                        put_str(np, d1, No);
        !          1162:                }
        !          1163:                if (has_xs && so_mode != Off)
        !          1164:                        standend();
        !          1165:                set_blanks(y, xskip+m1+d1, xskip+m1+d1+nb);
        !          1166:                if (dd != 0 || delta < 0) {
        !          1167:                        move(y, xskip+m1+d1+nb);
        !          1168:                        np = bq1;
        !          1169:                }
        !          1170:        }
        !          1171:        
        !          1172:        if (dd > 0) {
        !          1173:                set_mode(Normal);
        !          1174:                put_str(np, dd, No);
        !          1175:        }
        !          1176:        
        !          1177:        if (m2 > 0) {
        !          1178:                if (delta > 0) {
        !          1179:                        set_mode(Insert);
        !          1180:                        ins_str(np+dd, delta);
        !          1181:                }
        !          1182:                else if (delta < 0) {
        !          1183:                        set_mode(Delete);
        !          1184:                        del_str(-delta);
        !          1185:                }
        !          1186:        }
        !          1187:        else {
        !          1188:                if (delta < 0) {
        !          1189:                        clr_to_eol();
        !          1190:                        return;
        !          1191:                }
        !          1192:        }
        !          1193:        
        !          1194:        lenline[y] = xskip + len;
        !          1195:        if (cur_x == cols) {
        !          1196:                if (!has_mi)
        !          1197:                        set_mode(Normal);
        !          1198:                if (!has_ms)
        !          1199:                        so_mode = Undefined;
        !          1200:                if (has_am)
        !          1201:                        cur_y++;
        !          1202:                else
        !          1203:                        Putstr(cr_str);
        !          1204:                cur_x = 0;
        !          1205:        }
        !          1206:        else if (has_xs) {
        !          1207:                if (m2 == 0) {
        !          1208:                        if (so_mode == On)
        !          1209:                                standend();
        !          1210:                }
        !          1211:                else {
        !          1212:                        if (!(line[cur_y][cur_x] & XSBIT)) {
        !          1213:                                if (so_mode != (line[cur_y][cur_x] & SOBIT))
        !          1214:                                        (so_mode ? standend() : standout());
        !          1215:                        }
        !          1216:                }
        !          1217:        }
        !          1218: }
        !          1219: 
        !          1220: Hidden Procedure
        !          1221: set_mode(m)
        !          1222: int m;
        !          1223: {
        !          1224:        if (m == mode)
        !          1225:                return;
        !          1226:        switch (mode) {
        !          1227:        case Insert:
        !          1228:                Putstr(ei_str);
        !          1229:                break;
        !          1230:        case Delete:
        !          1231:                Putstr(ed_str);
        !          1232:                break;
        !          1233:        case Undefined:
        !          1234:                Putstr(ei_str);
        !          1235:                Putstr(ed_str);
        !          1236:                break;
        !          1237:        }
        !          1238:        switch (m) {
        !          1239:        case Insert:
        !          1240:                Putstr(im_str);
        !          1241:                break;
        !          1242:        case Delete:
        !          1243:                Putstr(dm_str);
        !          1244:                break;
        !          1245:        }
        !          1246:        mode = m;
        !          1247: }
        !          1248: 
        !          1249: Hidden Procedure
        !          1250: get_so_mode()
        !          1251: {
        !          1252:        if (cur_x >= lenline[cur_y] || line[cur_y][cur_x] == UNKNOWN)
        !          1253:                so_mode = Off;
        !          1254:        else
        !          1255:                so_mode = line[cur_y][cur_x] & SOBIT;
        !          1256: }
        !          1257: 
        !          1258: Hidden Procedure
        !          1259: standout()
        !          1260: {
        !          1261:        Putstr(so_str);
        !          1262:        so_mode = On;
        !          1263:        if (has_xs)
        !          1264:                line[cur_y][cur_x] |= SOCOOK;
        !          1265: }
        !          1266: 
        !          1267: Hidden Procedure
        !          1268: standend()
        !          1269: {
        !          1270:        Putstr(se_str);
        !          1271:        so_mode = Off;
        !          1272:        if (has_xs)
        !          1273:                line[cur_y][cur_x] = (line[cur_y][cur_x] & ~SOBIT) | XSBIT;
        !          1274: }
        !          1275: 
        !          1276: Hidden Procedure
        !          1277: put_str(data, n, inserting)
        !          1278: char *data;
        !          1279: int n;
        !          1280: bool inserting;
        !          1281: {
        !          1282:        register intlet c, so;
        !          1283:        intlet *ln_y_x, *ln_y_end;
        !          1284:        
        !          1285:        so = so_mode;
        !          1286:        if (has_xs) {
        !          1287:                ln_y_x = &line[cur_y][cur_x];
        !          1288:                ln_y_end = &line[cur_y][lenline[cur_y]];
        !          1289:        }
        !          1290:        while (n-- > 0) {
        !          1291:                if (has_xs && ln_y_x <= ln_y_end && ((*ln_y_x)&XSBIT))
        !          1292:                        so = so_mode = (*ln_y_x)&SOBIT;
        !          1293:                        /* this also checks for the standend cookie AFTER */
        !          1294:                        /* the line because off the equals sign in <= */
        !          1295:                c = ((intlet)(*data++))&SOCHAR;
        !          1296:                if ((c&SOBIT) != so) {
        !          1297:                        so = c&SOBIT;
        !          1298:                        so ? standout() : standend();
        !          1299:                }
        !          1300:                if (inserting)
        !          1301:                        Putstr(ic_str);
        !          1302:                put_c(c);
        !          1303:                if (has_xs)
        !          1304:                        ln_y_x++;
        !          1305:        }
        !          1306: }
        !          1307: 
        !          1308: Hidden Procedure
        !          1309: ins_str(data, n)
        !          1310: char *data;
        !          1311: int n;
        !          1312: {
        !          1313:        int x;
        !          1314:        
        !          1315:        /* x will start AFTER the line, because there might be a cookie */
        !          1316:        for (x = lenline[cur_y]; x >= cur_x; x--)
        !          1317:                line[cur_y][x+n] = line[cur_y][x];
        !          1318:        put_str(data, n, Yes);
        !          1319: }
        !          1320: 
        !          1321: Hidden Procedure
        !          1322: del_str(n)
        !          1323: int n;
        !          1324: {
        !          1325:        int x, xto;
        !          1326:        
        !          1327:        xto = lenline[cur_y] - n; /* again one too far because of cookie */
        !          1328:        if (has_xs) {
        !          1329:                for (x = cur_x + n; x >= cur_x; x--) {
        !          1330:                        if (line[cur_y][x] & XSBIT)
        !          1331:                                break;
        !          1332:                }
        !          1333:                if (x >= cur_x)
        !          1334:                        line[cur_y][cur_x+n] =
        !          1335:                                (line[cur_y][cur_x+n] & CHAR)
        !          1336:                                |
        !          1337:                                (line[cur_y][x] & COOKBITS);
        !          1338:        }
        !          1339:        for (x = cur_x; x <= xto; x++)
        !          1340:                line[cur_y][x] = line[cur_y][x+n];
        !          1341:        while (n-- > 0)
        !          1342:                Putstr(dc_str);
        !          1343: }
        !          1344: 
        !          1345: Hidden Procedure
        !          1346: put_c(c)
        !          1347: intlet c;
        !          1348: {
        !          1349:        char ch;
        !          1350:        intlet xs_flag;
        !          1351:        
        !          1352:        ch = c&CHAR;
        !          1353:        if (!isprint(ch) && ch != ' ') { /* V7 isprint doesn't include blank */
        !          1354:                ch = '?';
        !          1355:                c = (c&SOBIT)|'?';
        !          1356:        }
        !          1357:        putchar(ch);
        !          1358:        if (has_xs)
        !          1359:                xs_flag = line[cur_y][cur_x]&XSBIT;
        !          1360:        else
        !          1361:                xs_flag = 0;
        !          1362:        line[cur_y][cur_x] = (c&SOCHAR)|xs_flag;
        !          1363:        cur_x++;
        !          1364: }
        !          1365: 
        !          1366: Hidden Procedure
        !          1367: clear_lines(yfirst, ylast)
        !          1368: int yfirst, ylast ;
        !          1369: {
        !          1370:        register int y;
        !          1371:        
        !          1372:        if (!has_xs && so_mode != Off)
        !          1373:                standend();
        !          1374:        if (cl_str && yfirst == 0 && ylast == lines-1) {
        !          1375:                Putstr(cl_str);
        !          1376:                cur_y = cur_x = 0;
        !          1377:                return;
        !          1378:        }
        !          1379:        for (y = yfirst; y <= ylast; y++) {
        !          1380:                if (lenline[y] > 0) {
        !          1381:                        move(y, 0);
        !          1382:                        if (ylast == lines-1 && cd_str) {
        !          1383:                                Putstr(cd_str);
        !          1384:                                while (y <= ylast) {
        !          1385:                                        if (has_xs) line[y][0] = NOCOOK;
        !          1386:                                        lenline[y++] = 0;
        !          1387:                                }
        !          1388:                                break;
        !          1389:                        }
        !          1390:                        else {
        !          1391:                                clr_to_eol();
        !          1392:                        }
        !          1393:                }
        !          1394:        }
        !          1395: }
        !          1396: 
        !          1397: Hidden Procedure
        !          1398: clr_to_eol()
        !          1399: {
        !          1400:        lenline[cur_y] = cur_x;
        !          1401:        if (!has_xs && so_mode != Off)
        !          1402:                standend();
        !          1403:        Putstr(ce_str);
        !          1404:        if (has_xs) {
        !          1405:                if (cur_x == 0)
        !          1406:                        line[cur_y][0] = NOCOOK;
        !          1407:                else if (line[cur_y][cur_x-1]&SOBIT)
        !          1408:                        standend();
        !          1409:        }
        !          1410: }
        !          1411: 
        !          1412: Hidden Procedure
        !          1413: set_blanks
        !          1414: (y, xfrom, xto)
        !          1415: int y, xfrom, xto;
        !          1416: {
        !          1417:        register int x;
        !          1418:        
        !          1419:        for (x = xfrom; x < xto; x++) {
        !          1420:                line[y][x] = (line[y][x]&XSBIT) | ' ';
        !          1421:        }
        !          1422: }
        !          1423: 
        !          1424: /* 
        !          1425:  * outchar() is used by termcap's tputs;
        !          1426:  * we can't use putchar because that's probably a macro
        !          1427:  */
        !          1428: Hidden int
        !          1429: outchar(ch)
        !          1430: char ch;
        !          1431: {
        !          1432:        putchar(ch);
        !          1433: }
        !          1434: 
        !          1435: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !          1436: /* Scrolling (part of) the screen up (or down, dy<0).                       */
        !          1437: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !          1438: 
        !          1439: Visible Procedure
        !          1440: trmscrollup(yfirst, ylast, by)
        !          1441: register int yfirst;
        !          1442: register int ylast;
        !          1443: register int by;
        !          1444: {
        !          1445: #ifdef TRACE
        !          1446: fprintf(stderr, "\ttrmscrollup(%d, %d, %d);\n", yfirst, ylast, by);
        !          1447: #endif
        !          1448:        check_started("trmscrollup");
        !          1449:        
        !          1450:        if (yfirst < 0)
        !          1451:                yfirst = 0;
        !          1452:        if (ylast >= lines)
        !          1453:                ylast = lines-1;
        !          1454: 
        !          1455:        if (yfirst > ylast)
        !          1456:                return;
        !          1457: 
        !          1458:        if (!has_xs && so_mode != Off)
        !          1459:                standend();
        !          1460:        
        !          1461:        if (by > 0 && yfirst + by > ylast
        !          1462:            ||
        !          1463:            by < 0 && yfirst - by > ylast)
        !          1464:        {
        !          1465:                clear_lines(yfirst, ylast);
        !          1466:                return;
        !          1467:        }
        !          1468:        
        !          1469:        if (by > 0) {
        !          1470:                (*scr_up)(yfirst, ylast, by);
        !          1471:                scr_lines(yfirst, ylast, by, 1);
        !          1472:        }
        !          1473:        else if (by < 0) {
        !          1474:                (*scr_down)(yfirst, ylast, -by);
        !          1475:                scr_lines(ylast, yfirst, -by, -1);
        !          1476:        }
        !          1477: }
        !          1478: 
        !          1479: Hidden Procedure
        !          1480: scr_lines(yfrom, yto, n, dy)
        !          1481: int yfrom, yto, n, dy;
        !          1482: {
        !          1483:        register int y;
        !          1484:        intlet *saveln;
        !          1485:        
        !          1486:        while (n-- > 0) {
        !          1487:                saveln = line[yfrom];
        !          1488:                for (y = yfrom; y != yto; y += dy) {
        !          1489:                        line[y] = line[y+dy];
        !          1490:                        lenline[y] = lenline[y+dy];
        !          1491:                }
        !          1492:                line[yto] = saveln;
        !          1493:                lenline[yto] = 0;
        !          1494:                if (has_xs) line[yto][0] = NOCOOK;
        !          1495:        }
        !          1496: }
        !          1497: 
        !          1498: Hidden Procedure
        !          1499: scr1up(yfirst, ylast, n)
        !          1500:        int yfirst;
        !          1501:        int ylast;
        !          1502:        int n;
        !          1503: {
        !          1504:        move(yfirst, 0);
        !          1505:        dellines(n);
        !          1506:        if (ylast < lines-1) {
        !          1507:                move(ylast-n+1, 0);
        !          1508:                addlines(n);
        !          1509:        }
        !          1510: }
        !          1511: 
        !          1512: Hidden Procedure
        !          1513: scr1down(yfirst, ylast, n)
        !          1514:        int yfirst;
        !          1515:        int ylast;
        !          1516:        int n;
        !          1517: {
        !          1518:        if (ylast == lines-1) {
        !          1519:                clear_lines(ylast-n+1, ylast);
        !          1520:        }
        !          1521:        else {
        !          1522:                move(ylast-n+1, 0);
        !          1523:                dellines(n);
        !          1524:        }
        !          1525:        move(yfirst, 0);
        !          1526:        addlines(n);
        !          1527: }
        !          1528: 
        !          1529: Hidden Procedure
        !          1530: addlines(n)
        !          1531: register int n;
        !          1532: {
        !          1533:        if (par_al_str && n > 1)
        !          1534:                        Putstr(tgoto(par_al_str, n, n));
        !          1535:        else {
        !          1536:                while (n-- > 0)
        !          1537:                        Putstr(al_str);
        !          1538:        }
        !          1539: }
        !          1540: 
        !          1541: Hidden Procedure
        !          1542: dellines(n)
        !          1543: register int n;
        !          1544: {
        !          1545:        if (par_dl_str && n > 1)
        !          1546:                Putstr(tgoto(par_dl_str, n, n));
        !          1547:        else {
        !          1548:                while (n-- > 0)
        !          1549:                        Putstr(dl_str);
        !          1550:        }
        !          1551: }
        !          1552: 
        !          1553: Hidden Procedure
        !          1554: scr2up(yfirst, ylast, n)
        !          1555: int yfirst, ylast, n;
        !          1556: {
        !          1557:        Putstr(tgoto(cs_str, ylast, yfirst));
        !          1558:        cur_y = cur_x = Undefined;
        !          1559:        move(ylast, 0);
        !          1560:        while (n-- > 0) {
        !          1561:                Putstr(sf_str);
        !          1562:                if (has_db && ylast == lines-1)
        !          1563:                        clr_to_eol();
        !          1564:        }
        !          1565:        Putstr(tgoto(cs_str, lines-1, 0));
        !          1566:        cur_y = cur_x = Undefined;
        !          1567: }
        !          1568: 
        !          1569: Hidden Procedure
        !          1570: scr2down(yfirst, ylast, n)
        !          1571: int yfirst, ylast, n;
        !          1572: {
        !          1573:        Putstr(tgoto(cs_str, ylast, yfirst));
        !          1574:        cur_y = cur_x = Undefined;
        !          1575:        move(yfirst, 0);
        !          1576:        while (n-- > 0) {
        !          1577:                Putstr(sr_str);
        !          1578:                if (has_da && yfirst == 0)
        !          1579:                        clr_to_eol();
        !          1580:        }
        !          1581:        Putstr(tgoto(cs_str, lines-1, 0));
        !          1582:        cur_y = cur_x = Undefined;
        !          1583: }
        !          1584: 
        !          1585: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !          1586: /* Synchronization, move cursor to given position (or previous if < 0).     */
        !          1587: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !          1588: 
        !          1589: Visible Procedure
        !          1590: trmsync(y, x)
        !          1591:        int y;
        !          1592:        int x;
        !          1593: {
        !          1594: #ifdef TRACE
        !          1595: fprintf(stderr, "\ttrmsync(%d, %d);\n", y, x);
        !          1596: #endif
        !          1597:        check_started("trmsync");
        !          1598:        
        !          1599:        if (0 <= y && y < lines && 0 <= x && x < cols) {
        !          1600:                move(y, x);
        !          1601:                if (no_cursor) {
        !          1602:                        Putstr(ve_str);
        !          1603:                        no_cursor = No;
        !          1604:                }
        !          1605:        }
        !          1606:        else if (no_cursor == No) {
        !          1607:                Putstr(vi_str);
        !          1608:                no_cursor = Yes;
        !          1609:        }
        !          1610:        VOID fflush(stdout);
        !          1611: }
        !          1612: 
        !          1613: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !          1614: /* Send a bell, visible if possible.                                        */
        !          1615: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !          1616: 
        !          1617: Visible Procedure
        !          1618: trmbell()
        !          1619: {
        !          1620: #ifdef TRACE
        !          1621: fprintf(stderr, "\ttrmbell();\n");
        !          1622: #endif
        !          1623:        check_started("trmbell");
        !          1624:        
        !          1625:        Putstr(vb_str);
        !          1626:        VOID fflush(stdout);
        !          1627: }
        !          1628: 
        !          1629: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !          1630: /* Show the current internal statuses of the screen on stderr.              */
        !          1631: /* For debugging only.                                                      */
        !          1632: /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
        !          1633: 
        !          1634: #ifdef SHOW
        !          1635: Visible Procedure
        !          1636: trmshow(s)
        !          1637: char *s;
        !          1638: {
        !          1639:        int y, x;
        !          1640:        
        !          1641:        fprintf(stderr, "<<< %s >>>\n", s);
        !          1642:        for (y = 0; y < lines; y++) {
        !          1643:                for (x = 0; x <= lenline[y] /*** && x < cols-1 ***/ ; x++) {
        !          1644:                        fputc(line[y][x]&CHAR, stderr);
        !          1645:                }
        !          1646:                fputc('\n', stderr);
        !          1647:                for (x = 0; x <= lenline[y] && x < cols-1; x++) {
        !          1648:                        if (line[y][x]&SOBIT)
        !          1649:                                fputc('-', stderr);
        !          1650:                        else
        !          1651:                                fputc(' ', stderr);
        !          1652:                }
        !          1653:                fputc('\n', stderr);
        !          1654:                for (x = 0; x <= lenline[y] && x < cols-1; x++) {
        !          1655:                        if (line[y][x]&XSBIT)
        !          1656:                                fputc('+', stderr);
        !          1657:                        else
        !          1658:                                fputc(' ', stderr);
        !          1659:                }
        !          1660:                fputc('\n', stderr);
        !          1661:        }
        !          1662:        fprintf(stderr, "CUR_Y = %d, CUR_X = %d.\n", cur_y, cur_x);
        !          1663:        VOID fflush(stderr);
        !          1664: }
        !          1665: #endif

unix.superglobalmegacorp.com

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