[net.micro.6809] MicroEMACS OS-9 Part 6 of 7

jimomura@lsuc.UUCP (Jim Omura) (05/04/86)

Error: Unrecognized entry.
Choices are: all, alsop, backward, comment, copy, date, download, duew, first, 
forward, header, help, last, original, quit, reference, resign, say, search, 
skip, to, unclop, upload, withdraw, 
No more unread
Hit <RETURN> for next
R:sh scratch


==========
os.9/public.domain #96, from jimomura, 6663 chars, Sat Mar 22 21:13:10 1986

----------
TITLE: 'microEMACS' part 27 'ueregion.c'
/*
 * The routines in this file
 * deal with the region, that magic space
 * between "." and mark. Some functions are
 * commands. Some functions are just for
 * internal use.
 */
#include        <stdio.h>
#include        "ueed.h"

/*
 * Kill the region. Ask "getregion"
 * to figure out the bounds of the region.
 * Move "." to the start, and kill the characters.
 * Bound to "C-W".
 */
killregion(f, n)
{
        register int    s;
        REGION          region;

        if ((s=getregion(&region)) != TRUE)
                return (s);
        if ((lastflag&CFKILL) == 0)             /* This is a kill type  */
                kdelete();                      /* command, so do magic */
        thisflag |= CFKILL;                     /* kill buffer stuff.   */
        curwp->w_dotp = region.r_linep;
        curwp->w_doto = region.r_offset;
        return (ldelete(region.r_size, TRUE));
}

/*
 * Copy all of the characters in the
 * region to the kill buffer. Don't move dot
 * at all. This is a bit like a kill region followed
 * by a yank. Bound to "M-W".
 */
copyregion(f, n)
{
        register LINE   *linep;
        register int    loffs;
        register int    s;
        REGION          region;

        if ((s=getregion(&region)) != TRUE)
                return (s);
        if ((lastflag&CFKILL) == 0)             /* Kill type command.   */
                kdelete();
        thisflag |= CFKILL;
        linep = region.r_linep;                 /* Current line.        */
        loffs = region.r_offset;                /* Current offset.      */
        while (region.r_size--) {
                if (loffs == llength(linep)) {  /* End of line.         */
                        if ((s=kinsert('\n')) != TRUE)
                                return (s);
                        linep = lforw(linep);
                        loffs = 0;
                } else {                        /* Middle of line.      */
                        if ((s=kinsert(lgetc(linep, loffs))) != TRUE)
                                return (s);
                        ++loffs;
                }
        }
        return (TRUE);
}

/*
 * Lower case region. Zap all of the upper
 * case characters in the region to lower case. Use
 * the region code to set the limits. Scan the buffer,
 * doing the changes. Call "lchange" to ensure that
 * redisplay is done in all buffers. Bound to 
 * "C-X C-L".
 */
lowerregion(f, n)
{
        register LINE   *linep;
        register int    loffs;
        register int    c;
        register int    s;
        REGION          region;

        if ((s=getregion(&region)) != TRUE)
                return (s);
        lchange(WFHARD);
        linep = region.r_linep;
        loffs = region.r_offset;
        while (region.r_size--) {
                if (loffs == llength(linep)) {
                        linep = lforw(linep);
                        loffs = 0;
                } else {
                        c = lgetc(linep, loffs);
                        if (c>='A' && c<='Z')
                                lputc(linep, loffs, c+'a'-'A');
                        ++loffs;
                }
        }
        return (TRUE);
}

/*
 * Upper case region. Zap all of the lower
 * case characters in the region to upper case. Use
 * the region code to set the limits. Scan the buffer,
 * doing the changes. Call "lchange" to ensure that
 * redisplay is done in all buffers. Bound to 
 * "C-X C-L".
 */
upperregion(f, n)
{
        register LINE   *linep;
        register int    loffs;
        register int    c;
        register int    s;
        REGION          region;

        if ((s=getregion(&region)) != TRUE)
                return (s);
        lchange(WFHARD);
        linep = region.r_linep;
        loffs = region.r_offset;
        while (region.r_size--) {
                if (loffs == llength(linep)) {
                        linep = lforw(linep);
                        loffs = 0;
                } else {
                        c = lgetc(linep, loffs);
                        if (c>='a' && c<='z')
                                lputc(linep, loffs, c-'a'+'A');
                        ++loffs;
                }
        }
        return (TRUE);
}

/*
 * This routine figures out the
 * bounds of the region in the current window, and
 * fills in the fields of the "REGION" structure pointed
 * to by "rp". Because the dot and mark are usually very
 * close together, we scan outward from dot looking for
 * mark. This should save time. Return a standard code.
 * Callers of this routine should be prepared to get
 * an "ABORT" status; we might make this have the
 * conform thing later.
 */
getregion(rp)
register REGION *rp;
{
        register LINE   *flp;
        register LINE   *blp;
        register int    fsize;
        register int    bsize;

        if (curwp->w_markp == NULL) {
                mlwrite("No mark set in this window");
                return (FALSE);
        }
        if (curwp->w_dotp == curwp->w_markp) {
                rp->r_linep = curwp->w_dotp;
                if (curwp->w_doto < curwp->w_marko) {
                        rp->r_offset = curwp->w_doto;
                        rp->r_size = curwp->w_marko-curwp->w_doto;
                } else {
                        rp->r_offset = curwp->w_marko;
                        rp->r_size = curwp->w_doto-curwp->w_marko;
                }
                return (TRUE);
        }
        blp = curwp->w_dotp;
        bsize = curwp->w_doto;
        flp = curwp->w_dotp;
        fsize = llength(flp)-curwp->w_doto+1;
        while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) {
                if (flp != curbp->b_linep) {
                        flp = lforw(flp);
                        if (flp == curwp->w_markp) {
                                rp->r_linep = curwp->w_dotp;
                                rp->r_offset = curwp->w_doto;
                                rp->r_size = fsize+curwp->w_marko;
                                return (TRUE);
                        }
                        fsize += llength(flp)+1;
                }
                if (lback(blp) != curbp->b_linep) {
                        blp = lback(blp);
                        bsize += llength(blp)+1;
                        if (blp == curwp->w_markp) {
                                rp->r_linep = blp;
                                rp->r_offset = curwp->w_marko;
                                rp->r_size = bsize - curwp->w_marko;
                                return (TRUE);
                        }
                }
        }
        mlwrite("Bug: lost mark");
        return (FALSE);
}


==========
os.9/public.domain #97, from jimomura, 5714 chars, Sun Mar 23 10:15:46 1986

----------
TITLE: 'microEMACS' part 28 'uesearch.c'
/*
 * The functions in this file implement commands that search in the forward
 * and backward directions. There are no special characters in the search
 * strings. Probably should have a regular expression search, or something
 * like that.
 *
 * REVISION HISTORY:
 *
 * ?    Steve Wilhite, 1-Dec-85
 *      - massive cleanup on code.
 */

#include        <stdio.h>
#include        "ueed.h"

/*
 * Search forward. Get a search string from the user, and search, beginning at
 * ".", for the string. If found, reset the "." to be just after the match
 * string, and [perhaps] repaint the display. Bound to "C-S".
 */
forwsearch(f, n)
    {
    register LINE *clp;
    register int cbo;
    register LINE*tlp;
    register int tbo;
    register int c;
    register char *pp;
    register int s;

    if ((s = readpattern("Search")) != TRUE)
        return (s);

    clp = curwp->w_dotp;
    cbo = curwp->w_doto;

    while (clp != curbp->b_linep)
        {
        if (cbo == llength(clp))
            {
            clp = lforw(clp);
            cbo = 0;
            c = '\n';
            }
        else
            c = lgetc(clp, cbo++);

        if (eq(c, pat[0]) != FALSE)
            {
            tlp = clp;
            tbo = cbo;
            pp  = &pat[1];

            while (*pp != 0)
                {
                if (tlp == curbp->b_linep)
                    goto fail;

                if (tbo == llength(tlp))
                    {
                    tlp = lforw(tlp);
                    tbo = 0;
                    c = '\n';
                    }
                else
                    c = lgetc(tlp, tbo++);

                if (eq(c, *pp++) == FALSE)
                    goto fail;
                }

            curwp->w_dotp  = tlp;
            curwp->w_doto  = tbo;
            curwp->w_flag |= WFMOVE;
            return (TRUE);
            }
fail:;
        }

    mlwrite("Not found");
    return (FALSE);
    }

/*
 * Reverse search. Get a search string from the user, and search, starting at
 * "." and proceeding toward the front of the buffer. If found "." is left
 * pointing at the first character of the pattern [the last character that was
 j matched]. Bound to "C-R".
 */
backsearch(f, n)
    {
    register LINE *clp;
    register int cbo;
    register LINE *tlp;
    register int tbo;
    register int c;
    register char *epp;
    register char *pp;
    register int s;

    if ((s = readpattern("Reverse search")) != TRUE)
        return (s);

    for (epp = &pat[0]; epp[1] != 0; ++epp)
        ;

    clp = curwp->w_dotp;
    cbo = curwp->w_doto;

    for (;;)
        {
        if (cbo == 0)
            {
            clp = lback(clp);

            if (clp == curbp->b_linep)
                {
                mlwrite("Not found");
                return (FALSE);
                }

            cbo = llength(clp)+1;
            }

        if (--cbo == llength(clp))
            c = '\n';
        else
            c = lgetc(clp, cbo);

        if (eq(c, *epp) != FALSE)
            {
            tlp = clp;
            tbo = cbo;
            pp  = epp;

            while (pp != &pat[0])
                {
                if (tbo == 0)
                    {
                    tlp = lback(tlp);
                    if (tlp == curbp->b_linep)
                        goto fail;

                    tbo = llength(tlp)+1;
                    }

                if (--tbo == llength(tlp))
                    c = '\n';
                else
                    c = lgetc(tlp, tbo);

                if (eq(c, *--pp) == FALSE)
                    goto fail;
                }

            curwp->w_dotp  = tlp;
            curwp->w_doto  = tbo;
            curwp->w_flag |= WFMOVE;
            return (TRUE);
            }
fail:;
        }
    }

/*
 * Compare two characters. The "bc" comes from the buffer. It has it's case
 * folded out. The "pc" is from the pattern.
 */
eq(bc, pc)
    int bc;
    int pc;
    {
    if (bc>='a' && bc<='z')
        bc -= 0x20;

    if (pc>='a' && pc<='z')
        pc -= 0x20;

    if (bc == pc)
        return (TRUE);

    return (FALSE);
    }

/*
 * Read a pattern. Stash it in the external variable "pat". The "pat" is not
 * updated if the user types in an empty line. If the user typed an empty line,
 * and there is no old pattern, it is an error. Display the old pattern, in the
 * style of Jeff Lomicka. There is some do-it-yourself control expansion.
 */
readpattern(prompt)
    char *prompt;
    {
    register char *cp1;
    register char *cp2;
    register int c;
    register int s;
    char tpat[NPAT+20];

    cp1 = &tpat[0];                     /* Copy prompt */
    cp2 = prompt;

    while ((c = *cp2++) != '\0')
        *cp1++ = c;

    if (pat[0] != '\0')                 /* Old pattern */
        {
        *cp1++ = ' ';
        *cp1++ = '[';
        cp2 = &pat[0];

        while ((c = *cp2++) != 0)
            {
            if (cp1 < &tpat[NPAT+20-6]) /* "??]: \0" */
                {
                if (c<0x20 || c==0x7F) {
                    *cp1++ = '^';
                    c ^= 0x40;
                    }
                else if (c == '%')      /* Map "%" to */
                    *cp1++ = c;         /* "%%". */

                *cp1++ = c;
                }
            }

        *cp1++ = ']';
        }

    *cp1++ = ':';                       /* Finish prompt */
    *cp1++ = ' ';
    *cp1++ = '\0';
    s = mlreply(tpat, tpat, NPAT);      /* Read pattern */

    if (s == TRUE)                      /* Specified */
        strcpy(pat, tpat);
    else if (s == FALSE && pat[0] != 0)         /* CR, but old one */
        s = TRUE;

    return (s);
    }



==========
os.9/public.domain #98, from jimomura, 8241 chars, Sun Mar 23 10:28:50 1986

----------
TITLE: 'microEMACS' part 29 'uespawn.c'
/*
 * The routines in this file are called to create a subjob running a command
 * interpreter. This code is a big fat nothing on CP/M-86. You lose.
 */
#include        <stdio.h>
#include        "ueed.h"

#ifdef AMIGA
#define  NEW   1006
#endif

