18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Command line editing and history
31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2010-2011, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <termios.h>
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "list.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "edit.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CMD_BUF_LEN 256
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char cmdbuf[CMD_BUF_LEN];
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cmdbuf_pos = 0;
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cmdbuf_len = 0;
211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic char currbuf[CMD_BUF_LEN];
221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int currbuf_valid = 0;
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define HISTORY_MAX 100
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct edit_history {
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct dl_list list;
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char str[1];
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct dl_list history_list;
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct edit_history *history_curr;
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void *edit_cb_ctx;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void (*edit_cmd_cb)(void *ctx, char *cmd);
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void (*edit_eof_cb)(void *ctx);
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char ** (*edit_completion_cb)(void *ctx, const char *cmd, int pos) =
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	NULL;
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct termios prevt, newt;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define CLEAR_END_LINE "\e[K"
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid edit_clear_line(void)
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	putchar('\r');
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < cmdbuf_len + 2; i++)
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		putchar(' ');
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void move_start(void)
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_pos = 0;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void move_end(void)
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_pos = cmdbuf_len;
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void move_left(void)
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cmdbuf_pos > 0) {
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf_pos--;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		edit_redraw();
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void move_right(void)
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cmdbuf_pos < cmdbuf_len) {
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf_pos++;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		edit_redraw();
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void move_word_left(void)
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (cmdbuf_pos > 0 && cmdbuf[cmdbuf_pos - 1] == ' ')
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf_pos--;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (cmdbuf_pos > 0 && cmdbuf[cmdbuf_pos - 1] != ' ')
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf_pos--;
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void move_word_right(void)
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (cmdbuf_pos < cmdbuf_len && cmdbuf[cmdbuf_pos] == ' ')
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf_pos++;
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (cmdbuf_pos < cmdbuf_len && cmdbuf[cmdbuf_pos] != ' ')
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf_pos++;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void delete_left(void)
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cmdbuf_pos == 0)
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_clear_line();
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memmove(cmdbuf + cmdbuf_pos - 1, cmdbuf + cmdbuf_pos,
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   cmdbuf_len - cmdbuf_pos);
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_pos--;
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_len--;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void delete_current(void)
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cmdbuf_pos == cmdbuf_len)
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_clear_line();
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memmove(cmdbuf + cmdbuf_pos, cmdbuf + cmdbuf_pos + 1,
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   cmdbuf_len - cmdbuf_pos);
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_len--;
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void delete_word(void)
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int pos;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_clear_line();
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = cmdbuf_pos;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos > 0 && cmdbuf[pos - 1] == ' ')
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos--;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (pos > 0 && cmdbuf[pos - 1] != ' ')
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos--;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memmove(cmdbuf + pos, cmdbuf + cmdbuf_pos, cmdbuf_len - cmdbuf_pos);
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_len -= cmdbuf_pos - pos;
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_pos = pos;
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void clear_left(void)
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cmdbuf_pos == 0)
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_clear_line();
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memmove(cmdbuf, cmdbuf + cmdbuf_pos, cmdbuf_len - cmdbuf_pos);
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_len -= cmdbuf_pos;
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_pos = 0;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void clear_right(void)
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cmdbuf_pos == cmdbuf_len)
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_clear_line();
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_len = cmdbuf_pos;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void history_add(const char *str)
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct edit_history *h, *match = NULL, *last = NULL;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len, count = 0;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (str[0] == '\0')
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(h, &history_list, struct edit_history, list) {
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strcmp(str, h->str) == 0) {
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			match = h;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last = h;
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		count++;
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (match) {
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&h->list);
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_add(&history_list, &h->list);
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		history_curr = h;
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (count >= HISTORY_MAX && last) {
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&last->list);
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(last);
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_strlen(str);
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	h = os_zalloc(sizeof(*h) + len);
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (h == NULL)
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_add(&history_list, &h->list);
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_strlcpy(h->str, str, len + 1);
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	history_curr = h;
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void history_use(void)
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_clear_line();
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_len = cmdbuf_pos = os_strlen(history_curr->str);
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(cmdbuf, history_curr->str, cmdbuf_len);
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void history_prev(void)
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (history_curr == NULL)
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (history_curr ==
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    dl_list_first(&history_list, struct edit_history, list)) {
2301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (!currbuf_valid) {
2311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			cmdbuf[cmdbuf_len] = '\0';
2321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			os_memcpy(currbuf, cmdbuf, cmdbuf_len + 1);
2331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			currbuf_valid = 1;
2341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			history_use();
2351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			return;
2361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (history_curr ==
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    dl_list_last(&history_list, struct edit_history, list))
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	history_curr = dl_list_entry(history_curr->list.next,
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct edit_history, list);
2451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	history_use();
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void history_next(void)
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (history_curr == NULL ||
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    history_curr ==
2531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    dl_list_first(&history_list, struct edit_history, list)) {
2541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (currbuf_valid) {
2551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			currbuf_valid = 0;
2561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			edit_clear_line();
2571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			cmdbuf_len = cmdbuf_pos = os_strlen(currbuf);
2581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			os_memcpy(cmdbuf, currbuf, cmdbuf_len);
2591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			edit_redraw();
2601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	history_curr = dl_list_entry(history_curr->list.prev,
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     struct edit_history, list);
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	history_use();
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void history_read(const char *fname)
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FILE *f;
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char buf[CMD_BUF_LEN], *pos;
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	f = fopen(fname, "r");
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (f == NULL)
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (fgets(buf, CMD_BUF_LEN, f)) {
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (pos = buf; *pos; pos++) {
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (*pos == '\r' || *pos == '\n') {
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				*pos = '\0';
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		history_add(buf);
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fclose(f);
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void history_write(const char *fname,
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  int (*filter_cb)(void *ctx, const char *cmd))
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	FILE *f;
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct edit_history *h;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	f = fopen(fname, "w");
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (f == NULL)
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_reverse(h, &history_list, struct edit_history, list) {
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (filter_cb && filter_cb(edit_cb_ctx, h->str))
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		fprintf(f, "%s\n", h->str);
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fclose(f);
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void history_debug_dump(void)
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct edit_history *h;
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_clear_line();
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("\r");
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each_reverse(h, &history_list, struct edit_history, list)
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("%s%s\n", h == history_curr ? "[C]" : "", h->str);
3201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (currbuf_valid)
3211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		printf("{%s}\n", currbuf);
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void insert_char(int c)
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cmdbuf_len >= (int) sizeof(cmdbuf) - 1)
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cmdbuf_len == cmdbuf_pos) {
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf[cmdbuf_pos++] = c;
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf_len++;
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		putchar(c);
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		fflush(stdout);
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memmove(cmdbuf + cmdbuf_pos + 1, cmdbuf + cmdbuf_pos,
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   cmdbuf_len - cmdbuf_pos);
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf[cmdbuf_pos++] = c;
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf_len++;
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		edit_redraw();
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void process_cmd(void)
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cmdbuf_len == 0) {
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("\n> ");
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		fflush(stdout);
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("\n");
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf[cmdbuf_len] = '\0';
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	history_add(cmdbuf);
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_pos = 0;
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_len = 0;
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_cmd_cb(edit_cb_ctx, cmdbuf);
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("> ");
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fflush(stdout);
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void free_completions(char **c)
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (c == NULL)
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; c[i]; i++)
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(c[i]);
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(c);
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int filter_strings(char **c, char *str, size_t len)
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, j;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0, j = 0; c[j]; j++) {
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strncasecmp(c[j], str, len) == 0) {
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (i != j) {
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				c[i] = c[j];
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				c[j] = NULL;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			i++;
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_free(c[j]);
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			c[j] = NULL;
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c[i] = NULL;
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return i;
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int common_len(const char *a, const char *b)
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len = 0;
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (a[len] && a[len] == b[len])
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len++;
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return len;
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int max_common_length(char **c)
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int len, i;
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_strlen(c[0]);
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 1; c[i]; i++) {
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int same = common_len(c[0], c[i]);
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (same < len)
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			len = same;
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return len;
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cmp_str(const void *a, const void *b)
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return os_strcmp(* (const char **) a, * (const char **) b);
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void complete(int list)
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char **c;
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, len, count;
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int start, end;
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int room, plen, add_space;
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (edit_completion_cb == NULL)
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf[cmdbuf_len] = '\0';
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = edit_completion_cb(edit_cb_ctx, cmdbuf, cmdbuf_pos);
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (c == NULL)
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = cmdbuf_pos;
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	start = end;
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (start > 0 && cmdbuf[start - 1] != ' ')
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		start--;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	plen = end - start;
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	count = filter_strings(c, &cmdbuf[start], plen);
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (count == 0) {
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		free_completions(c);
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = max_common_length(c);
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len <= plen && count > 1) {
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (list) {
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			qsort(c, count, sizeof(char *), cmp_str);
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			edit_clear_line();
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("\r");
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			for (i = 0; c[i]; i++)
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				printf("%s%s", i > 0 ? " " : "", c[i]);
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			printf("\n");
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			edit_redraw();
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		free_completions(c);
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len -= plen;
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	room = sizeof(cmdbuf) - 1 - cmdbuf_len;
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (room < len)
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = room;
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	add_space = count == 1 && len < room;
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memmove(cmdbuf + cmdbuf_pos + len + add_space, cmdbuf + cmdbuf_pos,
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   cmdbuf_len - cmdbuf_pos);
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(&cmdbuf[cmdbuf_pos - plen], c[0], plen + len);
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (add_space)
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf[cmdbuf_pos + len] = ' ';
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_pos += len + add_space;
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf_len += len + add_space;
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	free_completions(c);
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtenum edit_key_code {
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_NONE = 256,
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_TAB,
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_UP,
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_DOWN,
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_RIGHT,
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_LEFT,
4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_ENTER,
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_BACKSPACE,
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_INSERT,
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_DELETE,
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_HOME,
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_END,
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_PAGE_UP,
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_PAGE_DOWN,
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_F1,
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_F2,
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_F3,
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_F4,
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_F5,
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_F6,
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_F7,
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_F8,
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_F9,
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_F10,
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_F11,
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_F12,
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_UP,
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_DOWN,
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_RIGHT,
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_LEFT,
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_A,
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_B,
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_D,
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_E,
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_F,
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_G,
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_H,
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_J,
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_K,
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_L,
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_N,
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_O,
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_P,
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_R,
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_T,
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_U,
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_V,
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_CTRL_W,
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_ALT_UP,
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_ALT_DOWN,
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_ALT_RIGHT,
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_ALT_LEFT,
5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_SHIFT_UP,
5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_SHIFT_DOWN,
5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_SHIFT_RIGHT,
5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_SHIFT_LEFT,
5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_ALT_SHIFT_UP,
5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_ALT_SHIFT_DOWN,
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_ALT_SHIFT_RIGHT,
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_ALT_SHIFT_LEFT,
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	EDIT_KEY_EOF
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void show_esc_buf(const char *esc_buf, char c, int i)
5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_clear_line();
5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("\rESC buffer '%s' c='%c' [%d]\n", esc_buf, c, i);
5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum edit_key_code esc_seq_to_key1_no(char last)
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (last) {
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'A':
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_UP;
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'B':
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_DOWN;
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'C':
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_RIGHT;
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'D':
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_LEFT;
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_NONE;
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum edit_key_code esc_seq_to_key1_shift(char last)
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (last) {
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'A':
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_SHIFT_UP;
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'B':
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_SHIFT_DOWN;
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'C':
5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_SHIFT_RIGHT;
5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'D':
5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_SHIFT_LEFT;
5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_NONE;
5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum edit_key_code esc_seq_to_key1_alt(char last)
5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (last) {
5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'A':
5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_ALT_UP;
5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'B':
6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_ALT_DOWN;
6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'C':
6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_ALT_RIGHT;
6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'D':
6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_ALT_LEFT;
6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_NONE;
6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum edit_key_code esc_seq_to_key1_alt_shift(char last)
6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (last) {
6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'A':
6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_ALT_SHIFT_UP;
6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'B':
6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_ALT_SHIFT_DOWN;
6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'C':
6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_ALT_SHIFT_RIGHT;
6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'D':
6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_ALT_SHIFT_LEFT;
6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_NONE;
6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum edit_key_code esc_seq_to_key1_ctrl(char last)
6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (last) {
6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'A':
6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_UP;
6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'B':
6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_DOWN;
6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'C':
6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_RIGHT;
6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'D':
6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_LEFT;
6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_NONE;
6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum edit_key_code esc_seq_to_key1(int param1, int param2, char last)
6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* ESC-[<param1>;<param2><last> */
6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (param1 < 0 && param2 < 0)
6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return esc_seq_to_key1_no(last);
6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (param1 == 1 && param2 == 2)
6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return esc_seq_to_key1_shift(last);
6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (param1 == 1 && param2 == 3)
6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return esc_seq_to_key1_alt(last);
6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (param1 == 1 && param2 == 4)
6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return esc_seq_to_key1_alt_shift(last);
6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (param1 == 1 && param2 == 5)
6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return esc_seq_to_key1_ctrl(last);
6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (param2 < 0) {
6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (last != '~')
6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_NONE;
6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (param1) {
6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 2:
6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_INSERT;
6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 3:
6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_DELETE;
6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 5:
6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_PAGE_UP;
6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 6:
6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_PAGE_DOWN;
6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 15:
6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_F5;
6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 17:
6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_F6;
6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 18:
6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_F7;
6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 19:
6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_F8;
6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 20:
6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_F9;
6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 21:
6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_F10;
6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 23:
6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_F11;
6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case 24:
6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_F12;
6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return EDIT_KEY_NONE;
6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum edit_key_code esc_seq_to_key2(int param1, int param2, char last)
7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* ESC-O<param1>;<param2><last> */
7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (param1 >= 0 || param2 >= 0)
7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_NONE;
7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (last) {
7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'F':
7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_END;
7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'H':
7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_HOME;
7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'P':
7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_F1;
7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'Q':
7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_F2;
7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'R':
7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_F3;
7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 'S':
7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_F4;
7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_NONE;
7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum edit_key_code esc_seq_to_key(char *seq)
7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char last, *pos;
7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int param1 = -1, param2 = -1;
7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum edit_key_code ret = EDIT_KEY_NONE;
7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	last = '\0';
7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (pos = seq; *pos; pos++)
7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last = *pos;
7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (seq[1] >= '0' && seq[1] <= '9') {
7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		param1 = atoi(&seq[1]);
7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos = os_strchr(seq, ';');
7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pos)
7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			param2 = atoi(pos + 1);
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (seq[0] == '[')
7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = esc_seq_to_key1(param1, param2, last);
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else if (seq[0] == 'O')
7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ret = esc_seq_to_key2(param1, param2, last);
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret != EDIT_KEY_NONE)
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return ret;
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_clear_line();
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("\rUnknown escape sequence '%s'\n", seq);
7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return EDIT_KEY_NONE;
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum edit_key_code edit_read_key(int sock)
7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int c;
7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned char buf[1];
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static int esc = -1;
7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static char esc_buf[7];
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = read(sock, buf, 1);
7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0)
7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		perror("read");
7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res <= 0)
7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_EOF;
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = buf[0];
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (esc >= 0) {
7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (c == 27 /* ESC */) {
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			esc = 0;
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_NONE;
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (esc == 6) {
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			show_esc_buf(esc_buf, c, 0);
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			esc = -1;
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			esc_buf[esc++] = c;
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			esc_buf[esc] = '\0';
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (esc == 1) {
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (esc_buf[0] != '[' && esc_buf[0] != 'O') {
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			show_esc_buf(esc_buf, c, 1);
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			esc = -1;
7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_NONE;
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_NONE; /* Escape sequence continues */
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (esc > 1) {
7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((c >= '0' && c <= '9') || c == ';')
7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return EDIT_KEY_NONE; /* Escape sequence continues */
8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (c == '~' || (c >= 'A' && c <= 'Z')) {
8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			esc = -1;
8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return esc_seq_to_key(esc_buf);
8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		show_esc_buf(esc_buf, c, 2);
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		esc = -1;
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_NONE;
8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (c) {
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 1:
8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_A;
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 2:
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_B;
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 4:
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_D;
8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 5:
8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_E;
8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 6:
8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_F;
8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 7:
8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_G;
8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 8:
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_H;
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 9:
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_TAB;
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 10:
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_J;
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 13: /* CR */
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_ENTER;
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 11:
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_K;
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 12:
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_L;
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 14:
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_N;
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 15:
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_O;
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 16:
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_P;
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 18:
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_R;
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 20:
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_T;
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 21:
8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_U;
8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 22:
8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_V;
8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 23:
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_CTRL_W;
8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 27: /* ESC */
8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		esc = 0;
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_NONE;
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 127:
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_BACKSPACE;
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return c;
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char search_buf[21];
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int search_skip;
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * search_find(void)
8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct edit_history *h;
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len = os_strlen(search_buf);
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int skip = search_skip;
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len == 0)
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_for_each(h, &history_list, struct edit_history, list) {
8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_strstr(h->str, search_buf)) {
8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (skip == 0)
8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return h->str;
8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			skip--;
8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_skip = 0;
8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void search_redraw(void)
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *match = search_find();
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("\rsearch '%s': %s" CLEAR_END_LINE,
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       search_buf, match ? match : "");
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("\rsearch '%s", search_buf);
8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fflush(stdout);
8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void search_start(void)
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_clear_line();
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_buf[0] = '\0';
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_skip = 0;
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_redraw();
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void search_clear(void)
9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_redraw();
9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("\r" CLEAR_END_LINE);
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void search_stop(void)
9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char *match = search_find();
9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_buf[0] = '\0';
9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_clear();
9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (match) {
9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_strlcpy(cmdbuf, match, CMD_BUF_LEN);
9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf_len = os_strlen(cmdbuf);
9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf_pos = cmdbuf_len;
9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void search_cancel(void)
9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_buf[0] = '\0';
9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_clear();
9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_redraw();
9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void search_backspace(void)
9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_strlen(search_buf);
9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len == 0)
9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_buf[len - 1] = '\0';
9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_skip = 0;
9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_redraw();
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void search_next(void)
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_skip++;
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_find();
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_redraw();
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void search_char(char c)
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = os_strlen(search_buf);
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len == sizeof(search_buf) - 1)
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_buf[len] = c;
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_buf[len + 1] = '\0';
9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_skip = 0;
9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	search_redraw();
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum edit_key_code search_key(enum edit_key_code c)
9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (c) {
9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_ENTER:
9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_J:
9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_LEFT:
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_RIGHT:
9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_HOME:
9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_END:
9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_A:
9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_E:
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		search_stop();
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return c;
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_DOWN:
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_UP:
9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		search_cancel();
9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return EDIT_KEY_EOF;
9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_H:
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_BACKSPACE:
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		search_backspace();
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_R:
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		search_next();
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (c >= 32 && c <= 255)
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			search_char(c);
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return EDIT_KEY_NONE;
10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void edit_read_char(int sock, void *eloop_ctx, void *sock_ctx)
10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static int last_tab = 0;
10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static int search = 0;
10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	enum edit_key_code c;
10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	c = edit_read_key(sock);
10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (search) {
10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		c = search_key(c);
10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (c == EDIT_KEY_NONE)
10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		search = 0;
10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (c == EDIT_KEY_EOF)
10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (c != EDIT_KEY_TAB && c != EDIT_KEY_NONE)
10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last_tab = 0;
10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (c) {
10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_NONE:
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_EOF:
10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		edit_eof_cb(edit_cb_ctx);
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_TAB:
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		complete(last_tab);
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		last_tab = 1;
10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_UP:
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_P:
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		history_prev();
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_DOWN:
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_N:
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		history_next();
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_RIGHT:
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_F:
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		move_right();
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_LEFT:
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_B:
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		move_left();
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_RIGHT:
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		move_word_right();
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_LEFT:
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		move_word_left();
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_DELETE:
10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		delete_current();
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_END:
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		move_end();
10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_HOME:
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_A:
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		move_start();
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_F2:
10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		history_debug_dump();
10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_D:
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (cmdbuf_len > 0) {
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			delete_current();
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("\n");
10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		edit_eof_cb(edit_cb_ctx);
10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_E:
10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		move_end();
10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_H:
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_BACKSPACE:
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		delete_left();
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_ENTER:
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_J:
10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		process_cmd();
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_K:
10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		clear_right();
10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_L:
10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		edit_clear_line();
10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		edit_redraw();
10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_R:
10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		search = 1;
10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		search_start();
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_U:
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		clear_left();
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EDIT_KEY_CTRL_W:
11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		delete_word();
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (c >= 32 && c <= 255)
11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			insert_char(c);
11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint edit_init(void (*cmd_cb)(void *ctx, char *cmd),
11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      void (*eof_cb)(void *ctx),
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      char ** (*completion_cb)(void *ctx, const char *cmd, int pos),
11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      void *ctx, const char *history_file)
11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	currbuf[0] = '\0';
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dl_list_init(&history_list);
11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	history_curr = NULL;
11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (history_file)
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		history_read(history_file);
11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_cb_ctx = ctx;
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_cmd_cb = cmd_cb;
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_eof_cb = eof_cb;
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_completion_cb = completion_cb;
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tcgetattr(STDIN_FILENO, &prevt);
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	newt = prevt;
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	newt.c_lflag &= ~(ICANON | ECHO);
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tcsetattr(STDIN_FILENO, TCSANOW, &newt);
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_read_sock(STDIN_FILENO, edit_read_char, NULL, NULL);
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("> ");
11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fflush(stdout);
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid edit_deinit(const char *history_file,
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 int (*filter_cb)(void *ctx, const char *cmd))
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct edit_history *h;
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (history_file)
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		history_write(history_file, filter_cb);
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((h = dl_list_first(&history_list, struct edit_history, list))) {
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dl_list_del(&h->list);
11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_free(h);
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	edit_clear_line();
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	putchar('\r');
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fflush(stdout);
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_unregister_read_sock(STDIN_FILENO);
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	tcsetattr(STDIN_FILENO, TCSANOW, &prevt);
11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid edit_redraw(void)
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char tmp;
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	cmdbuf[cmdbuf_len] = '\0';
11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	printf("\r> %s", cmdbuf);
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (cmdbuf_pos != cmdbuf_len) {
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		tmp = cmdbuf[cmdbuf_pos];
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf[cmdbuf_pos] = '\0';
11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		printf("\r> %s", cmdbuf);
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		cmdbuf[cmdbuf_pos] = tmp;
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fflush(stdout);
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1173