Metropoli BBS
VIEWER: ansi.c MODE: TEXT (ASCII)
/*
Copyright (C) Magna Carta Software, Inc. 1988-1991.  All Rights Reserved
C COMMUNICATIONS TOOLKIT
ANSI.C -- X3.64 terminal emulation routines.
*/

#define CCT_DEVELOPMENT
#if (defined(CCTW) || defined(_WINDOWS))
    #include <windows.h>
#endif
#include <string.h>
#include <compat.h>
#include <ctype.h>
#include <stdlib.h>
#include <ansi.h>
#include <colors.h>
#include <biosvid.h>



/*
ANSI_CPR -- Send a cursor position report from an ANSI terminal.
*/
void ansi_cpr_(TERMINAL *t)
{
    char *pa, asc[4];

    term_write(t, t->csi);
    term_write(t, '[');
    itoa((*t->cur_get_row)(t)+1, asc, 10);
    pa = asc;
    while (*pa) term_write(t, *pa++);
    term_write(t, t->delim1);
    itoa((*t->cur_get_col)(t)+1, asc, 10);
    pa = asc;
    while (*pa) term_write(t, *pa++);
    term_write(t, 'R');
}



/*
ANSI_CURSOR -- Handle terminal movement commands.
*/
void ansi_cursor_(TERMINAL *t, short cmd)
{
    switch(cmd) {
        case CUB:                       /* cursor back */
            if (t->ccol > t->clmargin) {
                t->ccol = (t->num[0]==0) ? t->ccol-1 : max(t->ccol-t->num[0], t->clmargin);
            }
            break;

        case CUD:
            if (t->crow < t->cbmargin) {
                t->crow = (t->num[0] == 0) ? t->crow+1 : min(t->crow+t->num[0], t->cbmargin);
            }
            break;

        case CUF:
            if (t->ccol < t->crmargin) {
                t->ccol = (t->num[0] == 0) ? t->ccol+1 : min(t->ccol+t->num[0], t->crmargin);
            }
            break;

        case CUP:
        case HVP:
            t->crow = (t->num[0] == 0) ? t->ctmargin : t->ctmargin + t->num[0] - 1;
            t->ccol = (t->num[1] == 0) ? t->clmargin : t->clmargin + t->num[1] - 1;
            if (t->num[0] == 22 && t->num[1] == 0)
                t->num[0] = 22;
            break;

        case CUU:
            if (t->crow > t->ctmargin) {
                t->crow = (t->num[0] == 0) ? t->crow-1 : max(t->crow-t->num[0], t->ctmargin);
            }
            break;

        case IND:                   /* index */
            if (t->crow == t->bmargin) (*t->scroll)(t, t->lmargin, t->tmargin, t->rmargin, t->bmargin, t->d_att, 1);
            else t->crow++;
            break;

        case NEL:                   /* next line */
            if (t->crow == t->bmargin) (*t->scroll)(t, t->lmargin, t->tmargin, t->rmargin, t->bmargin, t->d_att, 1);
            else t->crow++;
            t->ccol = 0;
            break;

        case TRI:                   /* reverse index */
            if (t->crow == t->tmargin) (*t->scroll)(t, t->lmargin, t->tmargin, t->rmargin, t->bmargin, t->d_att, -1);
            else t->crow--;
            break;

        default:
#if XDEBUG
            printf("Unrecognized term_cursor() command %d", cmd);
#endif
            break;
    }
    (*t->cur_pos_)(t, t->ccol, t->crow);
}



/*
ANSI_ERASE -- Generic function to handle several erase commands.
ANSI X3.64 escape code is "ESC [ Ps K"
*/
void ansi_erase_(TERMINAL *t, short cmd)
{
    switch (cmd) {
        case ECH:
            (*t->ech)(t, SP, t->att, 1);
            break;

        case EED0:            /* erase from active pos. to end of display */
        case EED1:
            (*t->eed)(t, SP, t->d_att);
            break;

        case EBD:           /* erase from start of display to active posn. */
            (*t->ebd)(t, SP, t->d_att);
            break;

        case ED:           /* erase all of display */
            (*t->scroll)(t, 0, 0, t->d_cols, t->d_rows, t->d_att, 0);
            if (t->type == ANSI_SYS) {
                t->crow = 0;
                t->ccol = 0;
                (*t->cur_pos_)(t, 0, 0);
            }
            break;

        case EEL0:        /* erase from active pos. to end of line */
        case EEL1:
            if (t->type == ANSI_SYS) (*t->eel)(t, SP, t->att);
            else (*t->eel)(t, SP, t->d_att);
            break;

        case EBL:         /* erase from start of line to active posn. */
            (*t->ebl)(t, SP, t->d_att);
            break;

        case EL:           /* erase all of line */
            (*t->eil)(t, SP, t->d_att);
            break;

        default:
#if XDEBUG
            printf("Unrecognized term_erase() command %d", cmd);
#endif
            break;
    }
}



/*
ANSI_HTS -- ANSI X3.64 tabulation set (HTS) ESC H.
*/
void ansi_hts_(TERMINAL *t)
{
    t->tabstop[t->ccol] = (char) 1;
}





/*
ANSI_INSERT -- Generic function to handle several insert commands.
ANSI X3.64 escape codes:
IL  Insert Line "ESC [ Ps L"
*/
void ansi_insert_(TERMINAL *t, short cmd)
{
    switch (cmd) {
        case IL:
            (*t->scroll)(t, t->lmargin, t->crow, t->rmargin, t->bmargin, t->d_att, -1);
            break;

        default:
#if XDEBUG
            printf("Unrecognized ansi_insert() command %d", cmd);
#endif
            break;
    }
}



/*
ANSI_MEDIA_COPY -- ANSI X3.64 media copy commands.
ANSI X3.64 commands CSIxxPn i
*/
void ansi_media_copy_(TERMINAL *t)
{
    WORD i=0;

    while (i < t->parmcount || i == 0) {
        switch (t->num[0]) {
            case 0:         /* copy entire screen to primary aux. device */
                break;

            case 1:         /* copy from primary auxilliary device */
                break;

            case 2:         /* copy entire screen to secondary aux. device */
                break;

            case 3:         /* copy from secondary auxilliary device */
                break;

            case 4:         /* turn off copying RX data to primary aux. */
                t->ansimode &= ~PRN_CTRL;
                break;

            case 5:         /* turn on copying RX data to primary aux. */
                t->ansimode |= PRN_CTRL;
                break;

            case 6:         /* turn off copying RX data to secondary aux. */
                break;

            case 7:         /* turn off copying RX data to secondary aux. */
                break;

            default:
#if XDEBUG
                printf("HOST: Unrecognized ANSI printer controller sequence");
#endif
                break;
        }
        i++;
    }
}



/*
ANSI_PARSE_CMD -- Search forward through the the set of strings that may be
received from the host for the one in the command buffer.
Ignore parameter specifications ('%').
If the string is not found, return EOF, else return
*/
short ansi_parse_cmd_(TERMINAL *t, const char *n)
{
    short i, j, k;
    TERM_RESPONSE *h = t->tr;
    BYTE ch;

    if (*n != '\0') {
        for (i=0; i < MAX_TERM_CMDS; i++) {
            if (h[i].sh2t[0] == '\0') continue;
            for (j=0, k=0; j < MAX_PARM_LEN && k < MAX_PARM_LEN; j++, k++) {
#if XDEBUG
                if (i == SGR && n[k-1] == 'm')
                    i = i;
#endif
                ch = h[i].sh2t[j];
                if (ch == '\0')
                    return (i);
                while (n[k] == (char) t->delim1 || n[k] == (char) t->csi) k++;
                if (ch == '%' || ch == (BYTE) t->delim1) {
                    while (h[i].sh2t[j] == '%' || h[i].sh2t[j] == (char) t->delim1) j++;
                    while (isdigit(n[k]) || n[k] == (char) t->delim1) k++;
                }
                if (h[i].sh2t[j] == n[k]) continue;
                else break;
            }
        }
    }

    return (EOF);
}



/*
ANSI_RESET -- Reset an ANSI X3.64 terminal to its initial state.
*/
void ansi_reset_(TERMINAL *t)
{
    t = t;          /* silence compiler warning */
    return;
}



/*
ANSI_RESET_MODE -- Called on receipt of "CSI Ps;...;Psl" (SM) sequence.
This routine handles ANSI X3.64 modes.
*/
void ansi_reset_mode_(TERMINAL *t)
{
    WORD i=0;

    while (i < t->parmcount || i == 0) {
        switch (t->num[i]) {
            case LNM:                       /* set CR = CRLF mode ON */
                t->ansimode &= ~ANSI_LNM;
                break;

            default:

                break;
        }
        i++;
    }
}