#ifdef VMS
#define EFN     0                               /* Event flag.          */

#include        <ssdef.h>                       /* Random headers.      */
#include        <stsdef.h>
#include        <descrip.h>
#include        <iodef.h>

extern  int     oldmode[];                      /* In "termio.c"        */
extern  int     newmode[];                      /* In "termio.c"        */
extern  short   iochan;                         /* In "termio.c"        */
#endif

#ifdef MSDOS
#include        <dos.h>
#endif

#ifdef V7
#include        <signal.h>
#endif

#ifdef OSK
#include        <sgstat.h>             
extern struct  sgbuf  ostate;                   /* In "termio.c" */
extern struct  sgbuf  nstate;                   /* In "termio.c" */
#endif

/*
 * Create a subjob with a copy of the command intrepreter in it. When the
 * command interpreter exits, mark the screen as garbage so that you do a full
 * repaint. Bound to "C-C". The message at the start in VMS puts out a newline.
 * Under some (unknown) condition, you don't get one free when DCL starts up.
 */
spawncli(f, n)
{
#ifdef AMIGA
        long newcli;

        newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
        mlwrite("[Starting new CLI]");
        sgarbf = TRUE;
        Execute("", newcli, 0);
        Close(newcli);
        return(TRUE);
#endif
#ifdef VMS
        movecursor(term.t_nrow, 0);             /* In last line.        */
        mlputs("[Starting DCL]\r\n");
        (*term.t_flush)();                      /* Ignore "ttcol".      */
        sgarbf = TRUE;
        return (sys(NULL));                     /* NULL => DCL.         */
#endif
#ifdef CPM
        mlwrite("Not in CP/M-86");
#endif
#ifdef MSDOS
        movecursor(term.t_nrow, 0);             /* Seek to last line.   */
        (*term.t_flush)();
        sys("\\command.com", "");               /* Run CLI.             */
        sgarbf = TRUE;
        return(TRUE);
#endif
#ifdef V7
        register char *cp;
        char    *getenv();
        movecursor(term.t_nrow, 0);             /* Seek to last line.   */
        (*term.t_flush)();
        ttclose();                              /* stty to old settings */
        if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
                system(cp);
        else
                system("exec /bin/sh");
        sgarbf = TRUE;
        sleep(2);
        ttopen();
        return(TRUE);
#endif
#ifdef OSK
        register char *cp;
        char    *getenv();
        movecursor(term.t_nrow, 0);             /* Seek to last line.   */
        (*term.t_flush)();
        setstat(0, 0, &ostate);                 /* stty to old settings */
        if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
                system(cp);
        else
                system("shell");
        sgarbf = TRUE;
        setstat(0, 0, &nstate);
        return(TRUE);
#endif
}

/*
 * Run a one-liner in a subjob. When the command returns, wait for a single
 * character to be typed, then mark the screen as garbage so a full repaint is
 * done. Bound to "C-X !".
 */
spawn(f, n)
{
        register int    s;
        char            line[NLINE];
#ifdef AMIGA
        long newcli;

        newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
        if ((s=mlreply("CLI command: ", line, NLINE)) != TRUE)
                return (s);
        Execute(line,0,newcli);
        Close(newcli);
        while ((*term.t_getchar)() != '\r')     /* Pause.               */
                ;
        sgarbf = TRUE;
        return(TRUE);
#endif
#ifdef VMS
        if ((s=mlreply("DCL command: ", line, NLINE)) != TRUE)
                return (s);
        (*term.t_putchar)('\n');                /* Already have '\r'    */
        (*term.t_flush)();
        s = sys(line);                          /* Run the command.     */
        mlputs("\r\n\n[End]");                  /* Pause.               */
        (*term.t_flush)();
        while ((*term.t_getchar)() != '\r')
                ;
        sgarbf = TRUE;
        return (s);
#endif
#ifdef CPM
        mlwrite("Not in CP/M-86");
        return (FALSE);
#endif
#ifdef MSDOS
        if ((s=mlreply("MS-DOS command: ", line, NLINE)) != TRUE)
                return (s);
        system(line);
        while ((*term.t_getchar)() != '\r')     /* Pause.               */
                ;
        sgarbf = TRUE;
        return (TRUE);
#endif
#ifdef V7
        if ((s=mlreply("! ", line, NLINE)) != TRUE)
                return (s);
        (*term.t_putchar)('\n');                /* Already have '\r'    */
        (*term.t_flush)();
        ttclose();                              /* stty to old modes    */
        system(line);
        sleep(2);
        ttopen();
        mlputs("[End]");                        /* Pause.               */
        (*term.t_flush)();
        while ((s = (*term.t_getchar)()) != '\r' && s != ' ')
                ;
        sgarbf = TRUE;
        return (TRUE);
#endif
#ifdef OSK
        if ((s=mlreply("! ", line, NLINE)) != TRUE)
                return (s);
        (*term.t_putchar)('\l');                /* Already have '\r'    */
        (*term.t_flush)();
        setstat(0, 0, &ostate);                 /* stty to old modes    */
        s=system(line);
        setstat(0, 0, &nstate);
        mlputs("[End]");                        /* Pause.               */
        (*term.t_flush)();
        while ((s = (*term.t_getchar)()) != '\r' && s != ' ')
                ;
        sgarbf = TRUE;
        return (TRUE);
#endif
}

