edit: Use struct dl_list for history buffer

This commit is contained in:
Jouni Malinen 2010-11-21 11:25:34 +02:00
parent 31e1206baa
commit ec9aac9468
2 changed files with 80 additions and 69 deletions

View file

@ -17,16 +17,21 @@
#include "common.h"
#include "eloop.h"
#include "list.h"
#include "edit.h"
#define CMD_BUF_LEN 256
static char cmdbuf[CMD_BUF_LEN];
static int cmdbuf_pos = 0;
static int cmdbuf_len = 0;
#define CMD_HISTORY_LEN 20
static char history_buf[CMD_HISTORY_LEN][CMD_BUF_LEN];
static int history_pos = 0;
static int history_current = 0;
struct edit_history {
struct dl_list list;
char str[1];
};
static struct dl_list history_list;
static struct edit_history *history_curr;
static void *edit_cb_ctx;
static void (*edit_cmd_cb)(void *ctx, char *cmd);
@ -171,87 +176,84 @@ static void clear_right(void)
static void history_add(const char *str)
{
int prev;
struct edit_history *h, *match = NULL;
size_t len;
if (str[0] == '\0')
return;
if (history_pos == 0)
prev = CMD_HISTORY_LEN - 1;
else
prev = history_pos - 1;
if (os_strcmp(history_buf[prev], str) == 0)
return;
dl_list_for_each(h, &history_list, struct edit_history, list) {
if (os_strcmp(str, h->str) == 0) {
match = h;
break;
}
}
os_strlcpy(history_buf[history_pos], str, CMD_BUF_LEN);
history_pos++;
if (history_pos == CMD_HISTORY_LEN)
history_pos = 0;
history_current = history_pos;
if (match) {
dl_list_del(&h->list);
dl_list_add(&history_list, &h->list);
history_curr = h;
return;
}
len = os_strlen(str);
h = os_zalloc(sizeof(*h) + len);
if (h == NULL)
return;
dl_list_add(&history_list, &h->list);
os_strlcpy(h->str, str, len + 1);
history_curr = h;
}
static void history_use(void)
{
edit_clear_line();
cmdbuf_len = cmdbuf_pos = os_strlen(history_curr->str);
os_memcpy(cmdbuf, history_curr->str, cmdbuf_len);
edit_redraw();
}
static void history_prev(void)
{
int pos;
if (history_current == (history_pos + 1) % CMD_HISTORY_LEN)
if (history_curr == NULL ||
history_curr ==
dl_list_last(&history_list, struct edit_history, list))
return;
pos = history_current;
if (history_current == history_pos && cmdbuf_len) {
if (history_curr ==
dl_list_first(&history_list, struct edit_history, list)) {
cmdbuf[cmdbuf_len] = '\0';
history_add(cmdbuf);
}
if (pos > 0)
pos--;
else
pos = CMD_HISTORY_LEN - 1;
if (history_buf[pos][0] == '\0')
return;
history_current = pos;
edit_clear_line();
cmdbuf_len = cmdbuf_pos = os_strlen(history_buf[history_current]);
os_memcpy(cmdbuf, history_buf[history_current], cmdbuf_len);
edit_redraw();
history_curr = dl_list_entry(history_curr->list.next,
struct edit_history, list);
history_use();
}
static void history_next(void)
{
if (history_current == history_pos)
if (history_curr == NULL ||
history_curr ==
dl_list_first(&history_list, struct edit_history, list))
return;
history_current++;
if (history_current == CMD_HISTORY_LEN)
history_current = 0;
edit_clear_line();
cmdbuf_len = cmdbuf_pos = os_strlen(history_buf[history_current]);
os_memcpy(cmdbuf, history_buf[history_current], cmdbuf_len);
edit_redraw();
history_curr = dl_list_entry(history_curr->list.prev,
struct edit_history, list);
history_use();
}
static void history_debug_dump(void)
{
int p;
struct edit_history *h;
edit_clear_line();
printf("\r");
p = (history_pos + 1) % CMD_HISTORY_LEN;
for (;;) {
printf("[%d%s%s] %s\n",
p, p == history_current ? "C" : "",
p == history_pos ? "P" : "", history_buf[p]);
if (p == history_pos)
break;
p++;
if (p == CMD_HISTORY_LEN)
p = 0;
}
dl_list_for_each_reverse(h, &history_list, struct edit_history, list)
printf("%s%s\n", h == history_curr ? "[C]" : "", h->str);
edit_redraw();
}
@ -797,29 +799,23 @@ static int search_skip;
static char * search_find(void)
{
int pos = history_pos;
struct edit_history *h;
size_t len = os_strlen(search_buf);
int skip = search_skip;
if (len == 0)
return NULL;
for (;;) {
if (pos == 0)
pos = CMD_HISTORY_LEN - 1;
else
pos--;
if (pos == history_pos) {
search_skip = 0;
return NULL;
}
if (os_strstr(history_buf[pos], search_buf)) {
dl_list_for_each(h, &history_list, struct edit_history, list) {
if (os_strstr(h->str, search_buf)) {
if (skip == 0)
return history_buf[pos];
return h->str;
skip--;
}
}
search_skip = 0;
return NULL;
}
@ -1051,7 +1047,8 @@ int edit_init(void (*cmd_cb)(void *ctx, char *cmd),
void (*eof_cb)(void *ctx),
void *ctx)
{
os_memset(history_buf, 0, sizeof(history_buf));
dl_list_init(&history_list);
history_curr = NULL;
edit_cb_ctx = ctx;
edit_cmd_cb = cmd_cb;
@ -1073,6 +1070,11 @@ int edit_init(void (*cmd_cb)(void *ctx, char *cmd),
void edit_deinit(void)
{
struct edit_history *h;
while ((h = dl_list_first(&history_list, struct edit_history, list))) {
dl_list_del(&h->list);
os_free(h);
}
eloop_unregister_read_sock(STDIN_FILENO);
tcsetattr(STDIN_FILENO, TCSANOW, &prevt);
}

View file

@ -75,6 +75,10 @@ static inline unsigned int dl_list_len(struct dl_list *list)
(dl_list_empty((list)) ? NULL : \
dl_list_entry((list)->next, type, member))
#define dl_list_last(list, type, member) \
(dl_list_empty((list)) ? NULL : \
dl_list_entry((list)->prev, type, member))
#define dl_list_for_each(item, list, type, member) \
for (item = dl_list_entry((list)->next, type, member); \
&item->member != (list); \
@ -86,4 +90,9 @@ static inline unsigned int dl_list_len(struct dl_list *list)
&item->member != (list); \
item = n, n = dl_list_entry(n->member.next, type, member))
#define dl_list_for_each_reverse(item, list, type, member) \
for (item = dl_list_entry((list)->prev, type, member); \
&item->member != (list); \
item = dl_list_entry(item->member.prev, type, member))
#endif /* LIST_H */