🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.sys.atari.st
Article #24759

Uemail source (4 of 12)

#24759
From: RDROYA01
Date: Wed, 04 Feb 1987 15:08
1004 lines
35590 bytes
#       This is a shell archive.
#       Remove everything above and including the cut line.
#       Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
#       Run the following text with /bin/sh to create:
#       display.c
# This archive created: Tue Feb  3 17:55:19 1987
cat << \SHAR_EOF > display.c
/*
 * The functions in this file
 * handle redisplay. There are two halves,
 * the ones that update the virtual display
 * screen, and the ones that make the physical
 * display screen the same as the virtual
 * display screen. These functions use hints
 * that are left in the windows by the
 * commands.
 */
#include        <stdio.h>
#include        <osbind.h>
#include        "ed.h"
 
#define WFDEBUG 0                       /* Window flag debug.           */
#define BELL    0x07
 
typedef struct  VIDEO {
        short   v_flag;                 /* Flags                        */
        char    v_text[];               /* Screen data.                 */
}       VIDEO;
 
#define VFCHG   0x0001                  /* Changed.                     */
#define VFEXT   0x0002                  /* extended (beyond column 80)  */
#define VFREV   0x0004                  /* reverse ?                    */
#define VFREQ   0x0008
int     sgarbf  = TRUE;                 /* TRUE if screen is garbage    */
int     mpresf  = FALSE;                /* TRUE if message in last line */
int     vtrow   = 0;                    /* Row location of SW cursor    */
int     vtcol   = 0;                    /* Column location of SW cursor */
int     ttrow   = HUGE;                 /* Row location of HW cursor    */
int     ttcol   = HUGE;                 /* Column location of HW cursor */
int     lbound  = 0;                    /* leftmost column of current ln*/
char    mlbuf[256];                     /* modeline buffer              */
VIDEO   **vscreen;                      /* Virtual screen.              */
VIDEO   **pscreen;                      /* Physical screen.             */
 
/*
 * Initialize the data structures used
 * by the display code. The edge vectors used
 * to access the screens are set up. The operating
 * system's terminal I/O channel is set up. All the
 * other things get initialized at compile time.
 * The original window has "WFCHG" set, so that it
 * will get completely redrawn on the first
 * call to "update".
 */
vtinit()
{
        register int    i;
        register VIDEO  *vp;
 
#if ST
        /* save current colors for later */
        savecolor();
#endif
        (*term.t_open)();
        vscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
        if (vscreen == NULL)
                abort();
        pscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
        if (pscreen == NULL)
                abort();
        for (i=0; i<term.t_nrow; ++i) {
                vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol);
                if (vp == NULL)
                        abort();
                vp->v_flag = 0;
                vscreen[i] = vp;
                vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_ncol);
                if (vp == NULL)
                        abort();
                vp->v_flag = 0;
                pscreen[i] = vp;
        }
}
 
/*
 * Clean up the virtual terminal
 * system, in anticipation for a return to the
 * operating system. Move down to the last line and
 * clear it out (the next system prompt will be
 * written in the line). Shut down the channel
 * to the terminal.
 */
vttidy()
{
        mlerase();
        movecursor(term.t_nrow, 0);
        (*term.t_eeol)();
        (*term.t_close)();
}
 
/*
 * Set the virtual cursor to
 * the specified row and column on the
 * virtual screen. There is no checking for
 * nonsense values; this might be a good
 * idea during the early stages.
 */
vtmove(row, col)
register int row, col;
{
        vtrow = row;
        vtcol = col;
}
 
/*
 * Write a character to the
 * virtual screen. The virtual row and
 * column are updated. If the line is too
 * long put a "$" in the last column.
 * This routine only puts printing characters
 * into the virtual terminal buffers.
 * Only column overflow is checked.
 */
vtputc(c)
register int    c;
{
        register VIDEO  *vp;
 
        vp = vscreen[vtrow];
        if (vtcol >= term.t_ncol) {
                vtcol = (vtcol + 0x07) & ~0x07;
                vp->v_text[term.t_ncol-1] = '$';
        }
        else if (c == '\t') {
                do {
                        vtputc(' ');
                } while ((vtcol&0x07) != 0);
        } else if (c<0x20 || c==0x7F) {
                vtputc('^');
                vtputc(c ^ 0x40);
        } else
                vp->v_text[vtcol++] = c;
}
 
/*
 * put a character to the virtual screen in an extended line. If we are
 * not yet on left edge, don't print it yet. check for overflow on
 * the right margin.
 */
vtpute(c)
register int c;
{
        register VIDEO      *vp;
 
        vp = vscreen[vtrow];
        if (vtcol >= term.t_ncol) {
                vtcol = (vtcol + 0x07) & ~0x07;
                vp->v_text[term.t_ncol - 1] = '$';
        }
        else if (c == '\t') {
                do {
                        vtpute(' ');
                } while (((vtcol + lbound)&0x07) != 0);
        }
        else if (c < 0x20 || c == 0x7F) {
                vtpute('^');
                vtpute(c ^ 0x40);
        }
        else {
                if (vtcol >= 0)
                        vp->v_text[vtcol] = c;
                ++vtcol;
        }
}
 
/*
 * Erase from the end of the
 * software cursor to the end of the
 * line on which the software cursor is
 * located.
 */
vteeol()
{
        register VIDEO  *vp;
 
        vp = vscreen[vtrow];
        while (vtcol < term.t_ncol)
                vp->v_text[vtcol++] = ' ';
}
 
/*
 * Make sure that the display is
 * right. This is a three part process. First,
 * scan through all of the windows looking for dirty
 * ones. Check the framing, and refresh the screen.
 * Second, make sure that "currow" and "curcol" are
 * correct for the current window. Third, make the
 * virtual and physical screens the same.
 */