/*
ANSI_SET_MODE -- Called on receipt of "CSI Ps;...;Psh" (SM) sequence.
This routine handles ANSI X3.64 modes.
*/
void ansi_set_mode_(TERMINAL *t)
{
    WORD i=0;

    while (i < t->parmcount) {
        switch (t->num[i]) {
            case 0:
                break;

            case LNM:                       /* set CR = CRLF mode ON */
                t->ansimode |= ANSI_LNM;
                break;

            default:
                break;
        }
        i++;
    }
}



/*
ANSI_SGR -- Set screen attributes on ANSI X3.64 compatible terminals.
Return value:
    0   -- OK;
    EOF -- unrecognized attribute request;
*/
void ansi_sgr_(TERMINAL *t)
{
    short fc, bc, blink, underscore;        /* ATTRIBUTES */
    short ch, ret = 0;
    short bright, reverse;
    WORD i=0;

    reverse = FALSE;
    fc = FG(t->att);
    bc = BG(t->att);
    blink  = (t->att & 0X80) ? TRUE : FALSE;
    underscore = (fc == 1) ? TRUE: FALSE;
    bright = fc & 0X8;
    while (i < t->parmcount || i == 0) {
#if 0
        printf("Num[%d]=%d", i, t->num[i]);
#endif
        switch(t->num[i]) {
            case 0:
                fc = FG(t->d_att);   bc = BG(t->d_att);
                bright  = reverse = underscore = blink = FALSE;
                break;

            case 1:
                bright = TRUE;
                break;

            case 4:
                underscore = TRUE;
                break;

            case 5:
                blink = TRUE;
                break;

            case 7:             /* reverse video on */
                fc = FG(t->d_att);   bc = BG(t->d_att);
                bright  = underscore = blink = FALSE;
                reverse = TRUE;
                break;

            case 8:             /* cancelled on */
                fc = bc;
                break;

            case 22:            /* bright off */
                bright = FALSE;
                break;

            case 24:            /* underline off */
                underscore = FALSE;
                break;

            case 25:            /* blink off */
                blink = FALSE;
                break;

            case 27:            /* display positive image (?) */
                reverse = FALSE;
                ch = fc;
                fc = bc;
                bc = ch;
                break;

            case 30:            /* black foreground */
                fc = BLACK;
                break;

            case 31:            /* red foreground */
                fc = RED;
                break;

            case 32:            /* green foreground */
                fc = GREEN;
                break;

            case 33:            /* yellow foreground */
                fc = YELLOW;
                break;

            case 34:            /* blue foreground */
                fc = BLUE;
                break;

            case 35:            /* magenta foreground */
                fc = MAGENTA;
                break;

            case 36:            /* cyan foreground */
                fc = CYAN;
                break;

            case 37:            /* white foreground */
                fc = LIGHTGREY;
                break;

            case 40:            /* black background */
                bc = BLACK;
                break;

            case 41:            /* red background */
                bc = RED;
                break;

            case 42:            /* green background */
                bc = GREEN;
                break;

            case 43:            /* yellow background */
                bc = YELLOW;
                break;

            case 44:            /* blue background */
                bc = BLUE;
                break;

            case 45:            /* magenta background */
                bc = MAGENTA;
                break;

            case 46:            /* cyan background */
                bc = CYAN;
                break;

            case 47:            /* white background */
                bc = LIGHTGREY;
                break;

            default:
                ret = EOF;
                break;
        }
        i++;                            /* increment to next attribute */
        if (ret == EOF) break;
    }
    if (reverse) {
        ch = fc;
        fc = bc;
        bc = ch;
    }
    if (bright)  fc |= 0X08;
    else if (fc != YELLOW) fc &= 0X7;
    if (blink)   bc |= 0X08;
    else bc &= 0X7;
    if (underscore) fc |= 0X1;
    t->att = 0;                     /* necessary to fix a TC v2.0 bug */
    t->att = (bc << 4) + fc;        /* update terminal structure */
#if XDEBUG
    printf("fc=%d, bc=%d", fc, bc);
    printf("att=%#x", t->att);
#endif
}



/*
ANSI_TBC -- ANSI X3.64 tabulation clear (TBC) ESC [Psg.
If Ps = 0 clear tabs at cursor column.
If Ps = 3 clear all tabs.
*/
void ansi_tbc_(TERMINAL *t)
{
    /* CLEAR ALL TABS */
    if (t->num[0] == 3) memset(t->tabstop, 0, (size_t) t->d_cols);
    else t->tabstop[t->ccol] = 0;
}
[ RETURN TO DIRECTORY ]