Browse Source

edit: Use struct dl_list for history buffer

Jouni Malinen 14 years ago
parent
commit
ec9aac9468
2 changed files with 79 additions and 68 deletions
  1. 70 68
      src/utils/edit.c
  2. 9 0
      src/utils/list.h

+ 70 - 68
src/utils/edit.c

@@ -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)
+	dl_list_for_each(h, &history_list, struct edit_history, list) {
+		if (os_strcmp(str, h->str) == 0) {
+			match = h;
+			break;
+		}
+	}
+
+	if (match) {
+		dl_list_del(&h->list);
+		dl_list_add(&history_list, &h->list);
+		history_curr = h;
 		return;
+	}
 
-	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;
+	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_prev(void)
+static void history_use(void)
 {
-	int pos;
+	edit_clear_line();
+	cmdbuf_len = cmdbuf_pos = os_strlen(history_curr->str);
+	os_memcpy(cmdbuf, history_curr->str, cmdbuf_len);
+	edit_redraw();
+}
 
-	if (history_current == (history_pos + 1) % CMD_HISTORY_LEN)
-		return;
 
-	pos = history_current;
+static void history_prev(void)
+{
+	if (history_curr == NULL ||
+	    history_curr ==
+	    dl_list_last(&history_list, struct edit_history, list))
+		return;
 
-	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);
 }

+ 9 - 0
src/utils/list.h

@@ -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 */