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 "common.h"
#include "eloop.h" #include "eloop.h"
#include "list.h"
#include "edit.h" #include "edit.h"
#define CMD_BUF_LEN 256 #define CMD_BUF_LEN 256
static char cmdbuf[CMD_BUF_LEN]; static char cmdbuf[CMD_BUF_LEN];
static int cmdbuf_pos = 0; static int cmdbuf_pos = 0;
static int cmdbuf_len = 0; static int cmdbuf_len = 0;
#define CMD_HISTORY_LEN 20
static char history_buf[CMD_HISTORY_LEN][CMD_BUF_LEN]; struct edit_history {
static int history_pos = 0; struct dl_list list;
static int history_current = 0; char str[1];
};
static struct dl_list history_list;
static struct edit_history *history_curr;
static void *edit_cb_ctx; static void *edit_cb_ctx;
static void (*edit_cmd_cb)(void *ctx, char *cmd); 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) static void history_add(const char *str)
{ {
int prev; struct edit_history *h, *match = NULL;
size_t len;
if (str[0] == '\0') if (str[0] == '\0')
return; return;
if (history_pos == 0) dl_list_for_each(h, &history_list, struct edit_history, list) {
prev = CMD_HISTORY_LEN - 1; if (os_strcmp(str, h->str) == 0) {
else match = h;
prev = history_pos - 1; break;
if (os_strcmp(history_buf[prev], str) == 0) }
return; }
os_strlcpy(history_buf[history_pos], str, CMD_BUF_LEN); if (match) {
history_pos++; dl_list_del(&h->list);
if (history_pos == CMD_HISTORY_LEN) dl_list_add(&history_list, &h->list);
history_pos = 0; history_curr = h;
history_current = history_pos; 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) static void history_prev(void)
{ {
int pos; if (history_curr == NULL ||
history_curr ==
if (history_current == (history_pos + 1) % CMD_HISTORY_LEN) dl_list_last(&history_list, struct edit_history, list))
return; return;
pos = history_current; if (history_curr ==
dl_list_first(&history_list, struct edit_history, list)) {
if (history_current == history_pos && cmdbuf_len) {
cmdbuf[cmdbuf_len] = '\0'; cmdbuf[cmdbuf_len] = '\0';
history_add(cmdbuf); history_add(cmdbuf);
} }
if (pos > 0) history_curr = dl_list_entry(history_curr->list.next,
pos--; struct edit_history, list);
else history_use();
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();
} }
static void history_next(void) 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; return;
history_current++; history_curr = dl_list_entry(history_curr->list.prev,
if (history_current == CMD_HISTORY_LEN) struct edit_history, list);
history_current = 0; history_use();
edit_clear_line();
cmdbuf_len = cmdbuf_pos = os_strlen(history_buf[history_current]);
os_memcpy(cmdbuf, history_buf[history_current], cmdbuf_len);
edit_redraw();
} }
static void history_debug_dump(void) static void history_debug_dump(void)
{ {
int p; struct edit_history *h;
edit_clear_line(); edit_clear_line();
printf("\r"); printf("\r");
p = (history_pos + 1) % CMD_HISTORY_LEN; dl_list_for_each_reverse(h, &history_list, struct edit_history, list)
for (;;) { printf("%s%s\n", h == history_curr ? "[C]" : "", h->str);
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;
}
edit_redraw(); edit_redraw();
} }
@ -797,29 +799,23 @@ static int search_skip;
static char * search_find(void) static char * search_find(void)
{ {
int pos = history_pos; struct edit_history *h;
size_t len = os_strlen(search_buf); size_t len = os_strlen(search_buf);
int skip = search_skip; int skip = search_skip;
if (len == 0) if (len == 0)
return NULL; return NULL;
for (;;) { dl_list_for_each(h, &history_list, struct edit_history, list) {
if (pos == 0) if (os_strstr(h->str, search_buf)) {
pos = CMD_HISTORY_LEN - 1;
else
pos--;
if (pos == history_pos) {
search_skip = 0;
return NULL;
}
if (os_strstr(history_buf[pos], search_buf)) {
if (skip == 0) if (skip == 0)
return history_buf[pos]; return h->str;
skip--; 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 (*eof_cb)(void *ctx),
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_cb_ctx = ctx;
edit_cmd_cb = cmd_cb; edit_cmd_cb = cmd_cb;
@ -1073,6 +1070,11 @@ int edit_init(void (*cmd_cb)(void *ctx, char *cmd),
void edit_deinit(void) 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); eloop_unregister_read_sock(STDIN_FILENO);
tcsetattr(STDIN_FILENO, TCSANOW, &prevt); 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_empty((list)) ? NULL : \
dl_list_entry((list)->next, type, member)) 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) \ #define dl_list_for_each(item, list, type, member) \
for (item = dl_list_entry((list)->next, type, member); \ for (item = dl_list_entry((list)->next, type, member); \
&item->member != (list); \ &item->member != (list); \
@ -86,4 +90,9 @@ static inline unsigned int dl_list_len(struct dl_list *list)
&item->member != (list); \ &item->member != (list); \
item = n, n = dl_list_entry(n->member.next, type, member)) 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 */ #endif /* LIST_H */