update()
{
        register LINE   *lp;
        register WINDOW *wp;
        register VIDEO  *vp1;
        register VIDEO  *vp2;
        register int    i;
        register int    j;
        register int    c;
 
#if     ST
        Bconout(2,0x1b);        /* hide cursor */
        Bconout(2,'f');
#endif
        for (i = 0; i < term.t_nrow; ++i)
                vscreen[i]->v_flag &= ~VFREQ;
#if     ST
        wp = wheadp;
        while (wp != NULL) {
                vscreen[wp->w_toprow+wp->w_ntrows]->v_flag |= VFREQ;
                wp = wp->w_wndp;
        }
#endif
        wp = wheadp;
        while (wp != NULL) {
                /* Look at any window with update flags set on.         */
                if (wp->w_flag != 0) {
                        /* If not force reframe, check the framing.     */
                        if ((wp->w_flag&WFFORCE) == 0) {
                                lp = wp->w_linep;
                                for (i=0; i<wp->w_ntrows; ++i) {
                                        if (lp == wp->w_dotp)
                                                goto out;
                                        if (lp == wp->w_bufp->b_linep)
                                                break;
                                        lp = lforw(lp);
                                }
                        }
                        /* Not acceptable, better compute a new value   */
                        /* for the line at the top of the window. Then  */
                        /* set the "WFHARD" flag to force full redraw.  */
                        i = wp->w_force;
                        if (i > 0) {
                                --i;
                                if (i >= wp->w_ntrows)
                                        i = wp->w_ntrows-1;
                        } else if (i < 0) {
                                i += wp->w_ntrows;
                                if (i < 0)
                                        i = 0;
                        } else
                                i = wp->w_ntrows/2;
                        lp = wp->w_dotp;
                        while (i!=0 && lback(lp)!=wp->w_bufp->b_linep) {
                                --i;
                                lp = lback(lp);
                        }
                        wp->w_linep = lp;
                        wp->w_flag |= WFHARD;   /* Force full.          */
                out:
                        /* Try to use reduced update. Mode line update  */
                        /* has its own special flag. The fast update is */
                        /* used if the only thing to do is within the   */
                        /* line editing.                                */
                        lp = wp->w_linep;
                        i  = wp->w_toprow;
                        if ((wp->w_flag&~WFMODE) == WFEDIT) {
                                while (lp != wp->w_dotp) {
                                        ++i;
                                        lp = lforw(lp);
                                }
                                vscreen[i]->v_flag |= VFCHG;
                                vtmove(i, 0);
                                for (j=0; j<llength(lp); ++j)
                                        vtputc(lgetc(lp, j));
                                vteeol();
                        } else if ((wp->w_flag&(WFEDIT|WFHARD)) != 0) {
                                while (i < wp->w_toprow+wp->w_ntrows) {
                                        vscreen[i]->v_flag |= VFCHG;
                                        vtmove(i, 0);
                                        if (lp != wp->w_bufp->b_linep) {
                                                for (j=0; j<llength(lp); ++j)
                                                        vtputc(lgetc(lp, j));
                                                lp = lforw(lp);
                                        }
                                        vteeol();
                                        ++i;
                                }
                        }
                        if ((wp->w_flag&WFMODE) != 0)
                                modeline(wp);
                        wp->w_flag  = 0;
                        wp->w_force = 0;
                }
/*
#if     WFDEBUG
                modeline(wp);
                wp->w_flag =  0;
                wp->w_force = 0;
#endif
*/
                wp = wp->w_wndp;
        }
        /* Always recompute the row and column number of the hardware   */
        /* cursor. This is the only update for simple moves.            */
        lp = curwp->w_linep;
        currow = curwp->w_toprow;
        while (lp != curwp->w_dotp) {
                ++currow;
                lp = lforw(lp);
        }
        curcol = 0;
        i = 0;
        while (i < curwp->w_doto) {
                c = lgetc(lp, i++);
                if (c == '\t')
                        curcol |= 0x07;
                else if (c<0x20 || c==0x7F)
                        ++curcol;
                ++curcol;
        }
        if (curcol >= term.t_ncol-1) {          /* Extended line.       */
                /* flag we are extended and changed */
                vscreen[currow]->v_flag |= VFEXT | VFCHG;
                updext();                       /* and output extended line */
        } else
                lbound = 0;                     /* not extended line */
        /* make sure no lines need to be de-extended because the cursor is
         * no longer on them
         */
        wp = wheadp;
        while (wp != NULL) {
                lp = wp->w_linep;
                i = wp->w_toprow;
                while (i < wp->w_toprow + wp->w_ntrows) {
                        if (vscreen[i]->v_flag & VFEXT) {
                                /* always flag extended lines as changed */
                                vscreen[i]->v_flag |= VFCHG;
                                if ((wp != curwp) || (lp != wp->w_dotp) ||
                                (curcol < term.t_ncol - 1)) {
                                        vtmove(i, 0);
                                        for (j = 0; j < llength(lp); ++j)
                                                vtputc(lgetc(lp, j));
                                        vteeol();
                                        /* this line no longer is extended */
                                        vscreen[i]->v_flag &= ~VFEXT;
                                }
                        }
                lp = lforw(lp);
                ++i;
                }
        /* and onward to the next window */
        wp = wp->w_wndp;
        }
        /* Special hacking if the screen is garbage. Clear the hardware */
        /* screen, and update your copy to agree with it. Set all the   */
        /* virtual screen change bits, to force a full update.          */
        if (sgarbf != FALSE) {
                for (i=0; i<term.t_nrow; ++i) {
                        vscreen[i]->v_flag |= VFCHG;
                        vp1 = pscreen[i];
                        for (j=0; j<term.t_ncol; ++j)
                                vp1->v_text[j] = ' ';
                }
                movecursor(0, 0);               /* Erase the screen.    */
                (*term.t_eeop)();
                sgarbf = FALSE;                 /* Erase-page clears    */
                mpresf = FALSE;                 /* the message area.    */
        }
        /* Make sure that the physical and virtual displays agree.      */
        /* Unlike before, the "updateline" code is only called with a   */
        /* line that has been updated for sure.                         */
        for (i=0; i<term.t_nrow; ++i) {
                vp1 = vscreen[i];
                j = vp1->v_flag;
                if (((j & VFCHG) != 0) || (((j & VFREV) == 0) !=
                        ((j & VFREQ) ==0)))
                        {
                        vp2 = pscreen[i];
                        updateline(i, &vp1->v_text[0], &vp2->v_text[0],
                        &vp1->v_flag);
                }
        }
        /* Finally, update the hardware cursor and flush out buffers.   */
        movecursor(currow, curcol-lbound);
        (*term.t_flush)();
#if     ST
        Bconout(2,0x1b);        /* enable cursor */
        Bconout(2,'e');
#endif
}
 