#ifdef VMS
/*
 * Run a command. The "cmd" is a pointer to a command string, or NULL if you
 * want to run a copy of DCL in the subjob (this is how the standard routine
 * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in
 * and the way out, because DCL does not want the channel to be in raw mode.
 */
sys(cmd)
register char   *cmd;
{
        struct  dsc$descriptor  cdsc;
        struct  dsc$descriptor  *cdscp;
        long    status;
        long    substatus;
        long    iosb[2];

        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
                          oldmode, sizeof(oldmode), 0, 0, 0, 0);
        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
                return (FALSE);
        cdscp = NULL;                           /* Assume DCL.          */
        if (cmd != NULL) {                      /* Build descriptor.    */
                cdsc.dsc$a_pointer = cmd;
                cdsc.dsc$w_length  = strlen(cmd);
                cdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
                cdsc.dsc$b_class   = DSC$K_CLASS_S;
                cdscp = &cdsc;
        }
        status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0);
        if (status != SS$_NORMAL)
                substatus = status;
        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
                          newmode, sizeof(newmode), 0, 0, 0, 0);
        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
                return (FALSE);
        if ((substatus&STS$M_SUCCESS) == 0)     /* Command failed.      */
                return (FALSE);
        return (TRUE);
}
#endif

#ifdef MSDOS
/*
 * This routine, once again by Bob McNamara, is a C translation of the "system"
 * routine in the MWC-86 run time library. It differs from the "system" routine
 * in that it does not unconditionally append the string ".exe" to the end of
 * the command name. We needed to do this because we want to be able to spawn
 * off "command.com". We really do not understand what it does, but if you don't
 * do it exactly "malloc" starts doing very very strange things.
 */
sys(cmd, tail)
char    *cmd;
char    *tail;
{
#ifdef MWC_86
        register unsigned n;
        extern   char     *__end;

        n = __end + 15;
        n >>= 4;
        n = ((n + dsreg() + 16) & 0xFFF0) + 16;
        return(execall(cmd, tail, n));
#endif

#ifdef LATTICE
        return forklp(cmd, tail, NULL);
#endif
}
#endif



==========
os.9/public.domain #99, from jimomura, 2217 chars, Sun Mar 23 10:34:22 1986

----------
TITLE: 'microEMACS' part 30 'uetcap.c'
#include <stdio.h>
#include "ueed.h"

#ifdef TERMCAP

#define NROW    24
#define NCOL    80
#define BEL     0x07
#define ESC     0x1B


extern int      ttopen();
extern int      ttgetc();
extern int      ttputc();
extern int      ttflush();
extern int      ttclose();
extern int      tcapmove();
extern int      tcapeeol();
extern int      tcapeeop();
extern int      tcapbeep();
extern int      tcapopen();
extern int      tput();
extern char     *tgoto();

#define TCAPSLEN 315

char tcapbuf[TCAPSLEN];
char    PC,
        *CM,
        *CL,
        *CE,
        *UP,
        *CD;


TERM term = {
        NROW-1,
        NCOL,
        &tcapopen,
        &ttclose,
        &ttgetc,
        &ttputc,
        &ttflush,
        &tcapmove,
        &tcapeeol,
        &tcapeeop,
        &tcapbeep
};

