v07i051: CRISP release 1.9 part 30/32
Brandon S. Allbery - comp.sources.misc
allbery at uunet.UU.NET
Thu Jun 22 13:57:41 AEST 1989
Posting-number: Volume 7, Issue 51
Submitted-by: fox at marlow.UUCP (Paul Fox)
Archive-name: crisp1.9/part31
#!/bin/sh
# this is part 10 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file ./tty.c continued
#
CurArch=10
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
exit 1; fi
( read Scheck
if test "$Scheck" != $CurArch
then echo "Please unpack part $Scheck next!"
exit 1;
else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file ./tty.c"
sed 's/^X//' << 'SHAR_EOF' >> ./tty.c
X char *bg[16];
X } COLORS;
XCOLORS colors = {
X {"\033[0;30m", "\033[0;34m", "\033[0;32m", "\033[0;36m", /* Foreground. */
X "\033[0;31m", "\033[0;35m", "\033[0;33m", "\033[0;37m",
X "\033[30;1m", "\033[34;1m", "\033[32;1m", "\033[36;1m",
X "\033[31;1m", "\033[35;1m", "\033[33;1m", "\033[37;1m"},
X {"\033[40m", "\033[44m", "\033[42m", "\033[46m", /* Background. */
X "\033[41m", "\033[45m", "\033[43m", "\033[47m",
X "\033[40;1m", "\033[44;1m", "\033[42;1m", "\033[46;1m",
X "\033[41;1m", "\033[45;1m", "\033[43;1m", "\033[47;1m"},
X };
X
Xint LI; /* standard # lines */
Xint AM; /* Has auto-margins. */
Xchar
X *AL, /* add line */
X *BC, /* Backspace character. */
X *CD, /* Clear to end of display. */
X *CE, /* Clear to end of line. */
X *CL, /* Clear screen */
X *CM, /* Cursor motion */
X *CS, /* set scroll region */
X *DC, /* Delete a character. */
X *DL, /* del line */
X *EI, /* end insert mode */
X *HO, /* Home cursor. */
X *IC, /* insert a single space */
X *IM, /* insert mode */
X *IS, /* Init sequence. */
X *MB, /* Turn on blinking. */
X *MD, /* Make bold */
X *ME, /* Turn off all attributes. */
X *RS, /* Reset sequence. */
X *SE, /* End standout mode. */
X *SO, /* Start standout mode. */
X *SR, /* back index (used with scroll region */
X *TE, /* term end --- end using cursor motion */
X *TI, /* term init -- start using cursor motion */
X *UP, /* Cursor up. */
X *pAL, /* parameterized add line */
X *pDL; /* parameterized delete line */
X
Xchar *K[NFKEYS]; /* other function key codes */
Xchar *KS, *KE; /* enter keypad mode, exit keypad mode */
Xint SG; /* number of glitches, 0 for invisable, -1 for none */
Xchar *termcap_strings =
X"AL DL al bc cd ce cl cm cs dc dl ei ho ic im is ks ke mb me mr rs se so sr te ti up ";
Xchar **termcap_ptrs[] = {
X &pAL, &pDL,
X &AL, &BC, &CD, &CE, &CL, &CM, &CS, &DC, &DL, &EI, &HO, &IC,
X &IM, &IS, &KS, &KE, &MB, &MD, &ME, &RS, &SE, &SO, &SR, &TE, &TI, &UP
X };
X
X/*
X * Initialize the terminal when the editor
X * gets started up.
X */
Xstatic char tcbuf[TCAPSLEN];
X
Xvoid
Xttinit()
X{
X char *ggetenv();
X char *p, *tgetstr();
X char *tv_stype;
X char *tptr;
X char ***cptr;
X char *cp;
X
X if ((tv_stype = ggetenv("TERM")) == NULL)
X panic("Environment variable TERM not defined!");
X
X if((tgetent(tcbuf, tv_stype)) != 1) {
X extern char *termcap_dir;
X fprintf(stderr,
X "Terminal type '%s' not found in %s.\n",
X tv_stype, termcap_dir);
X exit(1);
X }
X
X p = tcapbuf;
X
X LI = tgetnum("li");
X AM = tgetflag("am");
X SG = tgetnum("sg");
X
X cptr = termcap_ptrs;
X for (tptr = termcap_strings; *tptr; tptr += 3) {
X char *cp;
X char tmpbuf[3];
X tmpbuf[0] = tptr[0];
X tmpbuf[1] = tptr[1];
X tmpbuf[2] = 0;
X if ((cp = tgetstr(tmpbuf, &p)) && *cp)
X **cptr = cp;
X cptr++;
X }
X /*PC = pc ? *pc : 0;*/
X if (cp = tgetstr("kh", &p))
X K[KEY_HOME - KFIRST] = cp;
X if (cp = tgetstr("ku", &p))
X K[KEY_UP - KFIRST] = cp;
X if (cp = tgetstr("kd", &p))
X K[KEY_DOWN - KFIRST] = cp;
X if (cp = tgetstr("kl", &p))
X K[KEY_LEFT - KFIRST] = cp;
X if (cp = tgetstr("kr", &p))
X K[KEY_RIGHT - KFIRST] = cp;
X if (cp = tgetstr("EN", &p))
X K[KEY_END - KFIRST] = cp;
X if (cp = tgetstr("PU", &p))
X K[KEY_PAGEUP - KFIRST] = cp;
X if (cp = tgetstr("PD", &p))
X K[KEY_PAGEDOWN - KFIRST] = cp;
X
X if (CM == NULL)
X panic("No cursor move (cm) capability in termcap.");
X if (UP == NULL)
X panic("No upline (up) capability in termcap.");
X# if defined(SIGWINCH)
X {void ttwinch();
X signal(SIGWINCH, ttwinch);
X }
X# endif
X
X if(!CE) tceeol = ncol;
X else tceeol = charcost(CE);
X
X /* Estimate cost of inserting a line */
X if (CS && SR) tcinsl = charcost(CS)*2 + charcost(SR);
X else if (pAL) tcinsl = charcost(pAL);
X else if (AL) tcinsl = charcost(AL);
X else tcinsl = HUGE; /* make this cost high enough */
X
X /* Estimate cost of deleting a line */
X if (CS) tcdell = charcost(CS)*2 + 1;
X else if (pDL) tcdell = charcost(pDL);
X else if (DL) tcdell = charcost(DL);
X else tcdell = HUGE; /* make this cost high enough */
X
X /* Flag to indicate that we can both insert and delete lines */
X insdel = (AL || pAL) && (DL || pDL);
X
X if (p >= &tcapbuf[TCAPSLEN])
X panic("Terminal description too big!\n");
X
X /* tgoto() doesnt work properly with real termcap -- leave *
X /* this in for now. */
X# if 1 || defined(MY_TERMCAP)
X {
X void close_termcap();
X close_termcap();
X }
X# endif
X}
Xttinit1()
X{
X ttresize(); /* set nrow & ncol */
X flush_col_cache();
X if (TI)
X putpad (TI); /* init the term */
X if (IS)
X putpad (IS); /* init the term */
X if (KS)
X putpad(KS);
X}
X/*----------------------------------------
X/* Routine to decypher termcap style strings.
X/* Needed by code in set_term_escapes.
X/*----------------------------------------*/
X
X# define XDIGIT(x) (x <= '9' ? x - '0' : \
X (x >= 'a' && x <= 'z') ? x - 'a' + 10 : \
X (x - 'A' + 10))
Xchar *
Xtcopy_string(dp, bp, delim)
Xregister char *dp, *bp;
X{ register int n;
X
X while (*bp != delim && *bp) {
X if (*bp == '^') {
X *dp++ = *++bp & 0x1f;
X bp++;
X continue;
X }
X if (*bp != '\\') {
X *dp++ = *bp++;
X continue;
X }
X switch (*++bp) {
X case 'E': *dp++ = 0x1b; break;
X case 'r': *dp++ = '\r'; break;
X case 'n': *dp++ = '\n'; break;
X case 't': *dp++ = '\t'; break;
X case 'b': *dp++ = '\b'; break;
X case 'f': *dp++ = '\f'; break;
X case '0': case '1': case '2': case '3':
X n = 0;
X while (*bp >= '0' && *bp <= '7')
X n = 8*n + *bp++ - '0';
X bp--;
X *dp++ = (char) n;
X break;
X case 'x':
X bp++;
X n = XDIGIT(*bp);
X bp++;
X n = n * 16 + XDIGIT(*bp);
X *dp++ = (char) n;
X break;
X default: *dp++ = *bp; break;
X }
X bp++;
X }
X *dp++ = NULL;
X return dp;
X}
X
X/*
X * Clean up the terminal, in anticipation of
X * a return to the command interpreter. This is a no-op
X * on the ANSI display. On the SCALD display, it sets the
X * window back to half screen scrolling. Perhaps it should
X * query the display for the increment, and put it
X * back to what it was.
X */
Xvoid
Xtttidy()
X{
X if (RS && *RS) putpad (RS); /* set the term back to normal mode */
X if (TE && *TE) putpad (TE); /* set the term back to normal mode */
X if (KE)
X putpad(KE);
X}
X
X/*
X * Move the cursor to the specified
X * origin 0 row and column position. Try to
X * optimize out extra moves; redisplay may
X * have left the cursor in the right
X * location last time!
X */
Xvoid
Xttmove(row, col)
Xu_int16 row;
Xu_int16 col;
X{
X char *tgoto();
X extern char *HO;
X if (ttrow == row && ttcol == col)
X return;
X
X if (col == 0 && row == 0 && HO)
X putpad(HO);
X else if (ttcol == col && row == ttrow+1)
X ttputpad('\n');
X else if (ttcol == col+1 && row == ttrow+1) {
X ttputpad('\n');
X ttputpad('\b');
X }
X else if (ttcol-1 == col && row == ttrow)
X ttputpad('\b');
X else if (ttrow == row && pt.pt_escC[0] && col > ttcol && ttcol > 1) {
X putpad(tgoto(pt.pt_escC, 0, col - ttcol));
X }
X else {
X char *cp = tgoto(CM, (int) col, (int) row);
X/* int len = strlen(cp);
X if (row == ttrow && col + len < ttcol) {
X int i;
X for (i = 0; i++ < ttcol - col; i++)
X ttputpad('\b');
X }
X else*/
X putpad(cp);
X }
X ttrow = row;
X ttcol = col;
X}
X/*
X * Erase to end of line.
X */
Xvoid
Xtteeol()
X{
X if(CE) putpad(CE);
X else {
X register int i=ncol-ttcol;
X while(i--) ttputc(' ');
X ttrow = ttcol = HUGE;
X }
X}
X
Xttclear()
X{
X if (CL == NULL) {
X ttmove((u_int16) 0, (u_int16) 0);
X tteeop();
X }
X else {
X ttrow = 0;
X ttcol = 0;
X putpad(CL);
X }
X}
X/*
X * Erase to end of page.
X */
Xvoid
Xtteeop()
X{
X if(CD) putpad(CD);
X else {
X putpad(CE);
X if (insdel) ttdell(ttrow + 1, LI, LI - ttrow - 1);
X else { /* do it by hand */
X register int line;
X for (line = ttrow + 1; line <= LI; ++line) {
X ttmove((u_int16) line, (u_int16) 0);
X tteeol();
X }
X }
X ttrow = ttcol = HUGE;
X }
X}
X
X/*
X * Make a noise.
X */
Xvoid
Xttbeep()
X{
X ttputc(BEL);
X /*----------------------------------------
X /* Adjust cursor because ttputc() thinks
X /* BEL moves the cursor.
X /*----------------------------------------*/
X ttcol--;
X ttflush();
X}
Xbeep()
X{
X ttbeep();
X return 0;
X}
X
X/*
X * Insert nchunk blank line(s) onto the
X * screen, scrolling the last line on the
X * screen off the bottom. Use the scrolling
X * region if possible for a smoother display.
X * If no scrolling region, use a set
X * of insert and delete line sequences
X */
Xttinsl(row, bot, nchunk)
X{
X register int i;
X
X if (row == bot) { /* Case of one line insert is special */
X ttmove((u_int16) row, (u_int16) 0);
X tteeol();
X return TRUE;
X }
X if (CS && SR) { /* Use scroll region and back index */
X ttwindow(row,bot);
X ttmove((u_int16) row, (u_int16) 0);
X while (nchunk--) putpad(SR);
X /*ttnowindow();*/
X return TRUE;
X }
X if (insdel) {
X ttmove((u_int16) (1+bot-nchunk), (u_int16) 0);
X if (pDL)
X putpad (tgoto(pDL, 0, nchunk));
X else
X for (i=0; i<nchunk; i++)/* For all lines in the chunk */
X putpad(DL);
X ttmove((u_int16) row, (u_int16) 0);
X if (pAL)
X putpad (tgoto(pAL, 0, nchunk));
X else
X for (i=0; i<nchunk; i++)/* For all lines in the chunk*/
X putpad(AL);
X ttrow = HUGE;
X ttcol = HUGE;
X return TRUE;
X }
X return FALSE;
X}
X
X/*
X * Delete nchunk line(s) from "row", replacing the
X * bottom line on the screen with a blank line.
X * Unless we're using the scrolling region, this is
X * done with a crafty sequences of insert and delete
X * lines. The presence of the echo area makes a
X * boundry condition go away.
X */
Xttdell(row, bot, nchunk)
X{ register int i;
X
X if (row == bot) { /* One line special case */
X ttmove((u_int16) row, (u_int16) 0);
X tteeol();
X return TRUE;
X }
X if (CS) { /* scrolling region */
X ttwindow(row, bot);
X ttmove((u_int16) bot, (u_int16) 0);
X while (nchunk--) ttputc(LF);
X return TRUE;
X }
X if(insdel) {
X ttmove((u_int16) row, (u_int16) 0);
X if (pDL)
X putpad (tgoto(pDL, 0, nchunk));
X else
X for (i=0; i<nchunk; i++)
X putpad(DL);
X ttmove((u_int16) (1+bot-nchunk), (u_int16) 0);
X if (pAL)
X putpad (tgoto(pAL, 0, nchunk));
X else
X for (i=0; i<nchunk; i++)
X putpad(AL);
X ttrow = HUGE;
X ttcol = HUGE;
X return TRUE;
X }
X return FALSE;
X}
X
X/*
X * This routine sets the scrolling window
X * on the display to go from line "top" to line
X * "bot" (origin 0, inclusive). The caller checks
X * for the pathalogical 1 line scroll window that
X * doesn't work right, and avoids it. The "ttrow"
X * and "ttcol" variables are set to a crazy value
X * to ensure that the next call to "ttmove" does
X * not turn into a no-op (the window adjustment
X * moves the cursor).
X *
X */
Xvoid
Xttwindow(top, bot)
X{
X if (CS && (tttop!=top || ttbot!=bot)) {
X putpad(tgoto(CS, bot, top));
X ttrow = HUGE; /* Unknown. */
X ttcol = HUGE;
X tttop = top; /* Remember region. */
X ttbot = bot;
X }
X}
X
X/*
X * Set the current writing color to the
X * specified color. Watch for color changes that are
X * not going to do anything (the color is already right)
X * and don't send anything to the display.
X * The rainbow version does this in putline.s on a
X * line by line basis, so don't bother sending
X * out the color shift.
X */
Xstatic int tthue = -1;
Xstatic int tt_fg = -1;
Xstatic int tt_bg = -1;
Xstatic int gso = FALSE;
Xvoid
Xflush_col_cache()
X{
X tthue = tt_fg = tt_bg = -1;
X}
Xvoid
Xttcolor(color)
X{ int fg, bg;
X
X if (tthue == color)
X return;
X tthue = color;
X if (!pt.pt_color) {
X if (color == FG(col_table.c_normal) ||
X color == FG(col_table.c_messages)) {
X putpad(SE);
X }
X else if (color == FG(col_table.c_select) ||
X color == FG(col_table.c_error)) {
X putpad(SE);
X putpad(MD);
X }
X else {
X putpad(SO);
X }
X return;
X }
X fg = (color & FG_COLOR) >> FG_SHIFT;
X bg = (color & BG_COLOR) >> BG_SHIFT;
X if (fg != tt_fg) {
X putpad(colors.fg[fg]);
X tt_fg = fg;
X }
X if (bg != tt_bg) {
X putpad(colors.bg[bg]);
X tt_bg = bg;
X }
X}
Xvoid
Xttresize()
X{
X setttysize();
X if (nrow < 1)
X nrow = 1;
X if (ncol < 1)
X ncol = 1;
X}
Xvoid
Xttwinch()
X{
X# if defined(SIGWINCH)
X void ttwinch1();
X
X int oncol = ncol;
X int onrow = nrow;
X ttresize();
X signal(SIGWINCH, ttwinch);
X update();
X# endif
X}
Xvoid
Xttwinch1(oncol, onrow, ncol, nrow)
X{ register WINDOW *wp;
X extern int sgarbf;
X int diffcol, diffrow;
X
X vtinit1();
X diffcol = ncol - oncol;
X diffrow = nrow - onrow;
X for (wp = wheadp; wp; wp = wp->w_wndp) {
X int right_edge;
X int last_line;
X /*----------------------------------------
X /* Adjust window width only if its right
X /* hand edge touches the right hand edge
X /* of the window.
X /*----------------------------------------*/
X right_edge = wp->w_x + wp->w_w;
X last_line = wp->w_y + wp->w_h;
X if (wp->w_tiled)
X right_edge++;
X if (right_edge == oncol)
X wp->w_w += diffcol;
X /*----------------------------------------
X /* Adjust window height if window's
X /* bottom line touches bottom of screen.
X /*----------------------------------------*/
X if (last_line == onrow - 3)
X wp->w_h += diffrow;
X }
X sgarbf = TRUE;
X}
X
Xstatic int cci;
X
Xstatic void /* fake char output for charcost() */
Xfakec(c) char c;
X{
X#ifdef lint
X c++;
X#endif
X cci++;
X}
X
X/* calculate the cost of doing string s */
Xcharcost (s) char *s;
X{
X cci = 0;
X
X tputs(s, nrow, fakec);
X return cci;
X}
Xvoid
Xputpad(str)
Xchar *str;
X{
X if (str == NULL)
X return;
X/* if (str == SO) {
X if (gso)
X return;
X gso = TRUE;
X }
X else if (str == SE) {
X if (!gso)
X return;
X gso = FALSE;
X } */
X tputs(str, 1, ttputpad);
X}
Xvoid
Xttspace(n, space, stay)
X{ u_int16 oldrow = ttrow;
X u_int16 oldcol = ttcol;
X
X if (n <= 0)
X return;
X ttputc(space);
X if (--n <= 0)
X return;
X if (pt.pt_space[0]) {
X putpad(tgoto(pt.pt_space, 0, n));
X if (!stay)
X ttmove(oldrow, oldcol + n + 1);
X }
X else {
X while (n-- > 0)
X ttputc(space);
X }
X if (stay)
X ttmove(oldrow, oldcol);
X
X}
Xttrepeat(ch, n)
X{
X if (n > 12 && pt.pt_repeat[0]) {
X ttputc(ch);
X putpad(tgoto(pt.pt_repeat, 0, n-1));
X ttmove(ttrow, ttcol + n - 1);
X }
X while (n-- > 0)
X ttputc(ch);
X
X
X}
X
SHAR_EOF
echo "File ./tty.c is complete"
chmod 0444 ./tty.c || echo "restore of ./tty.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./ttyio.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./ttyio.c &&
X/**************************************************************
X *
X * CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X * (C) Paul Fox, 1989
X * 43, Jerome Close Tel: +44 6284 4222
X * Marlow
X * Bucks.
X * England SL7 1TX
X *
X *
X * Please See COPYRIGHT notice.
X *
X **************************************************************/
X
X# include "list.h"
XSCCSID("@(#) ttyio.c 1.15, (C) P. Fox");
X
X# if defined(SUN)
X# include <sys/time.h>
X# include <termio.h>
X# endif
X# if defined(XENIX)
X# include <termio.h>
X# endif
X
X
X
X# define TTY_FD 0
X# define BIT(x) (1 << (x))
X
X# if defined(SELECT)
X# include <sys/types.h>
X# include <sys/time.h>
X
X# endif
Xlong sel_bits = BIT(TTY_FD);
X
X# define CENTISECONDS 5 /* x .01 seconds */
Xvoid ttflush();
X
X#define NOBUF 136 /* Output buffer size. */
X
Xlong st_charout; /* Number of characters output. */
X
Xchar obuf[NOBUF+10]; /* Output buffer. */
Xint nobuf; /* buffer count */
Xint timeout_flag = FALSE; /* TRUE when we are in VMIN/VTIME mode.*/
Xint reading_char;
Xunsigned char kbdq = 0;
Xextern int ega43_flag;
Xint old_ega_flag = -1;
X
Xu_int16 nrow; /* Terminal size, rows. */
Xu_int16 ncol; /* Terminal size, columns. */
X
X/*
X * This function gets called once, to set up
X * the terminal channel. This version turns off flow
X * control. This may be wrong for your system, but no
X * good solution has really been found (daveb).
X */
Xvoid
Xttopen()
X{
X sys_open();
X ttinit1();
X}
Xvoid
Xtttimeout(yes)
X{
X if (yes == timeout_flag)
X return;
X timeout_flag = yes;
X sys_timeout(yes);
X}
X/*
X * This function gets called just
X * before we go back home to the shell. Put all of
X * the terminal parameters back.
X */
Xvoid
Xttclose()
X{
X ttflush();
X sys_close();
X old_ega_flag = -1;
X}
X
X/*
X * Write character to the display.
X * Characters are buffered up, to make things
X * a little bit more efficient.
X */
Xvoid
Xttputpad(c)
X{
X if (nobuf >= NOBUF)
X ttflush();
X obuf[nobuf++] = (char) c;
X}
Xvoid
Xttputs(str)
Xregister char *str;
X{
X while (*str)
X ttputc(*str++);
X}
Xvoid
Xttputc(c)
Xregister int c;
X{
X extern int scr_attr;
X register int color = c & COLOR_MASK;
X extern int AM;
X
X if (nobuf >= NOBUF)
X ttflush();
X
X ttcolor(color);
X
X c &= 0xff;
X/* if (c & 0x80 && c < (0x80 + ' ')) {*/
X if (c & 0x80) {
X if (c >= CH_MIN && c <= CH_MAX) {
X char *cp = "?";
X switch (c) {
X case CH_HORIZONTAL: cp = pt.pt_horizontal; break;
X case CH_VERTICAL: cp = pt.pt_vertical; break;
X case CH_TOP_LEFT: cp = pt.pt_top_left; break;
X case CH_TOP_RIGHT: cp = pt.pt_top_right; break;
X case CH_BOT_LEFT: cp = pt.pt_bot_left; break;
X case CH_BOT_RIGHT: cp = pt.pt_bot_right; break;
X case CH_TOP_JOIN: cp = pt.pt_top_join; break;
X case CH_BOT_JOIN: cp = pt.pt_bot_join; break;
X case CH_LEFT_JOIN: cp = pt.pt_left_join; break;
X case CH_RIGHT_JOIN: cp = pt.pt_right_join; break;
X case CH_CROSS: cp = pt.pt_cross; break;
X }
X strcpy(obuf + nobuf, cp);
X nobuf += strlen(cp);
X }
X else if (c >= 0x80 + ' ')
X goto hell;
X else {
X c &= 0x7f;
X if (c == 0x1b && pt.pt_escape[0])
X strcpy(obuf+nobuf, pt.pt_escape);
X else
X sprintf(obuf+nobuf, pt.pt_character, c ? c : 0x80);
X nobuf += strlen(obuf+nobuf);
X }
X goto end_of_function;
X }
X if (c == 0)
X return;
Xhell:
X obuf[nobuf++] = (char) c;
X if (c == '\b') {
X ttcol--;
X return;
X }
Xend_of_function:
X if (++ttcol >= ncol && AM) {
X ttcol = 0;
X ttrow++;
X }
X}
X
Xvoid
Xttflush()
X{ extern int background;
X
X if (nobuf != 0) {
X st_charout += nobuf;
X if (background == FALSE)
X sys_write(1, obuf, nobuf);
X nobuf = 0;
X }
X}
XKEY
Xgetkey()
X{
X int n;
X unsigned char ch;
X extern int num_pty;
X extern long time_last_key_pressed;
X KEY key;
X static unsigned char buf[32]; /* Buffer for current key being read in */
X static unsigned char *bufptr = NULL;
X unsigned char *cp = buf;
X int pass2 = FALSE;
X extern int push_cnt;
X# if defined(SELECT)
X struct timeval timeout;
X struct timeval *tp = NULL;
X
X timeout.tv_sec = 0;
X timeout.tv_usec = 0;
X# endif
X
X if (push_cnt)
X return get_push();
X
X if (bufptr) {
X ch = *bufptr++;
X if (*bufptr == NULL)
X bufptr = NULL;
X return ch;
X }
X
X while (1) {
X extern int child_sig;
X extern void proc_wait();
X /*----------------------------------------
X /* Check to see if clock has gone off
X /* and we need to call somebody. We can
X /* only safely do this whilst we are NOT
X /* reading a character from the keyboard.
X /*----------------------------------------*/
X clock_check();
X if (kbdq) {
X ch = kbdq;
X kbdq = 0;
X goto got_char;
X }
X /*----------------------------------------
X /* If SIGCLD gone off then we should be
X /* safe here to go and process it.
X /*----------------------------------------*/
X if (child_sig)
X proc_wait(-1);
X
X reading_char = TRUE;
X# if defined(SELECT)
X if (pass2) {
X timeout.tv_usec = CENTISECONDS * 100 * 1000;
X tp = &timeout;
X }
X if (tp || num_pty) {
X int fd, bits;
X long readbits = sel_bits;
X long kbd_ready;
X long pty_ready;
X int nfds = select(32, &readbits, (long *) NULL, (long *) NULL,
X tp);
X if (nfds < 0)
X continue;
X kbd_ready = BIT(TTY_FD) & readbits;
X pty_ready = FALSE;
X /*----------------------------------------
X /* Handle all pty's first.
X /*----------------------------------------*/
X for (fd = 0, bits = 0; readbits && bits < 32;
X bits++, readbits >>= 1, fd++) {
X if (fd == TTY_FD)
X continue;
X if ((BIT(fd) & readbits) == 0)
X continue;
X p_poll();
X pty_ready = TRUE;
X }
X if (kbdq)
X continue;
X if (!kbd_ready) {
X if (tp && pty_ready == FALSE)
X goto return_ch;
X continue;
X }
X }
X# endif
X# if !defined(SELECT)
X tttimeout(pass2);
X# endif
X /*----------------------------------------
X /* Check to see if we have anything in
X /* playback buffer, before finally going
X /* to the keyboard for a character.
X /*----------------------------------------*/
X if ((ch = grab_char()) == 0) {
X if (sys_getchar(TTY_FD, &ch, 1) != 1) {
X if (pass2)
X goto return_ch;
X continue;
X }
X }
X
Xgot_char:
X reading_char = FALSE;
X *cp++ = ch;
X *cp = NULL;
X time_last_key_pressed = time((long *) 0);
X key = check_key(buf, cp - buf);
X if (key > 0) {
X store_char(key);
X return key;
X }
X if (key == 0) {
Xreturn_ch:
X if (buf[1])
X bufptr = &buf[1];
X store_char (buf[0]);
X return buf[0];
X }
X pass2 = TRUE;
X }
X}
X
Xtypeahead()
X{
X if (kbdq)
X return kbdq;
X
X if (kbdq = grab_char())
X return kbdq;
X
X kbdq = sys_checkc();
X return kbdq;
X}
X
X
Xvoid
Xpanic(s)
Xchar *s;
X{
X u_close();
X vttidy();
X fprintf(stderr, "CRISP PANIC: %s\r\n", s);
X exit(1);
X}
X
Xdo_ega()
X{ int arg = argv[1].l_flags == F_NULL ? 0 : argv[1].l_int;
X
X accumulator = ega43_flag ? 43 : 25;
X if (argv[1].l_flags == F_NULL)
X return;
X
X if (arg == 43)
X arg = 1;
X else if (arg == 25)
X arg = 0;
X ega_switch(arg);
X}
Xvoid
Xsetttysize()
X{ extern char *ggetenv();
X extern int AM;
X
X#ifdef TIOCGWINSZ
X struct winsize winsize;
X
X if (ioctl(0, TIOCGWINSZ, (char *) &winsize) == 0) {
X nrow = winsize.ws_row;
X ncol = winsize.ws_col;
X }
X if (nrow == 0 || ncol == 0)
X#endif
X if ((nrow= (u_int16) tgetnum ("li")) == 0
X || (ncol= (u_int16) tgetnum ("co")) == 0) {
X nrow = 24;
X ncol = 80;
X }
X# if defined(CONS_GET)
X {extern int console_mode;
X if (console_mode > 0) {
X switch (console_mode) {
X case M_ENH_C80x43:
X ega_switch(1);
X nrow = 43;
X break;
X case M_ENH_C80x25:
X ega_switch(0);
X nrow = 25;
X break;
X }
X }
X }
X# endif
X if (ggetenv("LINES")) {
X nrow = atoi(ggetenv("LINES"));
X AM = FALSE;
X }
X if (ggetenv("COLUMNS")) {
X ncol = atoi(ggetenv("COLUMNS"));
X AM = FALSE;
X }
X}
Xega_switch(flag)
X{ extern int sgarbf;
X extern void ttwinch1();
X int onrow = nrow;
X
X if (flag)
X flag = 1;
X
X if (old_ega_flag == flag)
X return;
X
X old_ega_flag = ega43_flag = flag;
X if (flag) {
X# if defined(SW_ENHC80x43)
X ioctl(1, SW_ENHC80x43, 1);
X nrow = 43;
X# endif
X ttwinch1(ncol, onrow, ncol, nrow);
X }
X else {
X# if defined(SW_ENHC80x25)
X ioctl(1, SW_ENHC80x25, 1);
X nrow = 25;
X# endif
X ttwinch1(ncol, onrow, ncol, nrow);
X }
X flush_col_cache();
X}
X
SHAR_EOF
chmod 0444 ./ttyio.c || echo "restore of ./ttyio.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./ttykbd.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./ttykbd.c &&
X/**************************************************************
X *
X * CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X * (C) Paul Fox, 1989
X * 43, Jerome Close Tel: +44 6284 4222
X * Marlow
X * Bucks.
X * England SL7 1TX
X *
X *
X * Please See COPYRIGHT notice.
X *
X **************************************************************/
X# include "list.h"
X# include "alt.h"
X
XSCCSID("@(#) ttykbd.c 1.11, (C) P. Fox");
X
X/*
X0x80-0x8b 128-139 F1-F12
X0x8c-0x97 140-151 SHIFT-F1 - SHIFT-F12
X0x98-0xA3 152-163 CTRL-F1 - CTRL-F12
X0xA4-0xAF 164-175 ALT-F1 - ALT-F12
X0xB0-0xC9 176-201 ALT-A - ALT-Z
X0xCA-0xD3 202-211 Key-0, Key-9
X 0xCA/202=INS
X 0xCB/203=END, 0xCC/204=DOWN, 0xCD/205=PgDn,
X 0xCE/206=LEFT, 0xCF/207=5, 0xD0/208=RIGHT,
X 0xD1/209=HOME, 0xD2/210=UP, 0xD3/211=PgUp
X0xD4/212=DEL, 0xD5/213=+, 0xD6/214=-, 0xD7/215=*
X0xD8-0xE5 216-229 CTRL-0 .. CTRL-9, DEL, +, -, *
X 0xDF/223=Ctrl-Home 0xD9/217=Ctrl-End
X 0xE1/225=Ctrl-PgUp 0xDB/219=Ctrl-Pgdn
X 0xDC/220=Ctrl-<- 0xDE/222=Ctrl- ->
X0xE6 230 Back-tab
X*/
X# define MAX_PUSHBACK 12
X
Xint reading_char = FALSE;
Xstatic u_char key_buf[16];
Xextern long time_last_key_pressed;
Xu_char push_buf[MAX_PUSHBACK];
Xint push_cnt = 0;
Xchar user_call[64]; /* Last macro called from keyboard by user*/
X
Xchar *aitokey();
Xstatic short akeytoi();
Xtypedef char *KEYBOARD[NKEYS];
Xtypedef struct MAP {
X char *m_keys; /* Key sequence. */
X char *m_value; /* String assigned to. */
X int m_flags; /* Tells us whether m_value is a */
X /* string or a list. */
X } MAP;
X
X# define K_ALLOC 0x01 /* Key has been alloc'ed and should*/
X /* be freed when finished with. */
X# define K_LIST 0x02 /* Key is assigned to a list. */
Xstruct kbd_stk {
X int k_id;
X int k_ref; /* Reference count for this keyboard. */
X /* When this becomes zero, we may free*/
X /* it. Otherwise, it still exists in */
X /* the keyboard stack. */
X u_char k_flags[NKEYS];
X KEYBOARD k_keys;
X Head_p k_maps; /* Multicharacter key combinations. */
X };
X
XHead_p hd_kbd;
XHead_p hd_kstk;
Xstruct kbd_stk *kp;
X#define KFIRST 0x0080 /* First special. */
Xextern char *K[];
Xchar character;
Xint kid = 1;
X
Xextern struct k_tbl k_tbl[];
Xvoid
Xkey_init()
X{ extern char *chk_alloc();
X int i;
X struct kbd_stk *kptr;
X
X hd_kbd = ll_init();
X hd_kstk = ll_init();
X
X kptr = (struct kbd_stk *) chk_alloc(sizeof (struct kbd_stk));
X kptr->k_id = kid++;
X kptr->k_ref = 1;
X kptr->k_maps = ll_init();
X for (i = 0; i < NKEYS; i++) {
X kptr->k_keys[i] = NULL;
X kptr->k_flags[i] = 0;
X }
X for (i = 0; k_tbl[i].name; i++) {
X kptr->k_keys[k_tbl[i].key] = k_tbl[i].name;
X kptr->k_flags[k_tbl[i].key] = 0;
X }
X ll_push(hd_kbd, (char *) kptr);
X kp = kptr;
X K[BACK_TAB - KFIRST] = strdup("\033[Z");
X}
Xkbd_type()
X{
X register int i;
X
X for (i = 0; i < 127; i++) {
X if (kp->k_keys[i] && kp->k_flags[i] & K_ALLOC)
X chk_free(kp->k_keys[i]);
X kp->k_keys[i] = NULL;
X }
X
X return 0;
X}
Xpush_back()
X{
X push_back1((int) argv[1].l_int);
X
X return 0;
X}
Xpush_back1(ch)
X{
X if (push_cnt < MAX_PUSHBACK)
X push_buf[push_cnt++] = ch;
X}
Xget_push()
X{ int ch;
X register int i;
X if (push_cnt) {
X ch = push_buf[0];
X for (i = 0; i < MAX_PUSHBACK - 1; i++)
X push_buf[i] = push_buf[i+1];
X push_cnt--;
X return ch;
X }
X return 0;
X}
Xassign_to_key()
X{ int key;
X char *cp;
X char *macro_name;
X int flags = K_ALLOC;
X char buf1[80];
X char buf[BUFSIZ];
X
X if ((cp = get_arg1("Enter key: ", buf, sizeof buf)) == NULL)
X return;
X key = akeytoi(cp);
X
X if (argc < 3 || argv[2].l_flags == F_NULL) {
X if (ereply("Enter macro name to assign: ", buf1, sizeof buf1)
X != TRUE)
X return;
X macro_name = strdup(buf1);
X }
X else if (argv[2].l_flags == F_LIST) {
X LIST *copy_list();
X macro_name = (char *) copy_list(argv[2].l_list);
X flags = K_LIST | K_ALLOC;
X }
X else
X macro_name = strdup(get_str(2));
X
X if (key >= 0) {
X free_key(key);
X kp->k_keys[key] = macro_name;
X kp->k_flags[key] = flags;
X }
X else {
X MAP *mp = (MAP *) chk_alloc (sizeof (MAP));
X mp->m_keys = strdup(key_buf);
X mp->m_value = macro_name;
X mp->m_flags = flags;
X ll_push(kp->k_maps, (char *) mp);
X return;
X }
X}
X
Xfree_key(key)
X{
X if (kp->k_flags[key] & K_ALLOC)
X chk_free(kp->k_keys[key]);
X}
Xstatic short
Xakeytoi(cp)
Xregister char *cp;
X{
X int width;
X
X for (width = 0; *cp; width++) {
X if (*cp == '<') {
X key_buf[width] = (u_char) new_akeytoi(cp);
X while (*cp)
X if (*cp++ == '>')
X break;
X }
X else if (*cp == '#') {
X key_buf[width] = (u_char) atoi(++cp);
X while (isdigit(*cp))
X cp++;
X }
X else {
X key_buf[width] = 0;
X if (*cp == '%')
X cp++;
X if (*cp == '\\')
X key_buf[width] = (u_char) *++cp;
X else if (*cp == '^')
X key_buf[width] = (u_char) *++cp & 0x1f;
X else
X key_buf[width] = (u_char) *cp;
X cp++;
X }
X if (width >= sizeof key_buf)
X break;
X }
X if (width == 1)
X return key_buf[0];
X key_buf[width] = 0;
X return -1;
X}
Xkey_to_int()
X{
X accumulator = akeytoi(get_str(1));
X return 0;
X}
Xint_to_key()
X{
X strl_acc_assign(aitokey((short) argv[1].l_int));
X return 0;
X}
Xcheck_key(buf, len)
Xchar *buf;
X{
X register char **cpp;
X List_p lp;
X KEY key;
X
X /*--------------------------------------
X * Check for normal function keys first.
X *--------------------------------------*/
X for (cpp = K; cpp < &K[NFKEYS]; cpp++) {
X if (*cpp == NULL)
X continue;
X if (strcmp(*cpp, buf) == 0)
X return (KEY) (cpp - K + KFIRST);
X if (strncmp(*cpp, buf, len) == 0)
X return -1;
X }
X /*--------------------------------------
X * Check for multiple characters key
X * sequences.
X *--------------------------------------*/
X for (key = KFIRST + NFKEYS, lp = ll_first(kp->k_maps); lp;
X key++, lp = ll_next(lp)) {
X MAP *mp = (MAP *) ll_elem(lp);
X if (strcmp(buf, mp->m_keys) == 0)
X return key;
X if (strcmp(buf, mp->m_keys, len) == 0)
X return -1;
X }
X return 0;
X}
X# if 0
XKEY
Xgetkey()
X{ register char **cpp;
X static unsigned char buf[12];
X static unsigned char *bufptr = NULL;
X static unsigned char *cp;
X static int l;
X int i;
X unsigned char ch;
X int timeout = FALSE;
X List_p lp;
X KEY key;
X int ambiguous;
X
X if (push_cnt) {
X ch = push_buf[0];
X for (i = 0; i < MAX_PUSHBACK - 1; i++)
X push_buf[i] = push_buf[i+1];
X push_cnt--;
X return ch;
X }
X
X if (bufptr) {
X ch = *bufptr++;
X if (*bufptr == NULL)
X bufptr = NULL;
X return ch;
X }
X cp = buf;
X l = 0;
X while (1) {
X tttimeout(timeout);
X
X reading_char = TRUE;
X if (ch = *cp = (char) ttgetc()) {
X extern long time();
X store_char(*cp++);
X *cp = NULL;
X l++;
X time_last_key_pressed = time((long *) 0);
X }
X reading_char = FALSE;
X /*--------------------------------------
X * Check for normal function keys first.
X *--------------------------------------*/
X ambiguous = FALSE;
X for (cpp = K; cpp < &K[NFKEYS]; cpp++) {
X if (*cpp == NULL)
X continue;
X if (strcmp(*cpp, buf) == 0)
X return (KEY) (cpp - K + KFIRST);
X if (strncmp(*cpp, buf, l) == 0) {
X ambiguous = TRUE;
X break;
X }
X }
X /*--------------------------------------
X * Check for multiple characters key
X * sequences.
X *--------------------------------------*/
X if (!ambiguous) {
X for (key = KFIRST + NFKEYS, lp = ll_first(kp->k_maps); lp;
X key++, lp = ll_next(lp)) {
X MAP *mp = (MAP *) ll_elem(lp);
X if (strcmp(buf, mp->m_keys) == 0)
X return key;
X if (strncmp(buf, mp->m_keys, l) == 0) {
X ambiguous = TRUE;
X ch = 1; /* Non-zero. */
X break;
X }
X }
X }
X if (ch == 0 || !ambiguous) {
X if (buf[1])
X bufptr = &buf[1];
X tttimeout(FALSE);
X return buf[0];
X }
X timeout = TRUE;
X }
X
X}
X# endif
Xinq_command()
X{
X strl_acc_assign(user_call);
X return 0;
X}
Xexec_key(c)
X{ register char *cp;
X int list_flag;
X char *get_key_assignment();
X
X u_chain();
X cp = get_key_assignment(c, &list_flag);
X character = (char) c;
X
X remember_macro(cp, list_flag);
X
X if (list_flag) {
X LISTV result;
X eval((LIST *) cp, &result);
X return 0;
X }
X
X if (cp[0] != '_')
X strcpy(user_call, cp);
X trace_log("\nKEY_EXEC: %s\n", cp);
X return str_exec(cp);
X}
Xchar *
Xget_key_assignment(c, list_flagp)
Xint *list_flagp;
X{
X register List_p lp;
X register char *cp;
X *list_flagp = TRUE;
X
X if (c >= KFIRST + NFKEYS) {
X int i = c - KFIRST - NFKEYS;
X MAP *mp;
X for (lp = ll_first(kp->k_maps); i-- > 0 && lp; )
X lp = ll_next(lp);
X mp = (MAP *) ll_elem(lp);
X cp = mp->m_value;
X if (mp->m_flags & K_LIST)
X return cp;
X }
X else if (curbp->b_keyboard) {
X cp = curbp->b_keyboard->k_keys[c];
X if (curbp->b_keyboard->k_flags[c] & K_LIST)
X return cp;
X if (cp && strcmp(cp, "nothing") == 0) {
X cp = kp->k_keys[c];
X if (kp->k_flags[c] & K_LIST)
X return cp;
X }
X }
X else {
X cp = kp->k_keys[c];
X if (kp->k_flags[c] & K_LIST)
X return cp;
X }
X *list_flagp = FALSE;
X return cp ? cp : "self_insert";
X}
Xinq_keyboard()
X{
X accumulator = kp->k_id;
X return 0;
X}
Xinq_local_keyboard()
X{
X accumulator = curbp->b_keyboard ? curbp->b_keyboard->k_id : 0;
X return 0;
X}
Xkbd_push()
X{ register int i = argv[1].l_flags == F_NULL ? 0 : (int) argv[1].l_int;
X register int j;
X
X if (i) {
X List_p lp;
X for (lp = ll_first(hd_kbd); lp; lp = ll_next(lp)) {
X kp = (struct kbd_stk *) ll_elem(lp);
X if (kp->k_id == i) {
X kp->k_ref++;
X break;
X }
X }
X if (lp == NULL) {
X for (lp = ll_first(hd_kstk); lp; lp = ll_next(lp)) {
X kp = (struct kbd_stk *) ll_elem(lp);
X if (kp->k_id == i) {
X ll_delete(lp);
X break;
X }
X }
X }
X if (lp == NULL)
X errorf("keyboard_push: %d not found.", i);
X }
X else {
X kp = (struct kbd_stk *) chk_alloc(sizeof (struct kbd_stk));
X kp->k_id = kid++;
X kp->k_maps = ll_init();
X for (j = 0; j < NKEYS; j++) {
X kp->k_keys[j] = i ? (char *) NULL : "nothing";
X kp->k_flags[j] = 0;
X }
X }
X ll_push(hd_kbd, (char *) kp);
X
X return 0;
X
X}
Xkbd_pop()
X{ int i = argv[1].l_flags == F_NULL ? 0 : (int) argv[1].l_int;
X register int j;
X List_p lp = ll_first(hd_kbd);
X
X if (lp == NULL)
X return 0;
X kp = (struct kbd_stk *) ll_elem(lp);
X (void) ll_pop(hd_kbd);
X
X if (i == 0) {
X if (--kp->k_ref <= 0) {
X for (j = 0; j < NKEYS; j++)
X if (kp->k_keys[j] && kp->k_flags[j] & K_ALLOC)
X chk_free(kp->k_keys[j]);
X for (lp = ll_first(kp->k_maps); lp;
X lp = ll_next(lp)) {
X MAP *mp = (MAP *) ll_elem(lp);
X chk_free(mp->m_keys);
X chk_free(mp->m_value);
X }
X ll_clear(kp->k_maps);
X ll_free(kp->k_maps);
X chk_free((char *) kp);
X }
X }
X else {
X ll_append(hd_kstk, (char *) kp);
X }
X lp = ll_first(hd_kbd);
X kp = lp ? (struct kbd_stk *) ll_elem(lp) : NULL;
X
X return 0;
X}
Xuse_local_keyboard()
X{
X struct kbd_stk *kp;
X register List_p lp;
X
X accumulator = 0;
X if (argv[1].l_int == 0) {
X curbp->b_keyboard = NULL;
X return 0;
X }
X for (lp = ll_first(hd_kstk); lp; lp = ll_next(lp)) {
X kp = (struct kbd_stk *) ll_elem(lp);
X if (kp->k_id == argv[1].l_int) {
X curbp->b_keyboard = kp;
X return 0;
X }
X }
X accumulator = -1;
X return 0;
X}
Xinq_assignment()
X{ char *cp;
X short key;
X int from_key = argv[2].l_flags == F_NULL || argv[2].l_int == 0;
X
X if (from_key) {
X if (argv[1].l_flags == F_INT)
X key = argv[1].l_int;
X else
X key = akeytoi(get_str(1));
X if (key >= 0) {
X if (curbp->b_keyboard) {
X cp = curbp->b_keyboard->k_keys[key];
X if (cp && strcmp(cp, "nothing") == 0)
X cp = kp->k_keys[key];
X }
X else
X cp = kp->k_keys[key];
X }
X else
X cp = "nothing";
X if (cp == NULL) {
X character = (char) key;
X cp = "self_insert";
X }
X strl_acc_assign(cp);
X return 0;
X }
X str_acc_assign("", 0);
X if (curbp->b_keyboard)
X find_assignment(curbp->b_keyboard->k_keys);
X find_assignment(kp->k_keys);
X
X if (saccumulator[0] == NULL)
X strl_acc_assign("nothing", 7);
X return 0;
X}
Xfind_assignment(cpp)
Xregister char **cpp;
X{ char buf[BUFSIZ];
X char *sp;
X short key;
X char *str1 = get_str(1);
X
X strcpy(buf, saccumulator);
X sp = buf + strlen(buf);
X
X for (key = 0; key < NKEYS; key++, cpp++) {
X if (*cpp && strcmp(*cpp, str1) == 0) {
X if (sp != buf) {
X strcpy(sp, "<-also>");
X sp += 7;
X }
X strcpy(sp, aitokey(key));
X sp += strlen(sp);
X }
X }
X strl_acc_assign(buf);
X}
X# undef PLUS
X# undef MINUS
X# define CTRL 0x0100
X# define SHIFT 0x0200
X# define ALT 0x0400
X# define KEYPAD 0x0800
X
X# define ALL (CTRL|SHIFT|ALT|KEYPAD)
X
X# define UP 210
X# define DOWN 204
X# define LEFT 206
X# define RIGHT 208
X# define HOME 209
X# define END 203
X# define PGUP 211
X# define PGDN 205
X# define STAR 42
X# define MINUS 169
X# define PLUS 168
X# define DEL 152
X# define INS KEY_0
X/*
X# define F1 128
X# define F2 129
X# define F3 130
X# define F4 131
X# define F5 132
X# define F6 133
X# define F7 134
X# define F8 135
X# define F9 136
X# define F10 137
X*/
X# define F11 138
X# define F12 139
X# define BACKSPACE 8
X# define ENTER '\r'
Xstruct map {
X int len;
X char *name;
X short value;
X };
Xstruct map special[] = {
X {0, "<Ctrl-Home>", 223},
X {0, "<Ctrl-End>", 217},
X {0, "<Ctrl-PgUp>", 225},
X {0, "<Ctrl-PgDn>", 219},
X {0, "<Ctrl-Left arrow>", 220},
X {0, "<Ctrl-Right arrow>", 222},
X {0, "<Ins>", KEY_0},
X {0, "<Del>", 212},
X {0, "<Delete>", 127},
X {0, "<Keypad-plus>", 213},
X {0, "<Keypad-minus>", 214},
X {0, "<Keypad-star>", 215},
X {0}
X };
X
Xstruct map stoi[] = {
X {3, "ESC", 0x1b},
X {1, "{", '{'},
X {1, "}", '}'},
X {5, "SPACE", ' '},
X {5, "ENTER", ENTER},
X {3, "TAB", 0x09},
X {5, "ARROW", 0},
X {4, "CTRL", CTRL},
X {5, "SHIFT", SHIFT},
X {3, "ALT", ALT},
X {6, "KEYPAD", KEYPAD},
X {4, "GREY", KEYPAD},
X {2, "UP", UP},
X {4, "DOWN", DOWN},
X {4, "LEFT", LEFT},
X {5, "RIGHT", RIGHT},
X {4, "HOME", HOME},
X {3, "END", END},
X {4, "PGUP", PGUP},
X {4, "PGDN", PGDN},
X {4, "STAR", STAR},
X {5, "MINUS", MINUS},
X {4, "PLUS", PLUS},
X {3, "DEL", DEL},
X {3, "INS", INS},
X {3, "F12", F12},
X {3, "F11", F11},
X {3, "F10", F10},
X {2, "F9", F9},
X {2, "F8", F8},
X {2, "F7", F7},
X {2, "F6", F6},
X {2, "F5", F5},
X {2, "F4", F4},
X {2, "F3", F3},
X {2, "F2", F2},
X {2, "F1", F1},
X {9, "BACKSPACE", BACKSPACE},
X 0
X };
Xchar *
Xaitokey(key)
Xshort key;
X{
X struct map *mp;
X static char buf[32];
X register char *cp;
X int alpha_cnt = 0;
X
X if (key >= ALT_A && key <= ALT_Z) {
X sprintf(buf, "<Alt-%c>", key - ALT_A + 'A');
X return buf;
X }
X if (key >= SHIFT_F1 && key <= SHIFT_F1+11) {
X sprintf(buf, "<Shift-F%d>", key - SHIFT_F1 + 1);
X return buf;
X }
X if (key >= CTRL_F1 && key <= CTRL_F1+11) {
X sprintf(buf, "<Ctrl-F%d>", key - CTRL_F1 + 1);
X return buf;
X }
X if (key >= ALT_F1 && key <= ALT_F1+11) {
X sprintf(buf, "<Alt-F%d>", key - ALT_F1 + 1);
X return buf;
X }
X if (key >= ALT_0 && key <= ALT_0+9) {
X sprintf(buf, "<Alt-%d>", key - ALT_0);
X return buf;
X }
X if (key == BACK_TAB)
X return "<Shift-Tab>";
X
X for (mp = special; mp->name; mp++)
X if (mp->value == key)
X return mp->name;
X
X for (mp = stoi; mp->name; mp++)
X if (mp->value == (short) (key & 0xff)) {
X sprintf(buf, "<%s>", mp->name);
X for (cp = buf; *cp; cp++)
X if (*cp >= 'A' && *cp <= 'Z')
X if (alpha_cnt++)
X *cp += 0x20;
X return buf;
X }
X if (key < ' ')
X sprintf(buf, "<Ctrl-%c>", key + 'A' - 1);
X else
X sprintf(buf, "#%d", key);
X return buf;
X}
X
Xnew_akeytoi(string)
Xchar *string;
X{ char str[80];
X register char *cp;
X int flags = 0;
X int ch;
X register struct map *mp;
X
X strcpy(str, string+1);
X for (cp = str; *cp; cp++)
X if (islower(*cp))
X *cp = toupper(*cp);
X
X for (cp = str; *cp && *cp != '>'; ) {
X if (*cp == ' ' || *cp == '-' || *cp == '\t') {
X cp++;
X continue;
X }
X for (mp = stoi; mp->name; mp++)
X if (strncmp(mp->name, cp, mp->len) == 0) {
X cp += mp->len;
X flags |= mp->value;
X break;
X }
X if (mp->name == 0) {
X flags |= *cp;
X break;
X }
X }
X ch = flags & 0xff;
X switch (flags & ALL) {
X case 0: return ch;
X case SHIFT:
X if (ch >= F1 && ch <= F12)
X return ch + 12;
X if (ch >= 'A' && ch <= 'Z')
X return ch - 0x20;
X if (ch == UP || ch == DOWN || ch == LEFT || ch == RIGHT)
X return 0;
X if (ch == '\t')
X return BACK_TAB;
X if (isdigit(ch))
X return 0;
X return ch;
X case CTRL:
X if (ch == ENTER)
X return '\n';
X if (ch >= F1 && ch <= F12)
X return ch + 24;
X if (ch >= 'A' && ch <= 'Z')
X return ch & 0x1f;
X if (ch == UP || ch == DOWN || ch == LEFT || ch == RIGHT)
X return ch + 14;
X if (ch == '{' || ch == '}')
X return 0;
X if (isdigit(ch))
X return 0;
X return ch;
X case ALT:
X if (ch >= F1 && ch <= F12)
X return ch + 32;
X if (ch >= 'A' && ch <= 'Z')
X return (ch - 'A') + ALT_A;
X if (isdigit(ch))
X return (ch - '0') + ALT_0;
X return ch;
X case KEYPAD:
X switch (ch) {
X case MINUS: return 214;
X case PLUS: return 213;
X default:
X return 0;
X }
X case SHIFT|KEYPAD:
X return 0;
X }
X ewprintf("Not decoded - %s", string);
X return 0;
X}
SHAR_EOF
chmod 0444 ./ttykbd.c || echo "restore of ./ttykbd.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./undo.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./undo.c &&
X/**************************************************************
X *
X * CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X * (C) Paul Fox, 1989
X * 43, Jerome Close Tel: +44 6284 4222
X * Marlow
X * Bucks.
X * England SL7 1TX
X *
X *
X * Please See COPYRIGHT notice.
X *
X * Code to implement the undo and redo facilities.
X **************************************************************/
X# include "list.h"
XSCCSID("@(#) undo.c 1.14, (C) 1989, P. Fox");
Xstatic void re_goto();
Xstatic void u_write();
Xstatic undo_check();
X
Xenum undo_opcodes {
X GOTO = 0,
X INSERT = 1,
X DELETE = 2,
X RAISE = 3,
X DROP = 4,
X SCRAP = 5, /* Operation should do an undo on the scrap */
X /* buffer. */
X };
X
Xextern long ftell();
Xextern char *mktemp();
Xextern doing_selfinsert;
Xstatic read_last_undo();
Xstatic int undoing_scrap = FALSE; /* If TRUE stops us printing */
X /* 'Undone.' twice. */
XFILE *ufp = NULL;
Xenum undo_state {
X NORMAL,
X REDO,
X UNDO
X } undo_state = NORMAL;
X
Xstruct undo {
X enum undo_opcodes u_opcode;
X int u_line;
X int u_col;
X ANCHOR u_anchor;
X RSIZE u_length;
X long u_last1; /* Used for backing up over (write_buffer) */
X /* mark. */
X long u_last; /* tell() position of previous undo */
X int u_chain; /* Non-zero if part of a single */
X /* undo. */
X };
Xchar *u_fname;
Xint u_atend = FALSE; /* If TRUE dont fseek to eof. */
Xvoid
Xu_init()
X{ char temp_file[64];
X char *get_tmpdir();
X char *sys_delim();
X
X sprintf(temp_file, "%s%sundoXXXXXX", get_tmpdir(), sys_delim());
X u_fname = mktemp(temp_file);
X
X if ((ufp = fopen(u_fname, "w+")) == NULL) {
X printf("Cannot create undo file:\n");
X perror(u_fname);
X gr_exit();
X }
X /*-------------------------*/
X /* Ensure ftell(ufp) != 0) */
X /*-------------------------*/
X fwrite("Undo", 4, 1, ufp);
X unlink(u_fname);
X}
Xchar *
Xget_tmpdir()
X{ extern char *ggetenv();
X char *cp;
X
X if ((cp = ggetenv("BTMP")) != NULL)
X return cp;
X if ((cp = ggetenv("TMP")) != NULL)
X return cp;
X# if defined(VMS)
X return "[-]";
X# else
X return "/tmp";
X# endif
X}
Xvoid
Xu_close()
X{
X if (ufp)
X unlink(u_fname);
X}
Xvoid
Xu_insert(n)
XRSIZE n;
X{ register LINE *clp;
X register int cbo;
X register int line;
X struct undo undo_buf;
X
X if (n == 0 || undo_check())
X return;
X
X if (undo_state == NORMAL)
X curbp->b_nummod++;
X undo_buf.u_opcode = INSERT;
X undo_buf.u_length = n;
X
X u_write(&undo_buf);
X
X line = *cur_line;
X cbo = current_offset(*cur_col, FALSE);
X for ( ; line < curbp->b_numlines && n > 0; line++, cbo = 0) {
X RSIZE x,w;
X clp = vm_lock_line(line);
X x = llength(clp) - cbo;
X w = x;
X if (x >= n)
X w = n;
X fwrite(<ext(clp)[cbo], (int) w, 1, ufp);
X vm_unlock(line);
X if (n -= w) {
X fputc('\n', ufp);
X n--;
X }
X }
X
X
X}
Xvoid
Xu_delete(n)
XRSIZE n;
X{ struct undo undo_buf1;
X struct undo undo_buf;
X undo_info *up;
X
X if (n == 0 || undo_check())
X return;
X up = undo_state == UNDO ? &curbp->b_redo : &curbp->b_undo;
X if (doing_selfinsert && up->u_last) {
X if (read_last_undo(&undo_buf1, up))
X goto normal;
X if (undo_buf1.u_opcode == DELETE) {
X extern char character;
X# ifdef DEBUG
X {char buf[128];
X extern int dflag;
X if (dflag & DB_UNDO) {
X sprintf(buf,
X "undo(COLLAPSING, %d + %d => %d)\n",
X undo_buf1.u_length, n,
X undo_buf1.u_length + n);
X trace_log(buf, (char *) NULL);
X }
X }
X# endif
X if ((isalnum(curbp->b_uchar) && isalnum(character)) ||
X (isspace(curbp->b_uchar) && isspace(character)) ||
X (curbp->b_uchar == 0x1B || character == 0x1B) ||
X (ispunct(curbp->b_uchar) && ispunct(character))) {
X undo_buf1.u_length += n;
X if (!u_atend)
X fseek(ufp, up->u_last, 0);
X fwrite((char *) &undo_buf1, sizeof undo_buf1, 1, ufp);
X fseek(ufp, 0l, 2);
X u_atend = TRUE;
X return;
X }
X }
X }
Xnormal:
X if (undo_state == NORMAL)
X curbp->b_nummod++;
X undo_buf.u_opcode = DELETE;
X undo_buf.u_length = n;
X u_write(&undo_buf);
X
X}
Xvoid
Xu_chain()
X{ extern int playing_back;
X if (!playing_back) {
X curbp->b_undo.u_chain = 0;
X curbp->b_redo.u_chain = 0;
X }
X}
Xvoid
Xu_terminate()
X{
X undo_info *up = undo_state == NORMAL ? &curbp->b_undo : &curbp->b_redo;
X
X up->u_last1 = up->u_last;
X up->u_last = 0;
X}
Xvoid
Xu_dot()
X{ struct undo undo_buf;
X
X if (undo_check())
X return;
X undo_buf.u_opcode = GOTO;
X u_write(&undo_buf);
X}
X
Xvoid
Xu_raise()
X{ struct undo undo_buf;
X if (undo_check())
X return;
X undo_buf.u_opcode = RAISE;
X u_write(&undo_buf);
X}
Xvoid
Xu_drop()
X{ struct undo undo_buf;
X
X if (undo_check())
X return;
X
X undo_buf.u_opcode = DROP;
X
X undo_buf.u_anchor = *curbp->b_anchor;
X u_write(&undo_buf);
X}
Xvoid
Xu_scrap()
X{ struct undo undo_buf;
X
X if (undo_check())
X return;
X undo_buf.u_opcode = SCRAP;
X u_write(&undo_buf);
X
X}
X/* Undo utility routines. */
Xstatic
Xundo_check()
X{
X if (/*undo_state == REDO || */curbp->b_system || ufp == NULL)
X return TRUE;
X /*----------------------------------------
X /* If user isn't undoing an undo
X /* then terminate the redo chain so we
X /* dont confuse user.
X /*----------------------------------------*/
X if (undo_state == NORMAL)
X curbp->b_redo.u_last = 0;
X return FALSE;
X}
Xstatic void
Xu_write(undop)
Xstruct undo *undop;
X{ undo_info *up;
X
X if (undo_state == UNDO)
X up = &curbp->b_redo;
X else
X up = &curbp->b_undo;
X
X undop->u_line = *cur_line;
X undop->u_col = *cur_col;
X undop->u_last1 = up->u_last1;
X undop->u_last = up->u_last;
X undop->u_chain = up->u_chain++;
X if (!u_atend)
X fseek(ufp, 0l, 2);
X up->u_last = ftell(ufp);
X
X u_debug(undop, undo_state == NORMAL ? "normal" :
X undo_state == UNDO ? "undo" : "redo");
X fwrite((char *) undop, sizeof *undop, 1, ufp);
X u_atend = TRUE;
X}
Xu_debug(undop, str)
Xstruct undo *undop;
Xchar *str;
X{
X# ifdef DEBUG
X char buf[128];
X extern int dflag;
X if (dflag & DB_UNDO) {
X sprintf(buf,
X "%s(%s, line=%d, col=%d, len=%ld, last=%08lx, chain=%d)\n", str,
X undop->u_opcode == GOTO ? "GOTO" :
X undop->u_opcode == INSERT ? "INSERT" :
X undop->u_opcode == DELETE ? "DELETE" :
X undop->u_opcode == RAISE ? "RAISE" :
X undop->u_opcode == DROP ? "DROP" :
X undop->u_opcode == SCRAP ? "SCRAP" : "??",
X undop->u_line, undop->u_col,
X undop->u_length, undop->u_last, undop->u_chain);
X trace_log(buf, (char *) NULL);
X }
X# endif
X}
Xundo()
X{ int undo_mod = argv[1].l_flags == F_INT ? argv[1].l_int : 0;
X int past_mark = argv[2].l_flags == F_INT ? argv[2].l_int : 0;
X long num = -1;
X static int sub_undo();
X struct undo undo_buf;
X enum undo_state saved_undo_state = undo_state;
X int redo = argv[3].l_flags == F_INT;
X undo_info *up = redo ? &curbp->b_redo : &curbp->b_undo;
Xtrace_log(redo ? "doing redo\n" : "doing undo\n", (char *) NULL);
X if (up->u_last == 0 && past_mark) {
X up->u_last = up->u_last1;
X up->u_last1 = 0;
X }
X undo_state = redo ? REDO : UNDO;
X do {
X if (sub_undo(&undo_buf, redo, up)) {
X undo_state = NORMAL;
X return;
X }
X if (num < 0 && undo_buf.u_chain > 2)
X ewprintf("Undoing command...");
X if (num < 0)
X num = undo_buf.u_chain;
X else if (num && undo_buf.u_chain)
X percentage(num - undo_buf.u_chain, num, "Undoing", "command");
X if (undo_mod &&
X (undo_buf.u_opcode != INSERT &&
X undo_buf.u_opcode != DELETE))
X undo_buf.u_chain = 1;
X }
X while (undo_buf.u_chain);
X undo_state = saved_undo_state;
X if (!undoing_scrap)
X ewprintf(redo ? "Redone." : "Undone.");
X return;
X}
Xstatic
Xsub_undo(undop, redo, up)
Xstruct undo *undop;
Xundo_info *up;
X{ long pos;
X char buf[64];
X int n;
X
X if (up->u_last == 0) {
X ewprintf("Nothing to %s.", redo ? "redo" : "undo");
X curbp->b_flag &= ~BFCHG;
X return -1;
X }
X if (read_last_undo(undop, up))
X return -1;
X u_debug(undop, "UNDOING");
X up->u_last = undop->u_last;
X up->u_last1 = undop->u_last1;
X switch (undop->u_opcode) {
X case INSERT:
SHAR_EOF
echo "End of part 10"
echo "File ./undo.c is continued in part 11"
echo "11" > s2_seq_.tmp
exit 0
--
===================== Reuters Ltd PLC,
Tel: +44 628 891313 x. 212 Westthorpe House,
UUCP: fox%marlow.uucp at idec.stc.co.uk Little Marlow,
Bucks, England SL7 3RQ
More information about the Comp.sources.misc
mailing list