/*
 * updext: update the extended line which the cursor is currently
 * on at a column greater than the terminal width. The line
 * will be scrolled right or left to let the user see where
 * the cursor is
 */
updext()
{
        register int rcursor;   /* real cursor location */
        register LINE *lp;      /* pointer to current line */
        register int j;  /* index into line */
 
        /* calculate what column the real cursor will end up in */
        rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin;
        lbound = curcol - rcursor + 1;
        /* scan through the line outputing characters to the virtual screen */
        /* once we reach the left edge    */
        vtmove(currow, -lbound);        /* start scanning offscreen */
        lp = curwp->w_dotp;          /* line to output */
        for (j=0; j<llength(lp); ++j)   /* until the end-of-line */
                vtpute(lgetc(lp, j));
        /* truncate the virtual line */
        vteeol();
        /* and put a '$' in column 1 */
        vscreen[currow]->v_text[0] = '$';
}
 
/*
 * Update a single line. This
 * does not know how to use insert
 * or delete character sequences; we are
 * using VT52 functionality. Update the physical
 * row and column variables. It does try an
 * exploit erase to end of line. The RAINBOW version
 * of this routine uses fast video.
 */
updateline(row, vline, pline, flags)
int row;
char    vline[];
char    pline[];
short   *flags;
{
#if     RAINBOW
        register char   *cp1;
        register char   *cp2;
        register int    nch;
 
        cp1 = &vline[0];                        /* Use fast video.      */
        cp2 = &pline[0];
        putline(row+1, 1, cp1);
        nch = term.t_ncol;
        do {
                *cp2 = *cp1;
                ++cp2;
                ++cp1;
        } while (--nch);
#else
        register char   *cp1;
        register char   *cp2;
        register char   *cp3;
        register char   *cp4;
        register char   *cp5;
        register int    nbflag;
        int     rev;
        int     req;
 
        cp1 = &vline[0];                        /* Compute left match.  */
        cp2 = &pline[0];
#if     ST
        rev = *flags & VFREV;
        req = *flags & VFREQ;
        if (rev != req) {
                movecursor(row, 0);     /* Go to start of line. */
                if (req)
                        {
                        Crawio(0x1b);
                        Crawio('p');
                        }
                else
                        {
                        Crawio(0x1b);
                        Crawio('q');
                        }
/*              (*term.t_rev)(req != FALSE);*/
                /* scan through the line and dump it to the screen and
                 * the virtual screen array
                 */
                cp3 = &vline[term.t_ncol];
                while (cp1 < cp3) {
                        (*term.t_putchar)(*cp1);
                        ++ttcol;
                        *cp2++ = *cp1++;
                }
                Crawio(0x1b);
                Crawio('q');            /* turn on reverse video */
                /* update the needed flags */
                *flags &= ~VFCHG;
                if (req)
                        *flags |= VFREV;
                else
                        *flags &= ~VFREV;
                return(TRUE);
        }
#endif
        while (cp1!=&vline[term.t_ncol] && cp1[0]==cp2[0]) {
                ++cp1;
                ++cp2;
        }
        /* This can still happen, even though we only call this routine */
        /* on changed lines. A hard update is always done when a line   */
        /* splits, a massive change is done, or a buffer is displayed   */
        /* twice. This optimizes out most of the excess updating. A lot */
        /* of computes are used, but these tend to be hard operations   */
        /* that do a lot of update, so I don't really care.             */
        if (cp1 == &vline[term.t_ncol])         /* All equal.           */
                return;
        nbflag = FALSE;
        cp3 = &vline[term.t_ncol];              /* Compute right match. */
        cp4 = &pline[term.t_ncol];
        while (cp3[-1] == cp4[-1]) {
                --cp3;
                --cp4;
                if (cp3[0] != ' ')              /* Note if any nonblank */
                        nbflag = TRUE;          /* in right match.      */
        }
        cp5 = cp3;
        if (nbflag == FALSE) {                  /* Erase to EOL ?       */
                while (cp5!=cp1 && cp5[-1]==' ')
                        --cp5;
                if ( ((int)cp3-(int)cp5) <= 3)  /* Use only if erase is */
                        cp5 = cp3;              /* fewer characters.    */
        }
        movecursor(row, (int)cp1-(int)&vline[0]);/* Go to start of line.*/
        while (cp1 != cp5) {                    /* Ordinary.            */
                (*term.t_putchar)(*cp1);
                ++ttcol;
                *cp2++ = *cp1++;
        }
        if (cp5 != cp3) {                       /* Erase.               */
                (*term.t_eeol)();
                while (cp1 != cp3)
                        *cp2++ = *cp1++;
        }
        *flags &= ~VFCHG;
#endif
}
 