tcapopen()

{
        char *getenv();
        char *t, *p, *tgetstr();
        char tcbuf[1024];
        char *tv_stype;
        char err_str[72];

        if ((tv_stype = getenv("TERM")) == NULL)
        {
                puts("Environment variable TERM not defined!");
                exit(1);
        }

        if((tgetent(tcbuf, tv_stype)) != 1)
        {
                sprintf(err_str, "Unknown terminal type %s!", tv_stype);
                puts(err_str);
                exit(1);
        }

        p = tcapbuf;
        t = tgetstr("pc", &p);
        if(t)
                PC = *t;

        CD = tgetstr("cd", &p);
        CM = tgetstr("cm", &p);
        CE = tgetstr("ce", &p);
        UP = tgetstr("up", &p);

        if(CD == NULL || CM == NULL || CE == NULL || UP == NULL)
        {
                puts("Incomplete termcap entry\n");
                exit(1);
        }

        if (p >= &tcapbuf[TCAPSLEN])
        {
                puts("Terminal description too big!\n");
                exit(1);
        }
        ttopen();
}
tcapmove(row, col)
register int row, col;
{
        putpad(tgoto(CM, col, row));
}

tcapeeol()
{
        putpad(CE);
}

tcapeeop()
{
        putpad(CD);

}

tcapbeep()
{
        ttputc(BEL);
}

putpad(str)
char    *str;
{
        tputs(str, 1, ttputc);
}

putnpad(str, n)
char    *str;
{
        tputs(str, n, ttputc);
}
#endif TERMCAP



==========
os.9/public.domain #100, from jimomura, 10675 chars, Sun Mar 23 10:52:24 1986

----------
TITLE: 'microEMACS' part 31 'uetermio.c'
/*
 * The functions in this file negotiate with the operating system for
 * characters, and write characters in a barely buffered fashion on the display.
 * All operating systems.
 */
#include        <stdio.h>
#include        "ueed.h"

#ifdef AMIGA
#define NEW 1006
#define LEN 1

static long terminal;
#endif

#ifdef VMS
#include        <stsdef.h>
#include        <ssdef.h>
#include        <descrip.h>
#include        <iodef.h>
#include        <ttdef.h>

#define NIBUF   128                     /* Input  buffer size           */
#define NOBUF   1024                    /* MM says bug buffers win!     */
#define EFN     0                       /* Event flag                   */


char    obuf[NOBUF];                    /* Output buffer                */
int     nobuf;                          /* # of bytes in above          */
char    ibuf[NIBUF];                    /* Input buffer                 */
int     nibuf;                          /* # of bytes in above          */
int     ibufi;                          /* Read index                   */
int     oldmode[2];                     /* Old TTY mode bits            */
int     newmode[2];                     /* New TTY mode bits            */
short   iochan;                         /* TTY I/O channel              */
#endif

#ifdef CPM
#include        <bdos.h>
#endif

#ifdef MSDOS
#undef  LATTICE
#include        <dos.h>
#endif

#ifdef RAINBOW
#include "rainbow.h"
#endif

#ifdef V7
#include        <sgtty.h>               /* for stty/gtty functions */

struct  sgttyb  ostate;                 /* saved tty state */
struct  sgttyb  nstate;                 /* values for editor mode */
#endif

#ifdef OS9
#include        <sgstat.h>               /* for stty/gtty functions */
struct  sgbuf  ostate;                 /* saved tty state */
struct  sgbuf  nstate;                 /* values for editor mode */
#endif

#ifdef OSK
#include        <sgstat.h>             /* same as os9/6809 */
struct  sgbuf  ostate;
struct  sgbuf  nstate;
#endif

/*
 * This function is called once to set up the terminal device streams.
 * On VMS, it translates SYS$INPUT until it finds the terminal, then assigns
 * a channel to it and sets it raw. On CPM it is a no-op.
 */
ttopen()
{
#ifdef AMIGA
        terminal = Open("RAW:1/1/639/199/MicroEmacs", NEW);
#endif
#ifdef VMS
        struct  dsc$descriptor  idsc;
        struct  dsc$descriptor  odsc;
        char    oname[40];
        int     iosb[2];
        int     status;

        odsc.dsc$a_pointer = "SYS$INPUT";
        odsc.dsc$w_length  = strlen(odsc.dsc$a_pointer);
        odsc.dsc$b_dtype   = DSC$K_DTYPE_T;
        odsc.dsc$b_class   = DSC$K_CLASS_S;
        idsc.dsc$b_dtype   = DSC$K_DTYPE_T;
        idsc.dsc$b_class   = DSC$K_CLASS_S;
        do {
                idsc.dsc$a_pointer = odsc.dsc$a_pointer;
                idsc.dsc$w_length  = odsc.dsc$w_length;
                odsc.dsc$a_pointer = &oname[0];
                odsc.dsc$w_length  = sizeof(oname);
                status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
                if (status!=SS$_NORMAL && status!=SS$_NOTRAN)
                        exit(status);
                if (oname[0] == 0x1B) {
                        odsc.dsc$a_pointer += 4;
                        odsc.dsc$w_length  -= 4;
                }
        } while (status == SS$_NORMAL);
        status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
        if (status != SS$_NORMAL)
                exit(status);
        status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
                          oldmode, sizeof(oldmode), 0, 0, 0, 0);
        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
                exit(status);
        newmode[0] = oldmode[0];
        newmode[1] = oldmode[1] | TT$M_PASSALL | TT$M_NOECHO;
        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
                          newmode, sizeof(newmode), 0, 0, 0, 0);
        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
                exit(status);
#endif
#ifdef CPM
#endif
#ifdef MSDOS
#endif
#ifdef V7
        gtty(1, &ostate);                       /* save old state */
        gtty(1, &nstate);                       /* get base of new state */
        nstate.sg_flags |= RAW;
        nstate.sg_flags &= ~(ECHO|CRMOD);       /* no echo for now... */
        stty(1, &nstate);                       /* set mode */
#endif
#ifdef OS9
        getstat(0, 0, &ostate);                       /* save old state */
        getstat(0, 0, &nstate);                       /* get base of new state *
/
        nstate.sg_echo = 0;       /* no echo for now... */
        nstate.sg_bellch = 0;
        nstate.sg_bsech = 0;
        nstate.sg_kbach = 0;
        nstate.sg_kbich = 0;
        nstate.sg_psch = 0;
        nstate.sg_dulnch = 0;
        nstate.sg_rlnch = 0;
        nstate.sg_eofch = 0;
        nstate.sg_eorch = 0;
        nstate.sg_dlnch = 0;
        nstate.sg_bspch = 0;
        nstate.sg_pause = 0;
        nstate.sg_alf = 0;
        nstate.sg_backsp = 0;
        setstat(0, 0, &nstate);                       /* set mode */
        stdin->_flag &= ~_SCF;
        stdin->_flag |= _RBF;
        stdout->_flag &= ~_SCF;
        stdout->_flag |= _RBF;
        setbuf(stdout,0);
#endif
#ifdef OSK
        getstat(0, 0, &ostate);                       /* save old state */
        getstat(0, 0, &nstate);                       /* get base of new state *
/
        nstate.sg_echo = 0;       /* no echo for now... */
        nstate.sg_bellch = 0;
        nstate.sg_bsech = 0;
        nstate.sg_kbach = 0;

        nstate.sg_kbich = 0;
        nstate.sg_psch = 0;
        nstate.sg_dulnch = 0;
        nstate.sg_rlnch = 0;
        nstate.sg_eofch = 0;
        nstate.sg_eorch = 0;
        nstate.sg_dlnch = 0;
        nstate.sg_bspch = 0;
        nstate.sg_pause = 0;
        nstate.sg_alf = 0;
        nstate.sg_backsp = 0;
        nstate.sg_xoff =0;     /* new for OSK */
        nstate.sg_xon  =0;
        setstat(0, 0, &nstate);                       /* set mode */
        stdin->_flag &= ~_SCF;
        stdin->_flag |= _RBF;
        stdout->_flag &= ~_SCF;
        stdout->_flag |= _RBF;
        setbuf(stdout,0);
#endif
}

/*
 * This function gets called just before we go back home to the command
 * interpreter. On VMS it puts the terminal back in a reasonable state.
 * Another no-operation on CPM.
 */
