Annotation of coherent/g/usr/bin/me/display.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * The functions in this file handle redisplay.
                      3:  * There are two halves, the ones that update the virtual display screen,
                      4:  * and the ones that make the physical display screen the same as the virtual
                      5:  * display screen.  These functions use hints that are left in the windows by
                      6:  * the commands.
                      7:  */
                      8: #include       <stdio.h>
                      9: #include       "ed.h"
                     10: 
                     11: #define        WFDEBUG 0                       /* Window flag debug.           */
                     12: #define        FASTHACK        1               /* Slightly faster update code  */
                     13: 
                     14: typedef        struct  VIDEO {
                     15:        short   v_flag;                 /* Flags                        */
                     16:        uchar   v_text[];               /* Screen data.                 */
                     17: }      VIDEO;
                     18: 
                     19: #define        VFCHG   0x0001                  /* Changed.                     */
                     20: #define        VFSTD   0x0002                  /* Standout.                    */
                     21: 
                     22: int    sgarbf  = TRUE;                 /* TRUE if screen is garbage    */
                     23: int    mpresf  = FALSE;                /* TRUE if message in last line */
                     24: int    vtrow   = 0;                    /* Row location of SW cursor    */
                     25: int    vtcol   = 0;                    /* Column location of SW cursor */
                     26: int    ttrow   = HUGE;                 /* Row location of HW cursor    */
                     27: int    ttcol   = HUGE;                 /* Column location of HW cursor */
                     28: VIDEO  **vscreen;                      /* Virtual screen.              */
                     29: VIDEO  **pscreen;                      /* Physical screen.             */
                     30: 
                     31: /*
                     32:  * Initialize the data structures used by the display code.
                     33:  * The edge vectors used to access the screens are set up.
                     34:  * The operating system's terminal I/O channel is set up.
                     35:  * All the other things get initialized at compile time.
                     36:  * The original window has "WFCHG" set, so that it will get
                     37:  * completely redrawn on the first call to "update".
                     38:  */
                     39: vtinit()
                     40: {
                     41:        register int    i;
                     42:        register VIDEO  *vp;
                     43: 
                     44:        vscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
                     45:        if (vscreen == NULL)
                     46:                abort();
                     47:        pscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
                     48:        if (pscreen == NULL)
                     49:                abort();
                     50:        for (i=0; i<term.t_nrow; ++i) {
                     51:                vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol);
                     52:                if (vp == NULL)
                     53:                        abort();
                     54:                vscreen[i] = vp;
                     55:                vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol);
                     56:                if (vp == NULL)
                     57:                        abort();
                     58:                pscreen[i] = vp;
                     59:        }
                     60: }
                     61: 
                     62: /*
                     63:  * Clean up the virtual terminal system, in anticipation for a return to the
                     64:  * operating system.  Move down to the last line and clear it out (the next
                     65:  * system prompt will be written in the line).  Shut down the channel to the
                     66:  * terminal.
                     67:  */
                     68: vttidy()
                     69: {
                     70:        movecursor(term.t_nrow, 0);
                     71:        teeol();
                     72:        tstand(0);
                     73:        tclose();
                     74: }
                     75: 
                     76: /*
                     77:  * Set the virtual cursor to the specified row and column on the
                     78:  * virtual screen.  There is no checking for nonsense values; this might
                     79:  * be a good idea during the early stages.
                     80:  */
                     81: vtmove(row, col)
                     82: {
                     83:        vtrow = row;
                     84:        vtcol = col;
                     85: }
                     86: 
                     87: /*
                     88:  * If bind.dispmode == 1 chars < ' ' are displayed directly
                     89:  * else they are displayed whit preceeding ^ and ^= '@'
                     90:  */
                     91: displaymod()
                     92: {
                     93:        bind.dispmode ^= 1;
                     94: }
                     95: 
                     96: /*
                     97:  * Return 2 if char is tab 1 if it needs ^ for ansi emulation.
                     98:  */
                     99: dblchr(c)
                    100: register unsigned c;
                    101: {
                    102:        if (bind.dispmode) {
                    103:                switch(c) {
                    104:                case '\n':
                    105:                case '\f':
                    106:                case '\r':
                    107:                case 0x1b:
                    108:                        return (1);
                    109:                case '\t':
                    110:                        return (2);
                    111:                }
                    112:                return (0);
                    113:        }
                    114:        return (((c < ' ') || (c == 0x7f)) ? ((c == '\t') ? 2 : 1) : 0);
                    115: }
                    116: 
                    117: /*
                    118:  * Write a character to the virtual screen.  The virtual row and
                    119:  * column are updated.  If the line is too long put a "$" in the last column.
                    120:  * This routine only puts printing characters into the virtual terminal buffers.
                    121:  * Only column overflow is checked.
                    122:  */
                    123: vtputc(c)
                    124: unsigned c;
                    125: {
                    126:        register VIDEO  *vp;
                    127: 
                    128:        vp = vscreen[vtrow];
                    129:        switch (dblchr(c)) {
                    130:        case 0:         /* normal character */
                    131:                if (vtcol >= term.t_ncol)
                    132:                        vp->v_text[term.t_ncol - 1] = '$';
                    133:                else
                    134:                        vp->v_text[vtcol++] = c;
                    135:                break;
                    136:        case 2:         /* tab */
                    137:                do {
                    138:                        if (vtcol >= term.t_ncol) {
                    139:                                vp->v_text[term.t_ncol - 1] = '$';
                    140:                                break;
                    141:                        } else
                    142:                                vp->v_text[vtcol++] = ' ';              
                    143:                } while (vtcol % bind.tabsiz);
                    144:                break;
                    145:        case 1:         /* needs ^ */
                    146:                vtputc('^');
                    147:                vtputc(c ^ 0x40);
                    148:                break;
                    149:        }
                    150: }
                    151: 
                    152: /*
                    153:  * Erase from the end of the software cursor to the end of the line on which
                    154:  * the software cursor is located.
                    155:  */
                    156: vteeol()
                    157: {
                    158:        register VIDEO  *vp;
                    159: 
                    160:        vp = vscreen[vtrow];
                    161:        while (vtcol < term.t_ncol)
                    162:                vp->v_text[vtcol++] = ' ';
                    163: }
                    164: 
                    165: /*
                    166:  * Make sure that the display is right.  This is a three part process.
                    167:  * First, scan through all of the windows looking for dirty ones.
                    168:  * Check the framing, and refresh the screen.
                    169:  * Second, make sure that "currow" and "curcol" are correct for the current
                    170:  * window.
                    171:  * Third, make the virtual and physical screens the same.
                    172:  */
                    173: update()
                    174: {
                    175:        register LINE   *lp;
                    176:                 LINE   *xlp;
                    177:        register WINDOW *wp;
                    178:        register VIDEO  *vp1;
                    179:        register VIDEO  *vp2;
                    180:        register int    i;
                    181:        register int    j;
                    182: 
                    183:        wp = wheadp;
                    184:        while (wp != NULL) {
                    185:                /* Look at any window with update flags set on.         */
                    186:                if (wp->w_flag != 0) {
                    187:                        /* If not force reframe, check the framing.     */
                    188:                        if ((wp->w_flag&WFFORCE) == 0) {
                    189:                                lp = wp->w_linep;
                    190:                                for (i=0; i<wp->w_ntrows; ++i) {
                    191:                                        if (lp == wp->w_dotp)
                    192:                                                goto out;
                    193:                                        if (lp == wp->w_bufp->b_linep)
                    194:                                                break;
                    195:                                        lp = lforw(lp);
                    196:                                }
                    197:                        }
                    198:                        /* Not acceptable, better compute a new value   */
                    199:                        /* for the line at the top of the window. Then  */
                    200:                        /* set the "WFHARD" flag to force full redraw.  */
                    201:                        i = wp->w_force;
                    202:                        if (i > 0) {
                    203:                                --i;
                    204:                                if (i >= wp->w_ntrows)
                    205:                                        i = wp->w_ntrows-1;
                    206:                        } else if (i < 0) {
                    207:                                i += wp->w_ntrows;
                    208:                                if (i < 0)
                    209:                                        i = 0;
                    210:                        } else
                    211:                                i = wp->w_ntrows/2;
                    212:                        lp = wp->w_dotp;
                    213:                        while (i!=0 && lback(lp)!=wp->w_bufp->b_linep) {
                    214:                                --i;
                    215:                                lp = lback(lp);
                    216:                        }
                    217:                        wp->w_linep = lp;
                    218:                        wp->w_flag |= WFHARD;   /* Force full.          */
                    219:                out:
                    220:                        /* Try to use reduced update. Mode line update  */
                    221:                        /* has its own special flag. The fast update is */
                    222:                        /* used if the only thing to do is within the   */
                    223:                        /* line editing.                                */
                    224:                        lp = wp->w_linep;
                    225:                        i  = wp->w_toprow;
                    226:                        if ((wp->w_flag&~WFMODE) == WFEDIT) {
                    227:                                while (lp != wp->w_dotp) {
                    228:                                        ++i;
                    229:                                        lp = lforw(lp);
                    230:                                }
                    231: #ifdef FASTHACK
                    232:                                vscreen[i]->v_flag = VFCHG;
                    233: #else
                    234:                                vscreen[i]->v_flag |= VFCHG;
                    235:                                vscreen[i]->v_flag &= ~VFSTD;
                    236: #endif
                    237:                                vtmove(i, 0);
                    238:                                for (j=0; j<llength(lp); ++j)
                    239:                                        vtputc(lgetc(lp, j));
                    240:                                vteeol();
                    241:                        } else if ((wp->w_flag&(WFEDIT|WFHARD)) != 0) {
                    242:                                while (i < wp->w_toprow+wp->w_ntrows) {
                    243: #ifdef FASTHACK
                    244:                                        vscreen[i]->v_flag = VFCHG;
                    245: #else
                    246:                                        vscreen[i]->v_flag |= VFCHG;
                    247:                                        vscreen[i]->v_flag &= ~VFSTD;
                    248: #endif
                    249:                                        vtmove(i, 0);
                    250:                                        if (lp != wp->w_bufp->b_linep) {
                    251:                                                for (j=0; j<llength(lp); ++j)
                    252:                                                        vtputc(lgetc(lp, j));
                    253:                                                lp = lforw(lp);
                    254:                                        }
                    255:                                        vteeol();
                    256:                                        ++i;
                    257:                                }
                    258:                        }
                    259: #if    !WFDEBUG
                    260:                        if ((wp->w_flag&WFMODE) != 0)
                    261:                                modeline(wp);
                    262:                        wp->w_flag  = 0;
                    263:                        wp->w_force = 0;
                    264: #endif
                    265:                }               
                    266: #if    WFDEBUG
                    267:                modeline(wp);
                    268:                wp->w_flag =  0;
                    269:                wp->w_force = 0;
                    270: #endif
                    271:                /* Set standout mode on status line... */
                    272:                vscreen[wp->w_toprow+wp->w_ntrows]->v_flag |= VFSTD;
                    273:                wp = wp->w_wndp;
                    274:        }
                    275:        /* Always recompute the row and column number of the hardware   */
                    276:        /* cursor.  This is the only update for simple moves.           */
                    277:        xlp = lp = curwp->w_linep;
                    278:        currow = curwp->w_toprow;
                    279:        while (lp != curwp->w_dotp) {
                    280:                ++currow;
                    281:                if (xlp == (lp = lforw(lp))) {  /* Fix infinite loop problem */
                    282:                        currow = curwp->w_toprow;
                    283:                        curwp->w_dotp = lp = xlp;
                    284:                        curwp->w_doto = 0;
                    285:                        break;
                    286:                }
                    287:        }
                    288:        curcol = truecol(lp, curwp->w_doto);
                    289: 
                    290: #if    GEM && NATIVE
                    291:        /* Special preparation for screen update on ATARI ST native screen */
                    292:        /* We shut off the cursor -- This speeds up the writing of text */
                    293:        /* quite a bit.                                                 */
                    294: 
                    295:        astcursor(0);                   /* Turn cursor off for update   */
                    296: #endif
                    297: 
                    298:        /* Special hacking if the screen is garbage. Clear the hardware */
                    299:        /* screen, and update your copy to agree with it. Set all the   */
                    300:        /* virtual screen change bits, to force a full update.          */
                    301: 
                    302:        if (sgarbf != FALSE) {
                    303:                for (i=0; i<term.t_nrow; ++i) {
                    304:                        vscreen[i]->v_flag |= VFCHG;
                    305:                        vp1 = pscreen[i];
                    306:                        for (j=0; j<term.t_ncol; ++j)
                    307:                                vp1->v_text[j] = ' ';
                    308:                }
                    309:                teeop();                        /* Erase the screen.    */
                    310:                sgarbf = FALSE;                 /* Erase-page clears    */
                    311:                mpresf = FALSE;                 /* the message area.    */
                    312:        }
                    313: 
                    314:        /* Make sure that the physical and virtual displays agree.      */
                    315:        /* Unlike before, the "updateline" code is only called with a   */
                    316:        /* line that has been updated for sure.                         */
                    317: 
                    318:        for (i=0; i<term.t_nrow; ++i) {
                    319:                vp1 = vscreen[i];
                    320:                if ((vp1->v_flag&VFCHG) != 0) {
                    321:                        vp2 = pscreen[i];
                    322:                        if ((vp1->v_flag&VFSTD) != 0) { /* Standout mode */
                    323: #ifndef        FASTHACK
                    324:                                vp1->v_flag &= ~VFSTD;
                    325: #endif
                    326:                                tstand(1);
                    327:                                updateline(i, &vp1->v_text[0], &vp2->v_text[0]);
                    328:                                tstand(0);
                    329:                        } else
                    330:                                updateline(i, &vp1->v_text[0], &vp2->v_text[0]);
                    331: #ifdef FASTHACK
                    332:                        vp1->v_flag = 0;
                    333: #else
                    334:                        vp1->v_flag &= ~VFCHG;
                    335: #endif
                    336:                }
                    337:        }
                    338:        /* Finally, update the hardware cursor and flush out buffers.   */
                    339:        bracketmode(currow, curcol);
                    340: #if    GEM && NATIVE
                    341:        astcursor(1);                   /* Turn cursor back on...       */
                    342: #endif
                    343:        tflush();
                    344: }
                    345: 
                    346: /*
                    347:  * Update a single line.  This does not know how to use insert or delete
                    348:  * character sequences; we are using VT52 functionality.  Update the physical
                    349:  * row and column variables.  It does try and exploit erase to end of line.
                    350:  * The RAINBOW version of this routine uses fast video.
                    351:  */
                    352: updateline(row, vline, pline)
                    353: uchar  vline[];
                    354: uchar  pline[];
                    355: {
                    356: #if    RAINBOW|IBM
                    357:        register uchar  *cp1;
                    358:        register uchar  *cp2;
                    359:        register int    nch;
                    360: 
                    361:        cp1 = &vline[0];                        /* Use fast video.      */
                    362:        cp2 = &pline[0];
                    363:        putline(row+1, 1, cp1);
                    364:        nch = term.t_ncol;
                    365:        do {
                    366:                *cp2 = *cp1;
                    367:                ++cp2;
                    368:                ++cp1;
                    369:        } while (--nch);
                    370: #else
                    371:        register uchar  *cp1;
                    372:        register uchar  *cp2;
                    373:        register uchar  *cp3;
                    374:        register uchar  *cp4;
                    375:        register uchar  *cp5;
                    376:        register int    nbflag;
                    377: 
                    378:        cp1 = &vline[0];                        /* Compute left match.  */
                    379:        cp2 = &pline[0];
                    380:        while (cp1!=&vline[term.t_ncol] && cp1[0]==cp2[0]) {
                    381:                ++cp1;
                    382:                ++cp2;
                    383:        }
                    384:        /* This can still happen, even though we only call this routine */
                    385:        /* on changed lines. A hard update is always done when a line   */
                    386:        /* splits, a massive change is done, or a buffer is displayed   */
                    387:        /* twice. This optimizes out most of the excess updating. A lot */
                    388:        /* of computes are used, but these tend to be hard operations   */
                    389:        /* that do a lot of update, so I don't really care.             */
                    390:        if (cp1 == &vline[term.t_ncol])         /* All equal.           */
                    391:                return;
                    392:        nbflag = FALSE;
                    393:        cp3 = &vline[term.t_ncol];              /* Compute right match. */
                    394:        cp4 = &pline[term.t_ncol];
                    395:        while (cp3[-1] == cp4[-1]) {
                    396:                --cp3;
                    397:                --cp4;
                    398:                if (cp3[0] != ' ')              /* Note if any nonblank */
                    399:                        nbflag = TRUE;          /* in right match.      */
                    400:        }
                    401:        cp5 = cp3;
                    402:        if (nbflag == FALSE) {                  /* Erase to EOL ?       */
                    403:                while (cp5!=cp1 && cp5[-1]==' ')
                    404:                        --cp5;
                    405:                if (cp3-cp5 <= 3)               /* Use only if erase is */
                    406:                        cp5 = cp3;              /* fewer characters.    */
                    407:        }
                    408:        movecursor(row, (int)(cp1-&vline[0]));  /* Go to start of line. */
                    409:        while (cp1 != cp5) {                    /* Ordinary.            */
                    410:                tputc(*cp1);
                    411:                ++ttcol;
                    412:                *cp2++ = *cp1++;
                    413:        }
                    414:        if (cp5 != cp3) {                       /* Erase.               */
                    415:                teeol();
                    416:                while (cp1 != cp3)
                    417:                        *cp2++ = *cp1++;
                    418:        }
                    419: #endif
                    420: }
                    421: 
                    422: /*
                    423:  * Redisplay the mode line for the window pointed to by the "wp".
                    424:  * This is the only routine that has any idea of how the modeline is formatted.
                    425:  * You can change the modeline format by hacking at this routine.
                    426:  * Called by "update" any time there is a dirty window.
                    427:  */
                    428: modeline(wp)
                    429: register WINDOW        *wp;
                    430: {
                    431:        register uchar  *cp;
                    432:        register int    c;
                    433:        register int    n;
                    434:        register BUFFER *bp;
                    435: 
                    436:        n = wp->w_toprow+wp->w_ntrows;          /* Location.            */
                    437:        vscreen[n]->v_flag |= VFCHG;            /* Redraw next time.    */
                    438:        vtmove(n, 0);                           /* Seek to right line.  */
                    439:        vtputc('-');
                    440:        bp = wp->w_bufp;
                    441:        if ((bp->b_flag&BFCHG) != 0)            /* "*" if changed.      */
                    442:                vtputc('*');
                    443:        else
                    444:                vtputc('-');
                    445:        n  = 2;
                    446:        cp = PROMPT;                            /* Buffer name.         */
                    447:        while ((c = *cp++) != 0) {
                    448:                vtputc(c);
                    449:                ++n;
                    450:        }
                    451:        cp = &bp->b_bname[0];
                    452:        while ((c = *cp++) != 0) {
                    453:                vtputc(c);
                    454:                ++n;
                    455:        }
                    456:        vtputc(' ');
                    457:        ++n;
                    458:        if (bp->b_fname[0] != 0) {              /* File name.           */
                    459: #if    LIBHELP
                    460:                if (bp->b_flag & BFHELP)
                    461:                        cp = "- Subject: ";
                    462:                else
                    463: #endif
                    464:                        cp = "-- File: ";
                    465:                while ((c = *cp++) != 0) {
                    466:                        vtputc(c);
                    467:                        ++n;
                    468:                }
                    469:                cp = &bp->b_fname[0];
                    470:                while ((c = *cp++) != 0) {
                    471:                        vtputc(c);
                    472:                        ++n;
                    473:                }
                    474:                vtputc(' ');
                    475:                ++n;
                    476:        }
                    477: #if    WFDEBUG
                    478:        vtputc('-');
                    479:        vtputc((wp->w_flag&WFMODE)!=0  ? 'M' : '-');
                    480:        vtputc((wp->w_flag&WFHARD)!=0  ? 'H' : '-');
                    481:        vtputc((wp->w_flag&WFEDIT)!=0  ? 'E' : '-');
                    482:        vtputc((wp->w_flag&WFMOVE)!=0  ? 'V' : '-');
                    483:        vtputc((wp->w_flag&WFFORCE)!=0 ? 'F' : '-');
                    484:        n += 6;
                    485: #endif
                    486:        while (n < term.t_ncol) {               /* Pad to full width.   */
                    487:                vtputc('-');
                    488:                ++n;
                    489:        }
                    490: }
                    491: 
                    492: /*
                    493:  * Send a command to the terminal to move the hardware cursor to row "row"
                    494:  * and column "col".  The row and column arguments are origin 0.
                    495:  * Optimize out random calls.  Update "ttrow" and "ttcol".
                    496:  */
                    497: movecursor(row, col)
                    498: {
                    499:        if (row!=ttrow || col!=ttcol) {
                    500:                ttrow = row;
                    501:                ttcol = col;
                    502:                tmove(row, col);
                    503:        }
                    504: }
                    505: 
                    506: /*
                    507:  * Erase the message line.
                    508:  * This is a special routine because the message line is not considered to be
                    509:  * part of the virtual screen.  It always works immediately; the terminal
                    510:  * buffer is flushed via a call to the flusher.
                    511:  */
                    512: mlerase()
                    513: {
                    514:        movecursor(term.t_nrow, 0);
                    515:        teeol();
                    516:        tflush();
                    517:        mpresf = FALSE;
                    518: }
                    519: 
                    520: /*
                    521:  * Ask a yes or no question in the message line.
                    522:  * Return either TRUE, FALSE, or ABORT.  The ABORT status is returned
                    523:  * if the user bumps out of the question with a ^G.
                    524:  * Used any time a confirmation is required.
                    525:  */
                    526: mlyesno(prompt)
                    527: uchar  *prompt;
                    528: {
                    529:        register int    s;
                    530:        uchar           buf[64];
                    531: 
                    532:        for (;;) {
                    533:                strcpy(buf, prompt);
                    534:                strcat(buf, " [y/n]? ");
                    535:                s = mlreply(buf, buf, sizeof(buf));
                    536:                if (s == ABORT)
                    537:                        return (ABORT);
                    538:                if (s != FALSE) {
                    539:                        if (buf[0]=='y' || buf[0]=='Y')
                    540:                                return (TRUE);
                    541:                        if (buf[0]=='n' || buf[0]=='N')
                    542:                                return (FALSE);
                    543:                }
                    544:        }
                    545: }
                    546: 
                    547: /*
                    548:  * Write a prompt into the message line, then read back a response.
                    549:  * Keep track of the physical position of the cursor.
                    550:  * If we are in a keyboard macro throw the prompt away, and return
                    551:  * the remembered response.  This lets macros run at full speed.
                    552:  * The reply is always terminated by a carriage return.
                    553:  * Handle erase, kill, and abort keys.
                    554:  */
                    555: mlreply(prompt, buf, nbuf)
                    556: uchar  *prompt;
                    557: uchar  *buf;
                    558: {
                    559:        register int    cpos;
                    560:        register int    i;
                    561:        register int    c;
                    562: 
                    563:        cpos = 0;
                    564:        if (kbdmop != NULL) {
                    565:                while ((c = *kbdmop++) != '\0')
                    566:                        buf[cpos++] = c;
                    567:                buf[cpos] = 0;
                    568:                if (buf[0] == 0)
                    569:                        return (FALSE);
                    570:                return (TRUE);
                    571:        }
                    572:        mlwrite(prompt);
                    573:        for (;;) {
                    574:                c = tgetc();
                    575:                switch (c) {
                    576:                case 0x0D:                      /* Return, end of line  */
                    577:                        buf[cpos++] = 0;
                    578:                        if (kbdmip != NULL) {
                    579:                                if ((kbdmip+cpos) > (kbdm + ((NKBDM - 3)/2))) {
                    580:                                        ctrlg(FALSE, 0);
                    581:                                        tflush();
                    582:                                        return (ABORT);
                    583:                                }
                    584:                                for (i=0; i<cpos; ++i)
                    585:                                        *kbdmip++ = buf[i];
                    586:                        }
                    587:                        tputc('\r');
                    588:                        ttcol = 0;
                    589:                        tflush();
                    590:                        if (buf[0] == 0)
                    591:                                return (FALSE);
                    592:                        return (TRUE);
                    593: 
                    594:                case 0x07:                      /* Bell, abort          */
                    595:                        tputc('^');
                    596:                        tputc('G');
                    597:                        ttcol += 2;
                    598:                        ctrlg(FALSE, 0);
                    599:                        tflush();
                    600:                        return (ABORT);
                    601: 
                    602:                case 0x7f:                      /* Rubout, erase        */
                    603:                case 0x08:                      /* Backspace, erase     */
                    604:                        if (cpos != 0) {
                    605:                                tputc('\b');
                    606:                                tputc(' ');
                    607:                                tputc('\b');
                    608:                                --ttcol;
                    609:                                if (buf[--cpos] < 0x20) {
                    610:                                        tputc('\b');
                    611:                                        tputc(' ');
                    612:                                        tputc('\b');
                    613:                                        --ttcol;
                    614:                                }
                    615:                                tflush();
                    616:                        }
                    617:                        break;
                    618: 
                    619:                case 0x15:                      /* C-U, kill            */
                    620:                        while (cpos != 0) {
                    621:                                tputc('\b');
                    622:                                tputc(' ');
                    623:                                tputc('\b');
                    624:                                --ttcol;
                    625:                                if (buf[--cpos] < 0x20) {
                    626:                                        tputc('\b');
                    627:                                        tputc(' ');
                    628:                                        tputc('\b');
                    629:                                        --ttcol;
                    630:                                }
                    631:                        }
                    632:                        tflush();
                    633:                        break;
                    634: 
                    635:                default:
                    636:                        if (cpos < nbuf-1) {
                    637:                                buf[cpos++] = c;
                    638:                                if (c < ' ') {
                    639:                                        tputc('^');
                    640:                                        ++ttcol;
                    641:                                        c ^= 0x40;
                    642:                                }
                    643:                                tputc(c);
                    644:                                ++ttcol;
                    645:                                tflush();
                    646:                        }
                    647:                }
                    648:        }
                    649: }
                    650: 
                    651: /*
                    652:  * Write a message into the message line.
                    653:  * Keep track of the physical cursor position.
                    654:  * A small class of printf like format items is handled.
                    655:  * Assumes the stack grows down; this assumption is made by the "++"
                    656:  * in the argument scan loop.  Set the "message line" flag TRUE.
                    657:  */
                    658: mlwrite(fmt)
                    659: uchar  *fmt;
                    660: {
                    661:        register int    c;
                    662:        
                    663:        uchar buf[NPAT * 2];
                    664: 
                    665:        movecursor(term.t_nrow, 0);
                    666:        sprintf(buf, "%r", &fmt);
                    667:        if (strlen(buf) > (term.t_ncol - 1))
                    668:                buf[term.t_ncol - 1] = 0;
                    669:        for (fmt = buf; c = *fmt; fmt++) {
                    670:                tputc(c);
                    671:                ++ttcol;
                    672:        }
                    673:        teeol();
                    674:        tflush();
                    675:        mpresf = TRUE;
                    676: }
                    677: 
                    678: /*
                    679:  * Write out a string.
                    680:  * Update the physical cursor position.  This assumes that the characters in the
                    681:  * string all have width "1"; if this is not the case things will get screwed up
                    682:  * a little.
                    683:  */
                    684: mlputs(s)
                    685: register uchar *s;
                    686: {
                    687:        register int    c;
                    688: 
                    689:        while ((c = *s++) != 0) {
                    690:                tputc(c);
                    691:                ++ttcol;
                    692:        }
                    693: }
                    694: 
                    695: /*
                    696:  * find the logical cursor. Return line from top of
                    697:  * window.
                    698:  */
                    699: locatecursor(what)
                    700: LINE *what;
                    701: {
                    702:        int row;
                    703:        LINE *clp;
                    704: 
                    705:        row = 0;
                    706:        for (clp = curwp->w_linep; clp != what; clp = lforw(clp)) {
                    707:                if ((clp == curbp->b_linep) || (row > curwp->w_ntrows))
                    708:                        return (-1);
                    709:                row++;
                    710:        }
                    711:        return (row + curwp->w_toprow);
                    712: }
                    713: 
                    714: /*
                    715:  * turn LINE and char pointer into display col.
                    716:  */
                    717: truecol(clp, col)
                    718: LINE *clp;
                    719: {
                    720:        register int i, tcol;
                    721:        unsigned c;
                    722: 
                    723:        for (i = tcol = 0; i < col; i++) {
                    724:                c = lgetc(clp, i);
                    725:                switch (dblchr(c)) {
                    726:                case 2:
                    727:                        taber(tcol);
                    728:                        break;
                    729:                case 1:
                    730:                        tcol++;
                    731:                }
                    732:                tcol++;
                    733:        }
                    734:        if (tcol >= term.t_ncol)        /* too far out */
                    735:                tcol = term.t_ncol - 1;
                    736:        return (tcol);
                    737: }

unix.superglobalmegacorp.com

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