/*
 * Redisplay the mode line for
 * the window pointed to by the "wp".
 * This is the only routine that has any idea
 * of how the modeline is formatted. You can
 * change the modeline format by hacking at
 * this routine. Called by "update" any time
 * there is a dirty window.
 */
modeline(wp)
register WINDOW *wp;
{
        register char   *cp;
        register int    c;
        register int    i;
        register int    n;
        register BUFFER *bp;
        register int    lchar;
        char            tline[82];
 
        n = wp->w_toprow+wp->w_ntrows;          /* Location.            */
        vscreen[n]->v_flag |= VFCHG;            /* Redraw next time.    */
        vtmove(n,0);
        if (wp == curwp)
                lchar = '=';
        else
                lchar = '-';
 
        vtputc(lchar);
        bp = wp->w_bufp;
        if ((bp->b_flag&BFCHG) != 0)            /* "*" if changed.      */
                vtputc('*');
        else
                vtputc(lchar);
        n  = 2;
#if     ST
        strcpy(tline," Uemail ST 3.3 (");       /* Buffer name.         */
#else
        strcpy(tline, "Uemail 3.3 (");
#endif
        /* display the modes */
        if (wp->w_bufp->b_bmode&BMCMODE)
                strcat(tline, "C");
        else if (wp->w_bufp->b_bmode&BMWRAP)
                strcat(tline, "Wrap");
        else
                strcat(tline, "Fundamental");
        strcat(tline,") ");
 
        cp = &tline[0];
        while ((c = *cp++) != 0) {
                vtputc(c);
                ++n;
        }
        vtputc(lchar);
        vtputc(lchar);
        vtputc(' ');
        n += 3;
        cp = &bp->b_bname[0];
        while ((c = *cp++) != 0) {
                vtputc(c);
                ++n;
        }
        vtputc(' ');
        vtputc(lchar);
        vtputc(lchar);
        n += 3;
        if (bp->b_fname[0] != 0) {              /* File name.           */
                cp = " File: ";
                while ((c = *cp++) != 0) {
                        vtputc(c);
                        ++n;
                }
                cp = &bp->b_fname[0];
                while ((c = *cp++) != 0) {
                        vtputc(c);
                        ++n;
                }
                vtputc(' ');
                ++n;
        }
#if     WFDEBUG
        vtputc(lchar);
        vtputc((wp->w_flag&WFMODE)!=0  ? 'M' : '-');
        vtputc((wp->w_flag&WFHARD)!=0  ? 'H' : '-');
        vtputc((wp->w_flag&WFEDIT)!=0  ? 'E' : '-');
        vtputc((wp->w_flag&WFMOVE)!=0  ? 'V' : '-');
        vtputc((wp->w_flag&WFFORCE)!=0 ? 'F' : '-');
        n += 6;
#endif
        while (n < term.t_ncol) {               /* Pad to full width.   */
                vtputc(lchar);
                ++n;
        }
}
 