ttclose()
{
#ifdef AMIGA
        Close(terminal);
#endif
#ifdef VMS
        int     status;
        int     iosb[1];

        ttflush();
        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
                 oldmode, sizeof(oldmode), 0, 0, 0, 0);
        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
                exit(status);
        status = SYS$DASSGN(iochan);
        if (status != SS$_NORMAL)
                exit(status);
#endif
#ifdef CPM
#endif
#ifdef MSDOS
#endif
#ifdef V7
        stty(1, &ostate);
#endif
#ifdef OS9
        setstat(0, 0, &ostate);
#endif
#ifdef OSK
        setstat(0, 0, &ostate);
#endif
}

/*
 * Write a character to the display. On VMS, terminal output is buffered, and
 * we just put the characters in the big array, after checking for overflow.
 * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
 * MS-DOS (use the very very raw console output routine).
 */
ttputc(c)
char c;
{
#ifdef AMIGA
        Write(terminal, &c, LEN);
#endif
#ifdef VMS
        if (nobuf >= NOBUF)
                ttflush();
        obuf[nobuf++] = c;
#endif

#ifdef CPM
        bios(BCONOUT, c, 0);
#endif

#ifdef MSDOS & CWC86
        dosb(CONDIO, c, 0);
#endif

#ifdef RAINBOW
        Put_Char(c);                    /* fast video */
#endif

#ifdef V7
        fputc(c, stdout);
#endif
#ifdef OS9
        putc(c, stdout);
#endif
#ifdef OSK
        putc(c, stdout);
#endif
}

/*
 * Flush terminal buffer. Does real work where the terminal output is buffered
 * up. A no-operation on systems where byte at a time terminal I/O is done.
 */
ttflush()
{
#ifdef AMIGA
#endif
#ifdef VMS
        int     status;
        int     iosb[2];

        status = SS$_NORMAL;
        if (nobuf != 0) {
                status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
                         iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
                if (status == SS$_NORMAL)
                        status = iosb[0] & 0xFFFF;
                nobuf = 0;
        }
        return (status);
#endif
#ifdef CPM
#endif
#ifdef MSDOS
#endif
#ifdef V7
        fflush(stdout);
#endif
#ifdef OS9
        fflush(stdout);
#endif
#ifdef OSK
        fflush(stdout);
#endif
}

/*
 * Read a character from the terminal, performing no editing and doing no echo
 * at all. More complex in VMS that almost anyplace else, which figures. Very
 * simple on CPM, because the system can do exactly what you want.
 */
ttgetc()
{
#ifdef AMIGA
        char ch;

        Read(terminal, &ch, LEN);
        return (int) ch;
#endif
#ifdef VMS
        int     status;
        int     iosb[2];
        int     term[2];

        while (ibufi >= nibuf) {
                ibufi = 0;
                term[0] = 0;
                term[1] = 0;
                status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
                         iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
                if (status != SS$_NORMAL)
                        exit(status);
                status = iosb[0] & 0xFFFF;
                if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
                        exit(status);
                nibuf = (iosb[0]>>16) + (iosb[1]>>16);
                if (nibuf == 0) {
                        status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
                                 iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
                        if (status != SS$_NORMAL
                        || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL)
                                exit(status);
                        nibuf = (iosb[0]>>16) + (iosb[1]>>16);
                }
        }
        return (ibuf[ibufi++] & 0xFF);          /* Allow multinational  */
#endif

#ifdef CPM
        return (biosb(BCONIN, 0, 0));
#endif

#ifdef RAINBOW
        int Ch;

        while ((Ch = Read_Keyboard()) < 0);

        if ((Ch & Function_Key) == 0)
                if (!((Ch & 0xFF) == 015 || (Ch & 0xFF) == 0177))
                        Ch &= 0xFF;

        return Ch;
#endif

#ifdef MSDOS
#ifdef MWC86
        return (dosb(CONRAW, 0, 0));
#endif
#endif

#ifdef V7
        return(fgetc(stdin));
#endif
#ifdef OS9
    char ch;

        read(0, &ch, 1);
        return((int)ch);
#endif
#ifdef OSK
    char ch;

        read(0, &ch, 1);
        return((int)ch);
#endif
}



-- 
James Omura, Barrister & Solicitor, Toronto
ihnp4!utzoo!lsuc!jimomura
Byte Information eXchange: jimomura
(416) 652-3880