Metropoli BBS
VIEWER: altos3.c MODE: TEXT (ASCII)
/*
Copyright (C) Magna Carta Software, Inc. 1990.  All Rights Reserved
ALTOS3.C -- Altos III terminal emulation routines.
*/

#include <comm.h>
#include <ctype.h>
#if defined(__TURBOC__)
    #include <mem.h>
#elif defined(MSC) || defined(__WATCOMC__) || defined(__POWERC)
    #include <string.h>
#endif
#include <vt.h>
#include <ansi.h>
#include <biosvid.h>
#include <colors.h>
#include <terminal.h>
#include <altos3.h>


WORD pf[MAX_FUNC_KEYS] = {F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
    ALT_F1, ALT_F2, ALT_F3, ALT_F4};

WORD shift_pf[] = {SF1, SF2, SF3, SF4, SF5, SF6, SF7, SF8, SF9, SF10, SF11, SF12,
    CTRL_F1, CTRL_F2, CTRL_F3, CTRL_F4};

WORD pad[MAX_PAD_KEYS] = {',', '-', KPERIOD, 0XFF, K0, K1, K2, K3, K4, K5, K6, K7, K8, K9};

WORD arrow[MAX_ARROW_KEYS] = {GREY_UP_ARROW, GREY_DOWN_ARROW, GREY_RIGHT_ARROW, GREY_LEFT_ARROW};

WORD shift_arrow[4] = {SUP_ARROW, SDOWN_ARROW, SRIGHT_ARROW, SLEFT_ARROW};

TERMKEYS tk_altos3 = {
    HOME,                           /* "HOME" key */
    0,                              /* "HELP" key (e.g. ALTOS III) */
    KENTER,                         /* "enter" key */
    TAB,                            /* horizontal tab */
    ENTER,                          /* vertical tab */
    PAGE_UP,                        /* key to page to prev screen */
    PAGE_DOWN,                      /* key to page to next screen */
    16,                             /* number of function keys on terminal */
    pf,                             /* programmable function keys */
    shift_pf,                       /* shifted programmable function keys */
    15,                             /* number of keys on terminal keypad */
    pad,                            /* programmable function keys */
    4,                              /* number of arrow keys on terminal */
    arrow,                          /* PC arrow key codes */
    shift_arrow,                    /* PC shift arrow key codes */
};



/*
ALTOS3_INIT -- Initialize for ALTOS3 terminal emulation.  This function
is passed as a pointer to "init_port()".
*/
short  altos3_init(TERMINAL *t)
{
    t->csi1         = ESC;
    t->csi2         = '[';
    t->delim1       = ';';
    t->mode         = 0X8004;
    t->d_att        = 7;
    t->att          = 7;
    t->tk           = &tk_altos3;
    ((struct comm_port *) t->port)->c_write = altos3_c_write; /* fn. to send byte to port */
    ((struct comm_port *) t->port)->c_out   = altos3_conoutc; /* local echo function */

    return (0);
}



/*
ALTOS3_WRITE -- VT100 driver function to send a byte out of the serial port.
This function is pointed at by p->c_write (i.e. it replaces u8250_write(), etc.
It is just a 'binding' to make the VT100 code independent of CCT.
*/
void altos3_c_write(COMM_PORT *p, short ch)
{
    altos3_c_putc(p->term, ch);
}