upmode()        /* update all the mode lines */
{
        register WINDOW *wp;
 
        wp = wheadp;
        while (wp != NULL) {
                wp->w_flag |= WFMODE;
                wp = wp->w_wndp;
        }
}
 
/*
 * Send a command to the terminal
 * to move the hardware cursor to row "row"
 * and column "col". The row and column arguments
 * are origin 0. Optimize out random calls.
 * Update "ttrow" and "ttcol".
 */
movecursor(row, col)
register int row, col;
{
        if (row!=ttrow || col!=ttcol) {
                ttrow = row;
                ttcol = col;
                (*term.t_move)(row, col);
        }
}
 
/*
 * Erase the message line.
 * This is a special routine because
 * the message line is not considered to be
 * part of the virtual screen. It always works
 * immediately; the terminal buffer is flushed
 * via a call to the flusher (not on ST).
 */
mlerase()
{
        movecursor(term.t_nrow, 0);
#if     ST
        Bconout(2,0x1b);        /* ST Kill entire line command */
        Bconout(2,'l');
#else
        (*term.t_eeol)();
        (*term.t_flush)();
#endif
        mpresf = FALSE;
}
 
/*
 * Ask a yes or no question in
 * the message line. Return either TRUE,
 * FALSE, or ABORT. The ABORT status is returned
 * if the user bumps out of the question with
 * a ^G. Used any time a confirmation is
 * required.
 */
mlyesno(prompt)
char    *prompt;
{
        register int    c;
        char            buf[64];
 
        for (;;) {
                strcpy(buf, prompt);
                strcat(buf, " [y/n]? ");
                mlwrite(buf);
                /* get the response */
                c = (*term.t_getchar)();
 
                if (c == BELL)    /* Bail out! */
                        return(ABORT);
 
                if (c=='y' || c=='Y')
                        return(TRUE);
 
                if (c=='n' || c=='N')
                        return(FALSE);
        }
}
 
/*
 * Write a prompt into the message
 * line, then read back a response. Keep
 * track of the physical position of the cursor.
 * If we are in a keyboard macro throw the prompt
 * away, and return the remembered response. This
 * lets macros run at full speed. The reply is
 * always terminated by a carriage return. Handle
 * erase, kill, and abort keys.
 */
mlreply(prompt, buf, nbuf)
char    *prompt;
char    *buf;
int nbuf;
{
        return(mlreplt(prompt,buf,nbuf,'\n'));
}
 
/* A more generalized prompt/reply function allowing the caller
 * to specify the proper terminator. If the terminator is not
 * a return ('\n') it will echo as "<NL>"
 */
mlreplt(prompt, buf, nbuf, eolchar)
char *prompt;
char *buf;
int nbuf;
char eolchar;
{
        register int    cpos;
        register int    i;
        register int    c;
 
        cpos = 0;
        if (kbdmop != NULL) {
                while ((c = *kbdmop++) != '\0')
                        buf[cpos++] = c;
                buf[cpos] = 0;
                if (buf[0] == 0)
                        return (FALSE);
                return (TRUE);
        }
#if     ST
        (*term.t_move)(term.t_nrow, 0); /* in case we're in terminal mode */
#endif
        mlwrite(prompt);
        for (;;) {
        /* get a character from the user. if it is a <ret>, change it
         * to a <NL>
         */
                c = (*term.t_getchar)();
                if (c == 0x0d)
                        c = '\n';
                if (c == eolchar) {
                        buf[cpos++] = 0;
                        if (kbdmip != NULL) {
                                if (kbdmip+cpos > &kbdm[NKBDM-3]) {
                                        ctrlg(FALSE, 0);
                                        (*term.t_flush)();
                                        return(ABORT);
                                }
                                for (i=0; i<cpos; ++i)
                                        *kbdmip++ = buf[i];
                        }
                        (*term.t_putchar)('\r');
                        ttcol = 0;
                        (*term.t_flush)();
                        if (buf[0] == 0)
                                return(FALSE);
                        return(TRUE);
                } else if (c == 0x07) { /* Bell, abort */
                        (*term.t_putchar)('^');
                        (*term.t_putchar)('G');
                        ttcol += 2;
                        ctrlg(FALSE, 0);
                        (*term.t_flush)();
                        return(ABORT);
                } else if (c == 0x7F || c == 0x08 || c == 0x02) {
                        /* rubout/erase/cursor left */
                        if (cpos != 0) {
                                (*term.t_putchar)('\b');
                                (*term.t_putchar)(' ');
                                (*term.t_putchar)('\b');
                                --ttcol;
                                if (buf[--cpos] < 0x20) {
                                        (*term.t_putchar)('\b');
                                        (*term.t_putchar)(' ');
                                        (*term.t_putchar)('\b');
                                        --ttcol;
                                }
                                if (buf[cpos] == '\n') {
                                        (*term.t_putchar)('\b');
                                        (*term.t_putchar)('\b');
                                        (*term.t_putchar)(' ');
                                        (*term.t_putchar)(' ');
                                        (*term.t_putchar)('\b');
                                        (*term.t_putchar)('\b');
                                        --ttcol;
                                        --ttcol;
                                }
                                (*term.t_flush)();
                        }
                } else if (c == 0x15) { /* C-U, kill */
                        while (cpos != 0) {
                                (*term.t_putchar)('\b');
                                (*term.t_putchar)(' ');
                                (*term.t_putchar)('\b');
                                --ttcol;
                                if (buf[--cpos] < 0x20) {
                                        (*term.t_putchar)('\b');
                                        (*term.t_putchar)(' ');
                                        (*term.t_putchar)('\b');
                                        --ttcol;
                                }
                        }
                        (*term.t_flush)();
                } else {
                        if (cpos < nbuf-1) {
                                buf[cpos++] = c;
                                if ((c < ' ') && (c != '\n')) {
                                        (*term.t_putchar)('^');
                                        ++ttcol;
                                        c ^= 0x40;
                                }
                                if (c != '\n')
                                        (*term.t_putchar)(c);
                                else {  /* put out <NL> for <ret> */
                                        (*term.t_putchar)('<');
                                        (*term.t_putchar)('N');
                                        (*term.t_putchar)('L');
                                        (*term.t_putchar)('>');
                                        ttcol += 3;
                                }
                        ++ttcol;
                        (*term.t_flush)();
                        }
                }
        }
}
 
/*
 * Write a message into the message
 * line. Keep track of the physical cursor
 * position. A small class of printf like format
 * items is handled. Assumes the stack grows
 * down; this assumption is made by the "++"
 * in the argument scan loop. Set the "message
 * line" flag TRUE.  For the ST this function
 * uses sprintf() to get at ULONG and FLOAT
 * arguments.  I couldn't get *VARARGS* to work
 * so I kludged with the 10 long args.  Is this
 * worth it?
 */
