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