Mercurial > geeqie
annotate src/history_list.c @ 1660:da8afd03152f
improved file list update priority
- update list with lower priority than the priority of file operations
- make sure that it is updated at least once per 2 seconds
author | nadvornik |
---|---|
date | Sun, 21 Jun 2009 20:14:53 +0000 |
parents | 7e180091e0b7 |
children | 956aab097ea7 |
rev | line source |
---|---|
902 | 1 /* |
2 * Geeqie | |
1284 | 3 * Copyright (C) 2008 - 2009 The Geeqie Team |
902 | 4 * |
5 * Authors: John Ellis, Vladimir Nadvornik, Laurent Monin | |
6 * | |
7 * | |
8 * This software is released under the GNU General Public License (GNU GPL). | |
9 * Please read the included file COPYING for more information. | |
10 * This software comes with no warranty of any kind, use at your own risk! | |
11 */ | |
12 | |
13 #include "main.h" | |
14 #include "history_list.h" | |
15 | |
16 #include "secure_save.h" | |
17 #include "ui_fileops.h" | |
18 | |
19 /* | |
20 *----------------------------------------------------------------------------- | |
21 * history lists | |
22 *----------------------------------------------------------------------------- | |
23 */ | |
24 | |
25 #define HISTORY_DEFAULT_KEY_COUNT 16 | |
26 | |
27 | |
28 typedef struct _HistoryData HistoryData; | |
29 struct _HistoryData | |
30 { | |
31 gchar *key; | |
32 GList *list; | |
33 }; | |
34 | |
35 static GList *history_list = NULL; | |
36 | |
37 | |
38 static gchar *quoted_from_text(const gchar *text) | |
39 { | |
40 const gchar *ptr; | |
41 gint c = 0; | |
42 gint l = strlen(text); | |
43 | |
44 if (l == 0) return NULL; | |
45 | |
46 while (c < l && text[c] !='"') c++; | |
47 if (text[c] == '"') | |
48 { | |
49 gint e; | |
50 c++; | |
51 ptr = text + c; | |
52 e = c; | |
53 while (e < l && text[e] !='"') e++; | |
54 if (text[e] == '"') | |
55 { | |
56 if (e - c > 0) | |
57 { | |
58 return g_strndup(ptr, e - c); | |
59 } | |
60 } | |
61 } | |
62 return NULL; | |
63 } | |
64 | |
1431 | 65 gboolean history_list_load(const gchar *path) |
902 | 66 { |
67 FILE *f; | |
68 gchar *key = NULL; | |
69 gchar s_buf[1024]; | |
70 gchar *pathl; | |
71 | |
72 pathl = path_from_utf8(path); | |
73 f = fopen(pathl, "r"); | |
74 g_free(pathl); | |
75 if (!f) return FALSE; | |
76 | |
77 /* first line must start with History comment */ | |
78 if (!fgets(s_buf, sizeof(s_buf), f) || | |
79 strncmp(s_buf, "#History", 8) != 0) | |
80 { | |
81 fclose(f); | |
82 return FALSE; | |
83 } | |
84 | |
85 while (fgets(s_buf, sizeof(s_buf), f)) | |
86 { | |
87 if (s_buf[0]=='#') continue; | |
88 if (s_buf[0]=='[') | |
89 { | |
90 gint c; | |
91 gchar *ptr; | |
92 | |
93 ptr = s_buf + 1; | |
94 c = 0; | |
95 while (ptr[c] != ']' && ptr[c] != '\n' && ptr[c] != '\0') c++; | |
96 | |
97 g_free(key); | |
98 key = g_strndup(ptr, c); | |
99 } | |
100 else | |
101 { | |
102 gchar *value; | |
103 | |
104 value = quoted_from_text(s_buf); | |
105 if (value && key) | |
106 { | |
107 history_list_add_to_key(key, value, 0); | |
108 } | |
109 g_free(value); | |
110 } | |
111 } | |
112 | |
113 fclose(f); | |
114 | |
115 g_free(key); | |
116 | |
117 return TRUE; | |
118 } | |
119 | |
1431 | 120 gboolean history_list_save(const gchar *path) |
902 | 121 { |
122 SecureSaveInfo *ssi; | |
123 GList *list; | |
124 gchar *pathl; | |
125 | |
126 pathl = path_from_utf8(path); | |
127 ssi = secure_open(pathl); | |
128 g_free(pathl); | |
129 if (!ssi) | |
130 { | |
131 log_printf(_("Unable to write history lists to: %s\n"), path); | |
132 return FALSE; | |
133 } | |
134 | |
135 secure_fprintf(ssi, "#History lists\n\n"); | |
136 | |
137 list = g_list_last(history_list); | |
138 while (list && secsave_errno == SS_ERR_NONE) | |
139 { | |
140 HistoryData *hd; | |
141 GList *work; | |
142 | |
143 hd = list->data; | |
144 list = list->prev; | |
145 | |
146 secure_fprintf(ssi, "[%s]\n", hd->key); | |
147 | |
148 /* save them inverted (oldest to newest) | |
149 * so that when reading they are added correctly | |
150 */ | |
151 work = g_list_last(hd->list); | |
152 while (work && secsave_errno == SS_ERR_NONE) | |
153 { | |
154 secure_fprintf(ssi, "\"%s\"\n", (gchar *)work->data); | |
155 work = work->prev; | |
156 } | |
157 secure_fputc(ssi, '\n'); | |
158 } | |
159 | |
160 secure_fprintf(ssi, "#end\n"); | |
161 | |
162 return (secure_close(ssi) == 0); | |
163 } | |
164 | |
165 static void history_list_free(HistoryData *hd) | |
166 { | |
167 GList *work; | |
168 | |
169 if (!hd) return; | |
170 | |
171 work = hd->list; | |
172 while (work) | |
173 { | |
174 g_free(work->data); | |
175 work = work->next; | |
176 } | |
177 | |
178 g_free(hd->key); | |
179 g_free(hd); | |
180 } | |
181 | |
1000
4fe8f9656107
For the sake of consistency, use glib basic types everywhere.
zas_
parents:
902
diff
changeset
|
182 static HistoryData *history_list_find_by_key(const gchar *key) |
902 | 183 { |
184 GList *work = history_list; | |
185 | |
186 if (!key) return NULL; | |
187 | |
188 while (work) | |
189 { | |
190 HistoryData *hd = work->data; | |
191 if (strcmp(hd->key, key) == 0) return hd; | |
192 work = work->next; | |
193 } | |
194 return NULL; | |
195 } | |
196 | |
1000
4fe8f9656107
For the sake of consistency, use glib basic types everywhere.
zas_
parents:
902
diff
changeset
|
197 const gchar *history_list_find_last_path_by_key(const gchar *key) |
902 | 198 { |
199 HistoryData *hd; | |
200 | |
201 hd = history_list_find_by_key(key); | |
202 if (!hd || !hd->list) return NULL; | |
203 | |
204 return hd->list->data; | |
205 } | |
206 | |
207 void history_list_free_key(const gchar *key) | |
208 { | |
209 HistoryData *hd; | |
210 hd = history_list_find_by_key(key); | |
211 if (!hd) return; | |
212 | |
213 history_list = g_list_remove(history_list, hd); | |
214 history_list_free(hd); | |
215 } | |
216 | |
217 void history_list_add_to_key(const gchar *key, const gchar *path, gint max) | |
218 { | |
219 HistoryData *hd; | |
220 GList *work; | |
221 | |
222 if (!key || !path) return; | |
223 | |
224 hd = history_list_find_by_key(key); | |
225 if (!hd) | |
226 { | |
227 hd = g_new(HistoryData, 1); | |
228 hd->key = g_strdup(key); | |
229 hd->list = NULL; | |
230 history_list = g_list_prepend(history_list, hd); | |
231 } | |
232 | |
233 /* if already in the list, simply move it to the top */ | |
234 work = hd->list; | |
235 while (work) | |
236 { | |
237 gchar *buf = work->data; | |
238 | |
239 if (strcmp(buf, path) == 0) | |
240 { | |
241 /* if not first, move it */ | |
242 if (work != hd->list) | |
243 { | |
244 hd->list = g_list_remove(hd->list, buf); | |
245 hd->list = g_list_prepend(hd->list, buf); | |
246 } | |
247 return; | |
248 } | |
249 work = work->next; | |
250 } | |
251 | |
252 hd->list = g_list_prepend(hd->list, g_strdup(path)); | |
253 | |
254 if (max == -1) max = HISTORY_DEFAULT_KEY_COUNT; | |
255 if (max > 0) | |
256 { | |
257 gint len = 0; | |
258 GList *work = hd->list; | |
259 GList *last = NULL; | |
260 | |
261 while (work) | |
262 { | |
263 len++; | |
264 last = work; | |
265 work = work->next; | |
266 } | |
267 | |
268 work = last; | |
269 while (work && len > max) | |
270 { | |
271 GList *node = work; | |
272 work = work->prev; | |
273 | |
274 g_free(node->data); | |
275 hd->list = g_list_delete_link(hd->list, node); | |
276 len--; | |
277 } | |
278 } | |
279 } | |
280 | |
281 void history_list_item_change(const gchar *key, const gchar *oldpath, const gchar *newpath) | |
282 { | |
283 HistoryData *hd; | |
284 GList *work; | |
285 | |
286 if (!oldpath) return; | |
287 hd = history_list_find_by_key(key); | |
288 if (!hd) return; | |
289 | |
290 work = hd->list; | |
291 while (work) | |
292 { | |
293 gchar *buf = work->data; | |
294 if (strcmp(buf, oldpath) == 0) | |
295 { | |
296 if (newpath) | |
297 { | |
298 work->data = g_strdup(newpath); | |
299 } | |
300 else | |
301 { | |
302 hd->list = g_list_remove(hd->list, buf); | |
303 } | |
304 g_free(buf); | |
305 return; | |
306 } | |
307 work = work->next; | |
308 } | |
309 } | |
310 | |
311 void history_list_item_move(const gchar *key, const gchar *path, gint direction) | |
312 { | |
313 HistoryData *hd; | |
314 GList *work; | |
315 gint p = 0; | |
316 | |
317 if (!path) return; | |
318 hd = history_list_find_by_key(key); | |
319 if (!hd) return; | |
320 | |
321 work = hd->list; | |
322 while (work) | |
323 { | |
324 gchar *buf = work->data; | |
325 if (strcmp(buf, path) == 0) | |
326 { | |
327 p += direction; | |
328 if (p < 0) return; | |
329 hd->list = g_list_remove(hd->list, buf); | |
330 hd->list = g_list_insert(hd->list, buf, p); | |
331 return; | |
332 } | |
333 work = work->next; | |
334 p++; | |
335 } | |
336 } | |
337 | |
338 void history_list_item_remove(const gchar *key, const gchar *path) | |
339 { | |
340 history_list_item_change(key, path, NULL); | |
341 } | |
342 | |
343 GList *history_list_get_by_key(const gchar *key) | |
344 { | |
345 HistoryData *hd; | |
346 | |
347 hd = history_list_find_by_key(key); | |
348 if (!hd) return NULL; | |
349 | |
350 return hd->list; | |
351 } | |
1055
1646720364cf
Adding a vim modeline to all files - patch by Klaus Ethgen
nadvornik
parents:
1000
diff
changeset
|
352 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ |