Пример #1
0
/* deal with up arrow*/
static void
handle_up(void)
{
    /*get previous history */
    if (history_prev() < 0)
        return;

    /*copy current history cmd to out_cmd */
    strcpy(cmd_strp, history_buf[history_cur]);

    /*print out_cmd */
    out_cmd_print();
}
Пример #2
0
char * history_readline(struct cmd_history * ht, FILE * f, 
						char * buf, int max)
{
	int mode;
	int pos;
	int val;
	int len;
	int ctrl;
	int c;
	int i;
	char * s;

	if (isfatty(f)) {
		f = ftty_lowlevel(f);
	}

	mode = 0;
	pos = 0;
	val = 0;
	ctrl = 0;
	len = 0;
	/* reserve space for NULL termination */
	max--;
	for (;;) {
		if ((c = fgetc(f)) == EOF) {
			DCC_LOG(LOG_INFO, "EOF");
			return NULL;
		}

		DCC_LOG1(LOG_MSG, "[%02x]", c);

		switch (mode) {
		case MODE_ESC:
			switch (c) {
			case '[':
				mode = MODE_ESC_VAL1;
				val = 0;
				ctrl = 0;
				break;
			case 'O':
				mode = MODE_ESC_O;
				break;
			default:
				DCC_LOG1(LOG_INFO, "ESC:'%c'", c);
				mode = 0;
			};
			continue;

		case MODE_ESC_VAL1:
		case MODE_ESC_VAL2:
			switch (c) {
			case '0'...'9':
				val = val * 10 + c - '0';
				continue;
			case 'A':
				/* cursor up */
				DCC_LOG2(LOG_MSG, "up %d, %d", ctrl, val);
				c = IN_CURSOR_UP + ctrl;
				break;
			case 'B':
				/* cursor down */
				DCC_LOG2(LOG_MSG, "down %d, %d", ctrl, val);
				c = IN_CURSOR_DOWN + ctrl;
				break;
			case 'C':
				/* cursor right */
				DCC_LOG2(LOG_MSG, "right %d, %d", ctrl, val);
				c = IN_CURSOR_RIGHT + ctrl;
				break;
			case 'D':
				/* cursor left */
				DCC_LOG2(LOG_MSG, "left %d, %d", ctrl, val);
				c = IN_CURSOR_LEFT + ctrl;
				break;
			case '~':
				switch (val) {
				case 1:
					DCC_LOG1(LOG_MSG, "home %d", ctrl);
					c = IN_HOME + ctrl;
					break;
				case 2:
					DCC_LOG1(LOG_MSG, "insert %d", ctrl);
					c = IN_INSERT + ctrl;
					break;
				case 3:
					/* delete */
					DCC_LOG1(LOG_MSG, "delete %d", ctrl);
					c = IN_DELETE + ctrl;
					break;
				case 4:
					/* end */
					DCC_LOG(LOG_MSG, "end");
					c = IN_END + ctrl;
					break;
				case 5:
					DCC_LOG1(LOG_MSG, "pg up %d", ctrl);
					c = IN_PAGE_UP + ctrl;
					break;
				case 6:
					DCC_LOG1(LOG_MSG, "pg down %d", ctrl);
					c = IN_PAGE_DOWN + ctrl;
					break;
				default:
					DCC_LOG1(LOG_INFO, "seq %d", val);
					mode = 0;
					continue;
				}
				break;
			case ';':
				mode = MODE_ESC_VAL2;
				ctrl = IN_CTRL;
				val = 0;
				continue;
			default:
				DCC_LOG1(LOG_MSG, "VAL:'%c'", c);
				mode = 0;
				continue;
			};
			mode = 0;
			break;

		case MODE_ESC_O:
			switch (c) {
			case 'F':
				/* end */
				DCC_LOG(LOG_MSG, "end");
				c = IN_END;
				break;
			case 'H':
				/* home */
				DCC_LOG(LOG_MSG, "home");
				c = IN_HOME;
				break;
			default:
				DCC_LOG1(LOG_INFO, "ESC O:'%c'", c);
				mode = 0;
				continue;
			}
			mode = 0;
			break;
		} 

		switch (c) {
		case IN_ESC:
			DCC_LOG(LOG_MSG, "ESC");
			mode = MODE_ESC;
			continue;

		case IN_CURSOR_UP:
			if (ht->pos == ht->head) {
				buf[len] = '\0';
				/* save current line on history's head */
				strcpy(ht->buf + ht->pos * ht->len, buf);
			}

			if ((s = history_prev(ht)) == NULL)
				continue;
			goto set_buf;

		case IN_CURSOR_DOWN:
			if ((s = history_next(ht)) == NULL)
				continue;
			goto set_buf;

		case IN_CURSOR_RIGHT:
			if (pos < len)
				fputc(buf[pos++], f);
			else
				fputs(OUT_BEL, f);
			continue;

		case IN_CURSOR_LEFT:
			if (pos > 0) {
				fputs(OUT_CURSOR_LEFT, f);
				pos--;
			} else {
				fputs(OUT_BEL, f);
			}
			continue;

		case IN_CTRL_CURSOR_RIGHT:
			while (pos < len) {
				fputc(buf[pos++], f);
				if ((buf[pos - 1] != ' ') && (buf[pos] == ' '))
					break;
			} 
			continue;

		case IN_CTRL_CURSOR_LEFT:
			if (pos > 0) {
				do {
					fputs(OUT_CURSOR_LEFT, f);
					pos--;
					if ((buf[pos - 1] == ' ') && (buf[pos] != ' '))
						break;
				} while (pos > 0);
			}
			continue;

		case IN_PAGE_UP:
			continue;

		case IN_PAGE_DOWN:
			continue;

		case IN_INSERT:
			continue;

		case IN_HOME:
			while (pos > 0) {
				fputs(OUT_CURSOR_LEFT, f);
				pos--;
			} 
			continue;

		case IN_END:
			while (pos < len) {
				fputc(buf[pos++], f);
			} 
			continue;

		case IN_TN_BS:     
			DCC_LOG(LOG_MSG, "IN_TN_BS");
		case IN_BS:
			if (pos == 0) {
				fputs(OUT_BEL, f);
				continue;
			}
			if (len == pos) {
				pos--;
				len--;
				fputs(OUT_BS, f);
				continue;
			}

			fputs(OUT_CURSOR_LEFT, f);
			pos--;
			/* fall back */

		case IN_DELETE:

			if (len == pos) {
				continue;
			}
			len--;

			for (i = pos; i < len; i++) {
				buf[i] = buf[i + 1];
			}
			buf[len] = '\0';
			fputs(&buf[pos], f);
			fputc(' ', f);
			for (i = len + 1; i > pos; i--)
				fputs(OUT_CURSOR_LEFT, f);
			continue;

		case IN_EOL:
			buf[len] = '\0';
			fputs("\r\n", f);
			return buf;

		case IN_SKIP:
			fputs(OUT_SKIP, f);
			return NULL;
		}

		if (len == max) {
			fputs(OUT_BEL, f);
			continue;
		}

		if (len == pos) {
			fputc(c, f);
			buf[pos] = c;
			pos++;
			len++;
			continue;
		}

		for (i = len; i > pos; i--) {
			buf[i] = buf[i - 1];
		}

		len++;
		buf[pos] = c;
		buf[len] = '\0';

		fputs(&buf[pos], f);
		pos++;

		for (i = len; i > pos; i--)
			fputs(OUT_CURSOR_LEFT, f);

		continue;

set_buf:
		for (i = pos; i > 0; i--)
			fputs(OUT_CURSOR_LEFT, f);

		strcpy(buf, s);
		fputs(s, f);

		pos = strlen(s);
		if (pos < len) {
			for (i = pos; i < len; i++)
				fputc(' ', f);
			for (i = pos; i < len; i++)
				fputs(OUT_CURSOR_LEFT, f);
		}
		len = pos;

	}
}