/*
ALTOS3_C_PUTC -- ALTOS III driver function to send a byte out of the serial
port (typically, a keystroke).  This function is pointed at by
p->c_write (i.e. it replaces u8250_write(), and works if transmitter
interrupts are enabled.
'ch' is the character to be sent out of the port.  It may be a keystroke,
in which case it can consist of a scan code in the high byte and a character
code in the low byte.  See KEYS.H and ASCII.H for key definitions.
*/
void altos3_c_putc(TERMINAL *t, short ch)
{
    short i, f_ascii = TRUE;

/*  if (ch == TAB) printf("TAB pressed"); */
    /* TEST FOR "HOME" */
    if (ch == t->tk->home) {
        (*t->c_putc)(t, ESC);
        (*t->c_putc)(t, '[');
        ch = 'H';
        f_ascii = FALSE;
    }
    /* TEST FOR "HELP" */
    if (ch == t->tk->help) {
        (*t->c_putc)(t, SOH);
        (*t->c_putc)(t, 'P');
        ch = CR;
        f_ascii = FALSE;
    }
    /* TEST FOR "PREVIOUS SCREEN" */
    if (ch == t->tk->prevscreen) {
        (*t->c_putc)(t, ESC);
        (*t->c_putc)(t, '[');
        ch = 'T';
        f_ascii = FALSE;
    }
    /* TEST FOR "NEXT SCREEN" */
    if (ch == t->tk->nextscreen) {
        (*t->c_putc)(t, ESC);
        (*t->c_putc)(t, '[');
        ch = 'S';
        f_ascii = FALSE;
    }
    /* TEST FOR A FUNCTION KEY */
    for (i=0; i< t->tk->numfkeys; i++) {
        if (ch == t->tk->pf[i]) {       /* F1 - F12, ALT_F1 - ALT_F4 */
            (*t->c_putc)(t, SOH);
            (*t->c_putc)(t, '@' + i);
            ch = CR;
            f_ascii = FALSE;
            break;
        }
        if (ch == t->tk->shift_pf[i]) { /* SF1 - SF12, CTRL_F1 - CTRL_F4 */
            (*t->c_putc)(t, SOH);
            (*t->c_putc)(t, '`' + i);
            ch = CR;
            f_ascii = FALSE;
            break;
        }
    }
    /* TEST FOR KEYPAD KEYS (in Application Mode) */
    if (isapp()) {
        for (i=0; i< t->tk->numpadkeys; i++) {
            if ((ch & 0XFF) == t->tk->pad[i]) {
                (*t->c_putc)(t, ESC);
                (*t->c_putc)(t, 'O');
                ch =  'l' + i;
                f_ascii = FALSE;
                break;
            }
        }
        /* TEST FOR ENTER KEY (on numeric keypad) */
        if (ch == t->tk->enter) {
            (*t->c_putc)(t, ESC);
            (*t->c_putc)(t, 'O');
            ch =  'M';
            f_ascii = FALSE;
        }
    }
    /* TEST FOR ARROW KEYS */
    for (i=0; i< t->tk->numarrowkeys; i++) {
        if (ch == t->tk->arrow[i]) {
            (*t->c_putc)(t, ESC);
            if (isapp() && iscur()) (*t->c_putc)(t, 'O');
            else (*t->c_putc)(t, '[');
            ch =  'A' + i;
            f_ascii = FALSE;
            break;
        }
        if (ch == t->tk->shift_arrow[i]) {
            (*t->c_putc)(t, SOH);
            (*t->c_putc)(t, 'q' + i);
            ch =  CR;
            f_ascii = FALSE;
            break;
        }
    }
    /* A VALID CHARACTER CODE */
    if (f_ascii) switch(ch & 0XFF) {
        case CR:            /* treat these as LFs */
        case VT:
        case FF:
            if (isaddlf()) {
                (*t->c_putc)(t, CR);
                ch = LF;
            }
            break;
        default:
            break;
    }

    (*t->c_putc)(t, ch);            /* send character */
}



/*
ALTOS3_CONOUTC --- Under ALTOS3 emulation, this function replaces conoutc().
It is just a 'binding' to make the ALTOS3 code independent of CCT.
*/
void altos3_conoutc(COMM_PORT *p, short ch)
{
    altos3_parse(p->term, ch);
}



