Пример #1
0
/* returns TRUE at end-of-line */
int
db_inputchar(int c)
{
    static int escstate;

    if (escstate == 1) {
        /* ESC seen, look for [ or O */
        if (c == '[' || c == 'O')
            escstate++;
        else
            escstate = 0; /* re-init state machine */
        return (0);
    } else if (escstate == 2) {
        escstate = 0;
        /*
         * If a valid cursor key has been found, translate
         * into an emacs-style control key, and fall through.
         * Otherwise, drop off.
         */
        switch (c) {
        case 'A':	/* up */
            c = CTRL('p');
            break;
        case 'B':	/* down */
            c = CTRL('n');
            break;
        case 'C':	/* right */
            c = CTRL('f');
            break;
        case 'D':	/* left */
            c = CTRL('b');
            break;
        default:
            return (0);
        }
    }

    switch (c) {
    case CTRL('['):
        escstate = 1;
        break;
    case CTRL('b'):
        /* back up one character */
        if (db_lc > db_lbuf_start) {
            cnputc(BACKUP);
            db_lc--;
        }
        break;
    case CTRL('f'):
        /* forward one character */
        if (db_lc < db_le) {
            cnputc(*db_lc);
            db_lc++;
        }
        break;
    case CTRL('a'):
        /* beginning of line */
        while (db_lc > db_lbuf_start) {
            cnputc(BACKUP);
            db_lc--;
        }
        break;
    case CTRL('e'):
        /* end of line */
        while (db_lc < db_le) {
            cnputc(*db_lc);
            db_lc++;
        }
        break;
    case CTRL('h'):
    case 0177:
        /* erase previous character */
        if (db_lc > db_lbuf_start)
            db_delete(1, DEL_BWD);
        break;
    case CTRL('d'):
        /* erase next character */
        if (db_lc < db_le)
            db_delete(1, DEL_FWD);
        break;
    case CTRL('u'):
        /* kill entire line: */
        /* at first, delete to beginning of line */
        if (db_lc > db_lbuf_start)
            db_delete(db_lc - db_lbuf_start, DEL_BWD);
    /* FALLTHROUGH */
    case CTRL('k'):
        /* delete to end of line */
        if (db_lc < db_le)
            db_delete(db_le - db_lc, DEL_FWD);
        break;
    case CTRL('t'):
        /* twiddle last 2 characters */
        if (db_lc >= db_lbuf_start + 2) {
            c = db_lc[-2];
            db_lc[-2] = db_lc[-1];
            db_lc[-1] = c;
            cnputc(BACKUP);
            cnputc(BACKUP);
            cnputc(db_lc[-2]);
            cnputc(db_lc[-1]);
        }
        break;
    case CTRL('r'):
        db_putstring("^R\n", 3);
redraw:
        if (db_le > db_lbuf_start) {
            db_putstring(db_lbuf_start, db_le - db_lbuf_start);
            db_putnchars(BACKUP, db_le - db_lc);
        }
        break;
    case CTRL('p'):
        /* Make previous history line the active one. */
        if (db_lhistcur >= 0) {
            bcopy(db_lhistory + db_lhistcur * db_lhistlsize,
                  db_lbuf_start, db_lhistlsize);
            db_lhistcur--;
            goto hist_redraw;
        }
        break;
    case CTRL('n'):
        /* Make next history line the active one. */
        if (db_lhistcur < db_lhistidx - 1) {
            db_lhistcur += 2;
            bcopy(db_lhistory + db_lhistcur * db_lhistlsize,
                  db_lbuf_start, db_lhistlsize);
        } else {
            /*
             * ^N through tail of history, reset the
             * buffer to zero length.
             */
            *db_lbuf_start = '\0';
            db_lhistcur = db_lhistidx;
        }

hist_redraw:
        db_putnchars(BACKUP, db_le - db_lbuf_start);
        db_putnchars(BLANK, db_le - db_lbuf_start);
        db_putnchars(BACKUP, db_le - db_lbuf_start);
        db_le = index(db_lbuf_start, '\0');
        if (db_le[-1] == '\r' || db_le[-1] == '\n')
            *--db_le = '\0';
        db_lc = db_le;
        goto redraw;

    case -1:
        /*
         * eek! the console returned eof.
         * probably that means we HAVE no console.. we should try bail
         * XXX
         */
        return (0);
    case '\n':
    case '\r':
        *db_le++ = c;
        return (1);
    default:
        if (db_le == db_lbuf_end) {
            cnputc('\007');
        }
        else if (c >= ' ' && c <= '~') {
            char *p;

            for (p = db_le; p > db_lc; p--)
                *p = *(p-1);
            *db_lc++ = c;
            db_le++;
            cnputc(c);
            db_putstring(db_lc, db_le - db_lc);
            db_putnchars(BACKUP, db_le - db_lc);
        }
        break;
    }
    return (0);
}
Пример #2
0
/* returns TRUE at end-of-line */
int
db_inputchar(int c)
{
	switch (c) {
	    case CTRL('b'):
		/* back up one character */
		if (db_lc > db_lbuf_start) {
		    cnputc(BACKUP);
		    db_lc--;
		}
		break;
	    case CTRL('f'):
		/* forward one character */
		if (db_lc < db_le) {
		    cnputc(*db_lc);
		    db_lc++;
		}
		break;
	    case CTRL('a'):
		/* beginning of line */
		while (db_lc > db_lbuf_start) {
		    cnputc(BACKUP);
		    db_lc--;
		}
		break;
	    case CTRL('e'):
		/* end of line */
		while (db_lc < db_le) {
		    cnputc(*db_lc);
		    db_lc++;
		}
		break;
	    case CTRL('w'):
		/* erase word back */
		while (db_lc > db_lbuf_start && db_lc[-1] != BLANK)
		    db_delete(1, DEL_BWD);
		break;
	    case CTRL('h'):
	    case 0177:
		/* erase previous character */
		if (db_lc > db_lbuf_start)
		    db_delete(1, DEL_BWD);
		break;
	    case CTRL('d'):
		/* erase next character */
		if (db_lc < db_le)
		    db_delete(1, DEL_FWD);
		break;
	    case CTRL('k'):
		/* delete to end of line */
		if (db_lc < db_le)
		    db_delete(db_le - db_lc, DEL_FWD);
		break;
	    case CTRL('u'):
		/* delete line */
	        db_delete_line();
		break;
	    case CTRL('t'):
		/* twiddle last 2 characters */
		if (db_lc >= db_lbuf_start + 2) {
		    c = db_lc[-2];
		    db_lc[-2] = db_lc[-1];
		    db_lc[-1] = c;
		    cnputc(BACKUP);
		    cnputc(BACKUP);
		    cnputc(db_lc[-2]);
		    cnputc(db_lc[-1]);
		}
		break;
#if DB_HISTORY_SIZE != 0
	    case CTRL('p'):
		DEC_DB_CURR();
		while (db_history_curr != db_history_last) {
			DEC_DB_CURR();
			if (*db_history_curr == '\0')
				break;
		}
		db_delete_line();
		if (db_history_curr == db_history_last) {
			INC_DB_CURR();
			db_le = db_lc = db_lbuf_start;
		} else {
			char *p;
			INC_DB_CURR();
			for (p = db_history_curr, db_le = db_lbuf_start;*p; ) {
				*db_le++ = *p++;
				if (p == db_history + db_history_size)
					p = db_history;
			}
			db_lc = db_le;
		}
		db_putstring(db_lbuf_start, db_le - db_lbuf_start);
		break;
	    case CTRL('n'):
		while (db_history_curr != db_history_last) {
			if (*db_history_curr == '\0')
				break;
			INC_DB_CURR();
		}
		if (db_history_curr != db_history_last) {
			INC_DB_CURR();
			db_delete_line();
			if (db_history_curr != db_history_last) {
				char *p;
				for (p = db_history_curr,
				     db_le = db_lbuf_start; *p;) {
					*db_le++ = *p++;
					if (p == db_history + db_history_size)
						p = db_history;
				}
				db_lc = db_le;
			}
			db_putstring(db_lbuf_start, db_le - db_lbuf_start);
		}
		break;
#endif
	    case CTRL('r'):
		db_putstring("^R\n", 3);
		if (db_le > db_lbuf_start) {
			db_putstring(db_lbuf_start, db_le - db_lbuf_start);
			db_putnchars(BACKUP, db_le - db_lc);
		}
		break;
	    case '\n':
	    case '\r':
#if DB_HISTORY_SIZE != 0
		/*
		 * Check whether current line is the same
		 * as previous saved line.  If it is, don`t
		 * save it.
		 */
		if (db_history_curr == db_history_prev) {
			char *pp, *pc;

			/*
			 * Is it the same?
			 */
			for (pp = db_history_prev, pc = db_lbuf_start;
			     pc != db_le && *pp; ) {
				if (*pp != *pc)
					break;
				if (++pp == db_history + db_history_size)
					pp = db_history;
				pc++;
			}
			if (!*pp && pc == db_le) {
				/*
				 * Repeated previous line. Don`t save.
				 */
				db_history_curr = db_history_last;
				*db_le++ = c;
				return TRUE;
			}
		}
		if (db_le != db_lbuf_start) {
			char *p;
			db_history_prev = db_history_last;
			for (p = db_lbuf_start; p != db_le; p++) {
				*db_history_last++ = *p;
				if (db_history_last ==
				    db_history + db_history_size)
					db_history_last = db_history;
			}
			*db_history_last++ = '\0';
		}
		db_history_curr = db_history_last;
#endif
		*db_le++ = c;
		return TRUE;
	    default:
		if (db_le == db_lbuf_end) {
		    cnputc('\007');
		}
		else if (c >= ' ' && c <= '~') {
		    char *p;

		    for (p = db_le; p > db_lc; p--)
			*p = *(p-1);
		    *db_lc++ = c;
		    db_le++;
		    cnputc(c);
		    db_putstring(db_lc, db_le - db_lc);
		    db_putnchars(BACKUP, db_le - db_lc);
		}
		break;
	}
	return FALSE;
}