mlwrite(fmt, arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10)
char    *fmt;
#if     ST
long    arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10;
{
        /* Use the built-in functions on the ST.
         * This lets us get to unsigned longs and floats
         * but limits the number of arguments to 10.
         */
        mlerase();
        mpresf = TRUE;
        sprintf(mlbuf,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10);
        ttputc(0x1b); ttputc('f');      /* hide cursor */
        Cconws(mlbuf);
        (*term.t_eeol)();
        ttputc(0x1b); ttputc('e');      /* show cursor */
}
#else
int arg;
{
        register int    c;
        register char   *ap;
 
        movecursor(term.t_nrow, 0);
        ap = (char *) &arg;
        while ((c = *fmt++) != 0) {
                if (c != '%') {
                        (*term.t_putchar)(c);
                        ++ttcol;
                } else {
                        c = *fmt++;
                        switch (c) {
                        case 'd':
                                mlputi(*(int *)ap, 10);
                                ap += sizeof(int);
                                break;
 
                        case 'o':
                                mlputi(*(int *)ap,  8);
                                ap += sizeof(int);
                                break;
 
                        case 'x':
                                mlputi(*(int *)ap, 16);
                                ap += sizeof(int);
                                break;
 
                        case 'D':
                                mlputli(*(long *)ap, 10);
                                ap += sizeof(long);
                                break;
 
                        case 's':
                                mlputs(*(char **)ap);
                                ap += sizeof(char *);
                                break;
 
                        default:
                                (*term.t_putchar)(c);
                                ++ttcol;
                        }
                }
        }
        (*term.t_eeol)();
        (*term.t_flush)();
        mpresf = TRUE;
}
 
/*
 * Write out a string.
 * Update the physical cursor position.
 * This assumes that the characters in the
 * string all have width "1"; if this is
 * not the case things will get screwed up
 * a little.
 */
mlputs(s)
register char   *s;
{
        register int    c;
 
        while ((c = *s++) != 0) {
                (*term.t_putchar)(c);
                ++ttcol;
        }
}
 
/*
 * Write out an integer, in
 * the specified radix. Update the physical
 * cursor position. This will not handle any
 * negative numbers; maybe it should.
 */
mlputi(i, r)
int i, r;
{
        register int    q;
        static char hexdigits[] = "0123456789ABCDEF";
 
        if (i < 0) {
                i = -i;
                (*term.t_putchar)('-');
        }
        q = i/r;
        if (q != 0)
                mlputi(q, r);
        (*term.t_putchar)(hexdigits[i%r]);
        ++ttcol;
}
 
/*
 * do the same except as a long integer.
 */
mlputli(l, r)
long l;
int r;
{
        register long q;
 
        if (l < 0) {
                l = -l;
                (*term.t_putchar)('-');
        }
        q = l/r;
        if (q != 0)
                mlputli(q, r);
        (*term.t_putchar)((int)(l%r)+'0');
        ++ttcol;
}
#endif
SHAR_EOF
#       End of shell archive
exit 0
%NONAME-W-NOMSG, Message number 00000000
Technical Details
Message-ID: <8702041624.AA16231@ucbvax.Berkeley.EDU>
Path: arc1-ca.pugleaf.net!utzoo!watmath!clyde!cbatt!ucbvax!ULKYVX.BITNET!RDROYA01

Show Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: arc1-ca.pugleaf.net!utzoo!watmath!clyde!cbatt!ucbvax!ULKYVX.BITNET!RDROYA01
From: RDROYA01@ULKYVX.BITNET.UUCP
Newsgroups: comp.sys.atari.st
Subject: Uemail source (4 of 12)
Message-ID: <8702041624.AA16231@ucbvax.Berkeley.EDU>
Date: Wed, 4-Feb-87 10:08:00 EST
Article-I.D.: ucbvax.8702041624.AA16231
Posted: Wed Feb  4 10:08:00 1987
Date-Received: Sat, 7-Feb-87 05:07:43 EST
Sender: daemon@ucbvax.BERKELEY.EDU
Organization: University of Louisville
Lines: 1004