/*
ALTOS3_PARSE -- All characters for output to the screen go through here.
This is the ALTOS3 console emulation driver.
*/
void altos3_parse(TERMINAL *t, short ch)
{
    short ret = 0;

    /* COMMAND SEQUENCE INTRODUCER RECEIVED */
    if (ch == ESC) {
#if DEBUG
        (*t->putc)(ch, FG(t->att | 8), BG(t->att));
#endif
        t->inescape = 1;
        t->s = t->sequence;                     /* initialize buffer ptr. */
        memset(t->sequence, 0X0, MAX_ESC_LEN);  /* initialize buffer */
    }
    /* ALREADY IN AN ESCAPE SEQUENCE */
    else if (t->inescape) {
        /* HANDLE BUFFER OVERFLOW */
        if (t->s - t->sequence >= MAX_ESC_LEN) ret = EOF;
        else if (t->inescape == 1) {
#if DEBUG
            (*t->putc)(ch, FG(t->att | 8), BG(t->att));
#endif
            *t->s++ = (char) ch;
            if (ch == '[' || ch == '(') t->inescape++;
            else {
                ret = ansi_dispatch(t, t->sequence, ch);
                if (ret == EOF) ret = vt100_dispatch(t, t->sequence, ch);
                ret = EOF;
            }
        }
        else {
            if (isalpha(ch)) {
#if DEBUG
                (*t->putc)(ch, FG(t->att | 8), BG(t->att));
#endif
                ret = ansi_dispatch(t, t->sequence, ch);
                if (ret == EOF) vt100_dispatch(t, t->sequence, ch);
                if (ret == EOF) ret = altos3_dispatch(t, t->sequence, ch);
                ret = EOF;
            }
            else *t->s++ = (char) ch;
        }
    }
    /* CONTROL CHARACTER RECEIVED */
    else if (iscntrl(ch)) ret = vt_dispatch_ctrl(t, ch);
    /* NON-CONTROL ASCII CHARACTER */
    else (*t->putc)(ch, FG(t->att), BG(t->att));
    if (ret == EOF) t->inescape = FALSE;
}



/*
ALTOS3_DISPATCH -- Test for a DEC PRIVATE command received from the serial
port.
Return value:
    0   --  OK
    EOF --  Command not recognized.
*/
short altos3_dispatch(TERMINAL *t, char *buf, short ch)
{
    WORD num[128];
    short count, ret = 0;

    t->ccol = cur_get_col();
    t->crow = cur_get_row();
    count = term_parse(buf, num, ';');        /* no. of parameters */

    if (buf[0] == '[' || buf[0] == '(') {
        if (buf[1] == '?' || buf[1] == '>' || buf[1] == '=') {
            if (ch == 'h') ret = altos3_set_mode(t, num, count, buf[1]);
            else if (ch == 'l') ret = altos3_reset_mode(t, num, count, buf[1]);
        }
    }
    else ret = EOF;

    return (ret);
}



/*
ALTOS3_SET_MODE -- Called on receipt of "CSI Ps;...;Psh" (SM) sequence.
This routine sets ALTOS3 modes.
*/
short altos3_set_mode(TERMINAL *t, WORD *num, WORD len, WORD delim)
{
    short i = 0, ret = 0;

    while (i < len) {
        if (delim == '>') switch(num[i]) {
            case 0:
                break;

            case 1:
                break;

            case 5:
                /* cursor invisible */
                break;

            default:
                ret = EOF;
                break;
        }
        else if (delim == '=') switch(num[i]) {
            case 0:
                break;

            case 1:
                /* select printer echo mode */
                break;

            case 2:
                /* select unformatted printer mode */
                break;

            default:
                ret = EOF;
                break;
        }
        else ret = EOF;
        i++;
    }

    return (ret);
}



/*
ALTOS3_RESET_MODE -- Called on receipt of "CSI Ps;...;Psl" (SM) sequence.
This routine resets ALTOS3 modes.
*/
short altos3_reset_mode(TERMINAL *t, WORD *num, WORD len, WORD delim)
{
    short i = 0, ret = 0;

    while (i < len) {
        if (delim == '>') switch(num[i]) {
            case 0:
                break;

            case 1:
                break;

            case 5:
                /* cursor visible */
                break;

            default:
                ret = EOF;
                break;
        }
        else if (delim == '=') switch(num[i]) {
            case 0:
                break;

            case 1:
                /* select printer pass through mode */
                break;

            case 2:
                /* select formatted printer mode */
                break;

            default:
                ret = EOF;
                break;
        }
        else ret = EOF;
        i++;
    }

    return (ret);
}
[ RETURN TO DIRECTORY ]