2 * Copyright 2004-2005 Timo Hirvonen
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 #include <sys/types.h>
30 struct history_entry
{
31 struct list_head node
;
35 static struct history_entry
*history_entry_new(const char *text
)
37 struct history_entry
*new;
38 int size
= strlen(text
) + 1;
40 new = xmalloc(sizeof(struct history_entry
) + size
);
41 memcpy(new->text
, text
, size
);
45 static int history_add_tail(void *data
, const char *line
)
47 struct history
*history
= data
;
49 if (history
->lines
< history
->max_lines
) {
50 struct history_entry
*new;
52 new = history_entry_new(line
);
53 list_add_tail(&new->node
, &history
->head
);
59 void history_load(struct history
*history
, char *filename
, int max_lines
)
61 list_init(&history
->head
);
62 history
->max_lines
= max_lines
;
64 history
->search_pos
= NULL
;
65 history
->filename
= filename
;
66 file_for_each_line(filename
, history_add_tail
, history
);
69 void history_save(struct history
*history
)
71 struct list_head
*item
;
74 fd
= open(history
->filename
, O_CREAT
| O_WRONLY
| O_TRUNC
, 0666);
77 list_for_each(item
, &history
->head
) {
78 struct history_entry
*history_entry
;
81 history_entry
= list_entry(item
, struct history_entry
, node
);
82 write(fd
, history_entry
->text
, strlen(history_entry
->text
));
88 void history_add_line(struct history
*history
, const char *line
)
90 struct history_entry
*new;
91 struct list_head
*item
;
93 new = history_entry_new(line
);
94 list_add(&new->node
, &history
->head
);
97 /* remove identical */
98 item
= history
->head
.next
->next
;
99 while (item
!= &history
->head
) {
100 struct list_head
*next
= item
->next
;
101 struct history_entry
*hentry
;
103 hentry
= container_of(item
, struct history_entry
, node
);
104 if (strcmp(hentry
->text
, new->text
) == 0) {
112 /* remove oldest if history is 'full' */
113 if (history
->lines
> history
->max_lines
) {
114 struct list_head
*node
;
115 struct history_entry
*hentry
;
117 node
= history
->head
.prev
;
119 hentry
= list_entry(node
, struct history_entry
, node
);
125 void history_reset_search(struct history
*history
)
127 history
->search_pos
= NULL
;
130 const char *history_search_forward(struct history
*history
, const char *text
)
132 struct list_head
*item
;
135 if (history
->search_pos
== NULL
) {
136 /* first time to search. set search */
137 item
= history
->head
.next
;
139 item
= history
->search_pos
->next
;
141 search_len
= strlen(text
);
142 while (item
!= &history
->head
) {
143 struct history_entry
*hentry
;
145 hentry
= list_entry(item
, struct history_entry
, node
);
146 if (strncmp(text
, hentry
->text
, search_len
) == 0) {
147 history
->search_pos
= item
;
155 const char *history_search_backward(struct history
*history
, const char *text
)
157 struct list_head
*item
;
160 if (history
->search_pos
== NULL
)
162 item
= history
->search_pos
->prev
;
163 search_len
= strlen(text
);
164 while (item
!= &history
->head
) {
165 struct history_entry
*hentry
;
167 hentry
= list_entry(item
, struct history_entry
, node
);
168 if (strncmp(text
, hentry
->text
, search_len
) == 0) {
169 history
->search_pos
= item
;
174 history
->search_pos
= NULL
;