1 /* $Id: history.c,v 1.11 2003/09/26 17:59:51 ukai Exp $ */
2 #include "fm.h"
3 
4 #ifdef USE_HISTORY
5 Buffer *
historyBuffer(Hist * hist)6 historyBuffer(Hist *hist)
7 {
8     Str src = Strnew();
9     HistItem *item;
10     char *p, *q;
11 
12     /* FIXME: gettextize? */
13     Strcat_charp(src, "<html>\n<head><title>History Page</title></head>\n");
14     Strcat_charp(src, "<body>\n<h1>History Page</h1>\n<hr>\n");
15     Strcat_charp(src, "<ol>\n");
16     if (hist && hist->list) {
17 	for (item = hist->list->last; item; item = item->prev) {
18 	    q = html_quote((char *)item->ptr);
19 	    if (DecodeURL)
20 		p = html_quote(url_decode2((char *)item->ptr, NULL));
21 	    else
22 		p = q;
23 	    Strcat_charp(src, "<li><a href=\"");
24 	    Strcat_charp(src, q);
25 	    Strcat_charp(src, "\">");
26 	    Strcat_charp(src, p);
27 	    Strcat_charp(src, "</a>\n");
28 	}
29     }
30     Strcat_charp(src, "</ol>\n</body>\n</html>");
31     return loadHTMLString(src);
32 }
33 
34 void
loadHistory(Hist * hist)35 loadHistory(Hist *hist)
36 {
37     FILE *f;
38     Str line;
39 
40     if (hist == NULL)
41 	return;
42     if ((f = fopen(rcFile(HISTORY_FILE), "rt")) == NULL)
43 	return;
44 
45     while (!feof(f)) {
46 	line = Strfgets(f);
47 	Strchop(line);
48 	Strremovefirstspaces(line);
49 	Strremovetrailingspaces(line);
50 	if (line->length == 0)
51 	    continue;
52 	pushHist(hist, url_quote(line->ptr));
53     }
54     fclose(f);
55 }
56 
57 void
saveHistory(Hist * hist,size_t size)58 saveHistory(Hist *hist, size_t size)
59 {
60     FILE *f;
61     HistItem *item;
62     char *tmpf;
63     int rename_ret;
64 
65     if (hist == NULL || hist->list == NULL)
66 	return;
67     tmpf = tmpfname(TMPF_DFL, NULL)->ptr;
68     if ((f = fopen(tmpf, "w")) == NULL) {
69 	/* FIXME: gettextize? */
70 	disp_err_message("Can't open history", FALSE);
71 	return;
72     }
73     for (item = hist->list->first; item && hist->list->nitem > size;
74 	 item = item->next)
75 	size++;
76     for (; item; item = item->next)
77 	fprintf(f, "%s\n", (char *)item->ptr);
78     if (fclose(f) == EOF) {
79 	/* FIXME: gettextize? */
80 	disp_err_message("Can't save history", FALSE);
81 	return;
82     }
83     rename_ret = rename(tmpf, rcFile(HISTORY_FILE));
84     if (rename_ret != 0) {
85 	disp_err_message("Can't save history", FALSE);
86 	return;
87     }
88 }
89 #endif				/* USE_HISTORY */
90 
91 Hist *
newHist()92 newHist()
93 {
94     Hist *hist;
95 
96     hist = New(Hist);
97     hist->list = (HistList *)newGeneralList();
98     hist->current = NULL;
99     hist->hash = NULL;
100     return hist;
101 }
102 
103 Hist *
copyHist(Hist * hist)104 copyHist(Hist *hist)
105 {
106     Hist *new;
107     HistItem *item;
108 
109     if (hist == NULL)
110 	return NULL;
111     new = newHist();
112     for (item = hist->list->first; item; item = item->next)
113 	pushHist(new, (char *)item->ptr);
114     return new;
115 }
116 
117 HistItem *
unshiftHist(Hist * hist,char * ptr)118 unshiftHist(Hist *hist, char *ptr)
119 {
120     HistItem *item;
121 
122     if (hist == NULL || hist->list == NULL ||
123 	hist->list->nitem >= HIST_LIST_MAX)
124 	return NULL;
125     item = (HistItem *)newListItem((void *)allocStr(ptr, -1),
126 				   (ListItem *)hist->list->first, NULL);
127     if (hist->list->first)
128 	hist->list->first->prev = item;
129     else
130 	hist->list->last = item;
131     hist->list->first = item;
132     hist->list->nitem++;
133     return item;
134 }
135 
136 HistItem *
pushHist(Hist * hist,char * ptr)137 pushHist(Hist *hist, char *ptr)
138 {
139     HistItem *item;
140 
141     if (hist == NULL || hist->list == NULL ||
142 	hist->list->nitem >= HIST_LIST_MAX)
143 	return NULL;
144     item = (HistItem *)newListItem((void *)allocStr(ptr, -1),
145 				   NULL, (ListItem *)hist->list->last);
146     if (hist->list->last)
147 	hist->list->last->next = item;
148     else
149 	hist->list->first = item;
150     hist->list->last = item;
151     hist->list->nitem++;
152     return item;
153 }
154 
155 /* Don't mix pushHashHist() and pushHist()/unshiftHist(). */
156 
157 HistItem *
pushHashHist(Hist * hist,char * ptr)158 pushHashHist(Hist *hist, char *ptr)
159 {
160     HistItem *item;
161 
162     if (hist == NULL || hist->list == NULL ||
163 	hist->list->nitem >= HIST_LIST_MAX)
164 	return NULL;
165     item = getHashHist(hist, ptr);
166     if (item) {
167 	if (item->next)
168 	    item->next->prev = item->prev;
169 	else			/* item == hist->list->last */
170 	    hist->list->last = item->prev;
171 	if (item->prev)
172 	    item->prev->next = item->next;
173 	else			/* item == hist->list->first */
174 	    hist->list->first = item->next;
175 	hist->list->nitem--;
176     }
177     item = pushHist(hist, ptr);
178     putHash_sv(hist->hash, ptr, (void *)item);
179     return item;
180 }
181 
182 HistItem *
getHashHist(Hist * hist,char * ptr)183 getHashHist(Hist *hist, char *ptr)
184 {
185     HistItem *item;
186 
187     if (hist == NULL || hist->list == NULL)
188 	return NULL;
189     if (hist->hash == NULL) {
190 	hist->hash = newHash_sv(HIST_HASH_SIZE);
191 	for (item = hist->list->first; item; item = item->next)
192 	    putHash_sv(hist->hash, (char *)item->ptr, (void *)item);
193     }
194     return (HistItem *)getHash_sv(hist->hash, ptr, NULL);
195 }
196 
197 char *
lastHist(Hist * hist)198 lastHist(Hist *hist)
199 {
200     if (hist == NULL || hist->list == NULL)
201 	return NULL;
202     if (hist->list->last) {
203 	hist->current = hist->list->last;
204 	return (char *)hist->current->ptr;
205     }
206     return NULL;
207 }
208 
209 char *
nextHist(Hist * hist)210 nextHist(Hist *hist)
211 {
212     if (hist == NULL || hist->list == NULL)
213 	return NULL;
214     if (hist->current && hist->current->next) {
215 	hist->current = hist->current->next;
216 	return (char *)hist->current->ptr;
217     }
218     return NULL;
219 }
220 
221 char *
prevHist(Hist * hist)222 prevHist(Hist *hist)
223 {
224     if (hist == NULL || hist->list == NULL)
225 	return NULL;
226     if (hist->current && hist->current->prev) {
227 	hist->current = hist->current->prev;
228 	return (char *)hist->current->ptr;
229     }
230     return NULL;
231 }
232