comparison src/filelist.c @ 9:d907d608745f

Sync to GQview 1.5.9 release. ######## DO NOT BASE ENHANCEMENTS OR TRANSLATION UPDATES ON CODE IN THIS CVS! This CVS is never up to date with current development and is provided solely for reference purposes, please use the latest official release package when making any changes or translation updates. ########
author gqview
date Sat, 26 Feb 2005 00:13:35 +0000
parents c0e337a01cb7
children 3263965d5f9e
comparison
equal deleted inserted replaced
8:e0d0593d519e 9:d907d608745f
1 /* 1 /*
2 * GQview image viewer 2 * GQview
3 * (C)2000 John Ellis 3 * (C) 2004 John Ellis
4 * 4 *
5 * Author: John Ellis 5 * Author: John Ellis
6 * 6 *
7 * This software is released under the GNU General Public License (GNU GPL).
8 * Please read the included file COPYING for more information.
9 * This software comes with no warranty of any kind, use at your own risk!
7 */ 10 */
8 11
12
9 #include "gqview.h" 13 #include "gqview.h"
10 14 #include "filelist.h"
11 static gint filelist_click_row = -1; 15
12 16 #include "cache.h"
13 static void update_progressbar(gfloat val); 17 #include "rcfile.h"
14 18 #include "ui_fileops.h"
15 static gint file_is_hidden(gchar *name); 19
16 static gint file_is_in_filter(gchar *name);
17 static void add_to_filter(gchar *text, gint add);
18
19 static gint sort_list_cb(void *a, void *b);
20 static void filelist_read(gchar *path);
21
22 static gint file_find_closest_unaccounted(gint row, gint count, GList *ignore_list);
23
24 static void history_menu_select_cb(GtkWidget *widget, gpointer data);
25 static gchar *truncate_hist_text(gchar *t, gint l);
26 static void filelist_set_history(gchar *path);
27 20
28 /* 21 /*
29 *----------------------------------------------------------------------------- 22 *-----------------------------------------------------------------------------
30 * file status information (private) 23 * file filtering
31 *----------------------------------------------------------------------------- 24 *-----------------------------------------------------------------------------
32 */ 25 */
33 26
34 static void update_progressbar(gfloat val) 27 static GList *filter_list = NULL;
35 { 28 static GList *extension_list = NULL;
36 gtk_progress_bar_update (GTK_PROGRESS_BAR(info_progress_bar), val); 29
37 } 30 gint ishidden(const gchar *name)
38
39 void update_status_label(gchar *text)
40 {
41 gchar *buf;
42 gint count;
43 gchar *ss = "";
44
45 if (text)
46 {
47 gtk_label_set(GTK_LABEL(info_status), text);
48 return;
49 }
50
51 if (slideshow_is_running()) ss = _(" Slideshow");
52
53 count = file_selection_count();
54 if (count > 0)
55 buf = g_strdup_printf(_("%d files (%d)%s"), file_count(), count, ss);
56 else
57 buf = g_strdup_printf(_("%d files%s"), file_count(), ss);
58
59 gtk_label_set(GTK_LABEL(info_status), buf);
60 g_free(buf);
61 }
62
63 /*
64 *-----------------------------------------------------------------------------
65 * file filtering
66 *-----------------------------------------------------------------------------
67 */
68
69 static gint file_is_hidden(gchar *name)
70 { 31 {
71 if (name[0] != '.') return FALSE; 32 if (name[0] != '.') return FALSE;
72 if (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')) return FALSE; 33 if (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')) return FALSE;
73 return TRUE; 34 return TRUE;
74 } 35 }
75 36
76 static gint file_is_in_filter(gchar *name) 37 static FilterEntry *filter_entry_new(const gchar *key, const gchar *description,
77 { 38 const gchar *extensions, gint enabled)
78 GList *work; 39 {
79 if (!filename_filter || file_filter_disable) return TRUE; 40 FilterEntry *fe;
80 41
81 work = filename_filter; 42 fe = g_new0(FilterEntry, 1);
43 fe->key = g_strdup(key);
44 fe->description = g_strdup(description);
45 fe->extensions = g_strdup(extensions);
46 fe->enabled = enabled;
47
48 return fe;
49 }
50
51 static void filter_entry_free(FilterEntry *fe)
52 {
53 if (!fe) return;
54
55 g_free(fe->key);
56 g_free(fe->description);
57 g_free(fe->extensions);
58 g_free(fe);
59 }
60
61 GList *filter_get_list(void)
62 {
63 return filter_list;
64 }
65
66 void filter_remove_entry(FilterEntry *fe)
67 {
68 if (!g_list_find(filter_list, fe)) return;
69
70 filter_list = g_list_remove(filter_list, fe);
71 filter_entry_free(fe);
72 }
73
74 static gint filter_key_exists(const gchar *key)
75 {
76 GList *work;
77
78 if (!key) return FALSE;
79
80 work = filter_list;
81 while (work)
82 {
83 FilterEntry *fe = work->data;
84 work = work->next;
85
86 if (strcmp(fe->key, key) == 0) return TRUE;
87 }
88
89 return FALSE;
90 }
91
92 void filter_add(const gchar *key, const gchar *description, const gchar *extensions, gint enabled)
93 {
94 filter_list = g_list_append(filter_list, filter_entry_new(key, description, extensions, enabled));
95 }
96
97 void filter_add_unique(const gchar *description, const gchar *extensions, gint enabled)
98 {
99 gchar *key;
100 gint n;
101
102 key = g_strdup("user0");
103 n = 1;
104 while (filter_key_exists(key))
105 {
106 g_free(key);
107 if (n > 999) return;
108 key = g_strdup_printf("user%d", n);
109 n++;
110 }
111
112 filter_add(key, description, extensions, enabled);
113 g_free(key);
114 }
115
116 static void filter_add_if_missing(const gchar *key, const gchar *description, const gchar *extensions, gint enabled)
117 {
118 GList *work;
119
120 if (!key) return;
121
122 work = filter_list;
123 while (work)
124 {
125 FilterEntry *fe = work->data;
126 work = work->next;
127 if (fe->key && strcmp(fe->key, key) == 0) return;
128 }
129
130 filter_add(key, description, extensions, enabled);
131 }
132
133 void filter_reset(void)
134 {
135 GList *work;
136
137 work = filter_list;
138 while (work)
139 {
140 FilterEntry *fe = work->data;
141 work = work->next;
142 filter_entry_free(fe);
143 }
144
145 g_list_free(filter_list);
146 filter_list = NULL;
147 }
148
149 void filter_add_defaults(void)
150 {
151 GSList *list, *work;
152
153 list = gdk_pixbuf_get_formats();
154 work = list;
155 while (work)
156 {
157 GdkPixbufFormat *format;
158 gchar *name;
159 gchar *desc;
160 gchar **extensions;
161 GString *filter = NULL;
162 gint i;
163
164 format = work->data;
165 work = work->next;
166
167 name = gdk_pixbuf_format_get_name(format);
168 desc = gdk_pixbuf_format_get_description(format);
169 extensions = gdk_pixbuf_format_get_extensions(format);
170
171 i = 0;
172 while (extensions[i])
173 {
174 if (!filter)
175 {
176 filter = g_string_new(".");
177 filter = g_string_append(filter, extensions[i]);
178 }
179 else
180 {
181 filter = g_string_append(filter, ";.");
182 filter = g_string_append(filter, extensions[i]);
183 }
184 i++;
185 }
186
187 if (debug) printf("loader reported [%s] [%s] [%s]\n", name, desc, filter->str);
188
189 filter_add_if_missing(name, desc, filter->str, TRUE);
190
191 g_free(name);
192 g_free(desc);
193 g_strfreev(extensions);
194 g_string_free(filter, TRUE);
195 }
196 g_slist_free(list);
197
198 /* add defaults even if gdk-pixbuf does not have them, but disabled */
199 filter_add_if_missing("jpeg", "JPEG group", ".jpg;.jpeg;.jpe", FALSE);
200 filter_add_if_missing("png", "Portable Network Graphic", ".png", FALSE);
201 filter_add_if_missing("tiff", "Tiff", ".tif;.tiff", FALSE);
202 filter_add_if_missing("pnm", "Packed Pixel formats", ".pbm;.pgm;.pnm;.ppm", FALSE);
203 filter_add_if_missing("gif", "Graphics Interchange Format", ".gif", FALSE);
204 filter_add_if_missing("xbm", "X bitmap", ".xbm", FALSE);
205 filter_add_if_missing("xpm", "X pixmap", ".xpm", FALSE);
206 filter_add_if_missing("bmp", "Bitmap", ".bmp", FALSE);
207 filter_add_if_missing("ico", "Icon file", ".ico;.cur", FALSE);
208 filter_add_if_missing("ras", "Raster", ".ras", FALSE);
209 filter_add_if_missing("svg", "Scalable Vector Graphics", ".svg", FALSE);
210 }
211
212 static GList *filter_to_list(const gchar *extensions)
213 {
214 GList *list = NULL;
215 const gchar *p;
216
217 if (!extensions) return NULL;
218
219 p = extensions;
220 while (*p != '\0')
221 {
222 const gchar *b;
223 gint l = 0;
224
225 b = p;
226 while (*p != '\0' && *p != ';')
227 {
228 p++;
229 l++;
230 }
231 list = g_list_append(list, g_strndup(b, l));
232 if (*p == ';') p++;
233 }
234
235 return list;
236 }
237
238 void filter_rebuild(void)
239 {
240 GList *work;
241
242 path_list_free(extension_list);
243 extension_list = NULL;
244
245 work = filter_list;
246 while (work)
247 {
248 FilterEntry *fe;
249
250 fe = work->data;
251 work = work->next;
252
253 if (fe->enabled)
254 {
255 GList *ext;
256
257 ext = filter_to_list(fe->extensions);
258 if (ext) extension_list = g_list_concat(extension_list, ext);
259 }
260 }
261 }
262
263 gint filter_name_exists(const gchar *name)
264 {
265 GList *work;
266 if (!extension_list || file_filter_disable) return TRUE;
267
268 work = extension_list;
82 while (work) 269 while (work)
83 { 270 {
84 gchar *filter = work->data; 271 gchar *filter = work->data;
85 gint lf = strlen(filter); 272 gint lf = strlen(filter);
86 gint ln = strlen(name); 273 gint ln = strlen(name);
92 } 279 }
93 280
94 return FALSE; 281 return FALSE;
95 } 282 }
96 283
97 static void add_to_filter(gchar *text, gint add) 284 void filter_write_list(FILE *f)
98 { 285 {
99 if (add) filename_filter = g_list_append(filename_filter, g_strdup(text)); 286 GList *work;
100 } 287
101 288 work = filter_list;
102 void rebuild_file_filter() 289 while (work)
103 { 290 {
104 if (filename_filter) 291 FilterEntry *fe = work->data;
105 { 292 work = work->next;
106 g_list_foreach(filename_filter,(GFunc)g_free,NULL); 293
107 g_list_free(filename_filter); 294 fprintf(f, "filter_ext: \"%s%s\" \"%s\" \"%s\"\n", (fe->enabled) ? "" : "#",
108 filename_filter = NULL; 295 fe->key, fe->extensions,
109 } 296 (fe->description) ? fe->description : "");
110 297 }
111 add_to_filter(".jpg", filter_include_jpg); 298 }
112 add_to_filter(".jpeg", filter_include_jpg); 299
113 add_to_filter(".xpm", filter_include_xpm); 300 void filter_parse(const gchar *text)
114 add_to_filter(".tif", filter_include_tif); 301 {
115 add_to_filter(".tiff", filter_include_tif); 302 const gchar *p;
116 add_to_filter(".gif", filter_include_gif); 303 gchar *key;
117 add_to_filter(".png", filter_include_png); 304 gchar *ext;
118 add_to_filter(".ppm", filter_include_ppm); 305 gchar *desc;
119 add_to_filter(".pgm", filter_include_pgm); 306 gint enabled = TRUE;
120 add_to_filter(".pcx", filter_include_pcx); 307
121 add_to_filter(".bmp", filter_include_bmp); 308 if (!text || text[0] != '"') return;
122 309
123 if (custom_filter) 310 key = quoted_value(text);
124 { 311 if (!key) return;
125 gchar *buf = g_strdup(custom_filter); 312
126 gchar *pos_ptr_b; 313 p = text;
127 gchar *pos_ptr_e = buf; 314 p++;
128 while(pos_ptr_e[0] != '\0') 315 while (*p != '"' && *p != '\0') p++;
129 { 316 if (*p != '"')
130 pos_ptr_b = pos_ptr_e; 317 {
131 while (pos_ptr_e[0] != ';' && pos_ptr_e[0] != '\0') pos_ptr_e++; 318 g_free(key);
132 if (pos_ptr_e[0] == ';') 319 return;
133 { 320 }
134 pos_ptr_e[0] = '\0'; 321 p++;
135 pos_ptr_e++; 322 while (*p != '"' && *p != '\0') p++;
136 } 323 if (*p != '"')
137 add_to_filter(pos_ptr_b, TRUE); 324 {
138 } 325 g_free(key);
139 g_free(buf); 326 return;
140 } 327 }
328
329 ext = quoted_value(p);
330
331 p++;
332 while (*p != '"' && *p != '\0') p++;
333 if (*p == '"') p++;
334 while (*p != '"' && *p != '\0') p++;
335
336 if (*p == '"')
337 {
338 desc = quoted_value(p);
339 }
340 else
341 {
342 desc = NULL;
343 }
344
345 if (key && key[0] == '#')
346 {
347 gchar *tmp;
348 tmp = g_strdup(key + 1);
349 g_free(key);
350 key = tmp;
351
352 enabled = FALSE;
353 }
354
355 if (key && strlen(key) > 0 && ext) filter_add(key, desc, ext, enabled);
356
357 g_free(key);
358 g_free(ext);
359 g_free(desc);
360 }
361
362 GList *path_list_filter(GList *list, gint is_dir_list)
363 {
364 GList *work;
365
366 if (!is_dir_list && file_filter_disable && show_dot_files) return list;
367
368 work = list;
369 while (work)
370 {
371 gchar *name = work->data;
372 const gchar *base;
373
374 base = filename_from_path(name);
375
376 if ((!show_dot_files && ishidden(base)) ||
377 (!is_dir_list && !filter_name_exists(base)) ||
378 (is_dir_list && base[0] == '.' && (strcmp(base, GQVIEW_CACHE_LOCAL_THUMB) == 0 ||
379 strcmp(base, GQVIEW_CACHE_LOCAL_METADATA) == 0)) )
380 {
381 GList *link = work;
382 work = work->next;
383 list = g_list_remove_link(list, link);
384 g_free(name);
385 g_list_free(link);
386 }
387 else
388 {
389 work = work->next;
390 }
391 }
392
393 return list;
141 } 394 }
142 395
143 /* 396 /*
144 *----------------------------------------------------------------------------- 397 *-----------------------------------------------------------------------------
145 * load file list (private) 398 * path list recursive
146 *----------------------------------------------------------------------------- 399 *-----------------------------------------------------------------------------
147 */ 400 */
148 401
149 static gint sort_list_cb(void *a, void *b) 402 static gint path_list_sort_cb(gconstpointer a, gconstpointer b)
150 { 403 {
151 return strcmp((gchar *)a, (gchar *)b); 404 return CASE_SORT((gchar *)a, (gchar *)b);
152 } 405 }
153 406
154 static void filelist_read(gchar *path) 407 GList *path_list_sort(GList *list)
408 {
409 return g_list_sort(list, path_list_sort_cb);
410 }
411
412 static void path_list_recursive_append(GList **list, GList *dirs)
413 {
414 GList *work;
415
416 work = dirs;
417 while (work)
418 {
419 const gchar *path = work->data;
420 GList *f = NULL;
421 GList *d = NULL;
422
423 if (path_list(path, &f, &d))
424 {
425 f = path_list_filter(f, FALSE);
426 f = path_list_sort(f);
427 *list = g_list_concat(*list, f);
428
429 d = path_list_filter(d, TRUE);
430 d = path_list_sort(d);
431 path_list_recursive_append(list, d);
432 g_list_free(d);
433 }
434
435 work = work->next;
436 }
437 }
438
439 GList *path_list_recursive(const gchar *path)
440 {
441 GList *list = NULL;
442 GList *d = NULL;
443
444 if (!path_list(path, &list, &d)) return NULL;
445 list = path_list_filter(list, FALSE);
446 list = path_list_sort(list);
447
448 d = path_list_filter(d, TRUE);
449 d = path_list_sort(d);
450 path_list_recursive_append(&list, d);
451 path_list_free(d);
452
453 return list;
454 }
455
456 /*
457 *-----------------------------------------------------------------------------
458 * text conversion utils
459 *-----------------------------------------------------------------------------
460 */
461
462 gchar *text_from_size(gint64 size)
463 {
464 gchar *a, *b;
465 gchar *s, *d;
466 gint l, n, i;
467
468 /* what I would like to use is printf("%'d", size)
469 * BUT: not supported on every libc :(
470 */
471 if (size > G_MAXUINT)
472 {
473 /* the %lld conversion is not valid in all libcs, so use a simple work-around */
474 a = g_strdup_printf("%d%09d", (guint)(size / 1000000000), (guint)(size % 1000000000));
475 }
476 else
477 {
478 a = g_strdup_printf("%d", (guint)size);
479 }
480 l = strlen(a);
481 n = (l - 1)/ 3;
482 if (n < 1) return a;
483
484 b = g_new(gchar, l + n + 1);
485
486 s = a;
487 d = b;
488 i = l - n * 3;
489 while (*s != '\0')
490 {
491 if (i < 1)
492 {
493 i = 3;
494 *d = ',';
495 d++;
496 }
497
498 *d = *s;
499 s++;
500 d++;
501 i--;
502 }
503 *d = '\0';
504
505 g_free(a);
506 return b;
507 }
508
509 gchar *text_from_size_abrev(gint64 size)
510 {
511 if (size < (gint64)1024)
512 {
513 return g_strdup_printf(_("%d bytes"), (gint)size);
514 }
515 if (size < (gint64)1048576)
516 {
517 return g_strdup_printf(_("%.1f K"), (gfloat)size / 1024.0);
518 }
519 if (size < (gint64)1073741824)
520 {
521 return g_strdup_printf(_("%.1f MB"), (gfloat)size / 1048576.0);
522 }
523
524 /* to avoid overflowing the float, do division in two steps */
525 size /= 1048576.0;
526 return g_strdup_printf(_("%.1f GB"), (gfloat)size / 1024.0);
527 }
528
529 /* note: returned string is valid until next call to text_from_time() */
530 const gchar *text_from_time(time_t t)
531 {
532 static gchar *ret = NULL;
533 gchar buf[128];
534 gint buflen;
535 struct tm *btime;
536 GError *error = NULL;
537
538 btime = localtime(&t);
539
540 /* the %x warning about 2 digit years is not an error */
541 buflen = strftime(buf, sizeof(buf), "%x %H:%M", btime);
542 if (buflen < 1) return "";
543
544 g_free(ret);
545 ret = g_locale_to_utf8(buf, buflen, NULL, NULL, &error);
546 if (error)
547 {
548 printf("Error converting locale strftime to UTF-8: %s\n", error->message);
549 g_error_free(error);
550 return "";
551 }
552
553 return ret;
554 }
555
556 /*
557 *-----------------------------------------------------------------------------
558 * file info struct
559 *-----------------------------------------------------------------------------
560 */
561
562 FileData *file_data_new(const gchar *path, struct stat *st)
563 {
564 FileData *fd;
565
566 fd = g_new0(FileData, 1);
567 fd->path = path_to_utf8(path);
568 fd->name = filename_from_path(fd->path);
569 fd->size = st->st_size;
570 fd->date = st->st_mtime;
571 fd->pixbuf = NULL;
572
573 return fd;
574 }
575
576 FileData *file_data_new_simple(const gchar *path)
577 {
578 FileData *fd;
579 struct stat st;
580
581 fd = g_new0(FileData, 1);
582 fd->path = g_strdup(path);
583 fd->name = filename_from_path(fd->path);
584
585 if (stat_utf8(fd->path, &st))
586 {
587 fd->size = st.st_size;
588 fd->date = st.st_mtime;
589 }
590
591 fd->pixbuf = NULL;
592
593 return fd;
594 }
595
596 void file_data_free(FileData *fd)
597 {
598 g_free(fd->path);
599 if (fd->pixbuf) g_object_unref(fd->pixbuf);
600 g_free(fd);
601 }
602
603 /*
604 *-----------------------------------------------------------------------------
605 * load file list
606 *-----------------------------------------------------------------------------
607 */
608
609 static SortType filelist_sort_method = SORT_NONE;
610 static gint filelist_sort_ascend = TRUE;
611
612 static gint sort_file_cb(void *a, void *b)
613 {
614 FileData *fa = a;
615 FileData *fb = b;
616
617 if (!filelist_sort_ascend)
618 {
619 fa = b;
620 fb = a;
621 }
622
623 switch (filelist_sort_method)
624 {
625 case SORT_SIZE:
626 if (fa->size < fb->size) return -1;
627 if (fa->size > fb->size) return 1;
628 return 0;
629 break;
630 case SORT_TIME:
631 if (fa->date < fb->date) return -1;
632 if (fa->date > fb->date) return 1;
633 return 0;
634 break;
635 #ifdef HAVE_STRVERSCMP
636 case SORT_NUMBER:
637 return strverscmp(fa->name, fb->name);
638 break;
639 #endif
640 case SORT_NAME:
641 default:
642 return CASE_SORT(fa->name, fb->name);
643 break;
644 }
645 }
646
647 GList *filelist_sort(GList *list, SortType method, gint ascend)
648 {
649 filelist_sort_method = method;
650 filelist_sort_ascend = ascend;
651 return g_list_sort(list, (GCompareFunc) sort_file_cb);
652 }
653
654 GList *filelist_insert_sort(GList *list, FileData *fd, SortType method, gint ascend)
655 {
656 filelist_sort_method = method;
657 filelist_sort_ascend = ascend;
658 return g_list_insert_sorted(list, fd, (GCompareFunc) sort_file_cb);
659 }
660
661 gint filelist_read(const gchar *path, GList **files, GList **dirs)
155 { 662 {
156 DIR *dp; 663 DIR *dp;
157 struct dirent *dir; 664 struct dirent *dir;
158 struct stat ent_sbuf; 665 struct stat ent_sbuf;
159 666 gchar *pathl;
160 if((dp = opendir(path))==NULL) 667 GList *dlist;
161 { 668 GList *flist;
162 /* dir not found */ 669
163 return; 670 dlist = NULL;
164 } 671 flist = NULL;
165 672
166 g_list_foreach(dir_list,(GFunc)g_free,NULL); 673 pathl = path_from_utf8(path);
167 g_list_free(dir_list); 674 if (!pathl || (dp = opendir(pathl)) == NULL)
168 dir_list = NULL; 675 {
169 676 g_free(pathl);
170 g_list_foreach(file_list,(GFunc)g_free,NULL); 677 if (files) *files = NULL;
171 g_list_free(file_list); 678 if (dirs) *dirs = NULL;
172 file_list = NULL; 679 return FALSE;
680 }
681
682 /* root dir fix */
683 if (pathl[0] == '/' && pathl[1] == '\0')
684 {
685 g_free(pathl);
686 pathl = g_strdup("");
687 }
173 688
174 while ((dir = readdir(dp)) != NULL) 689 while ((dir = readdir(dp)) != NULL)
175 { 690 {
176 /* skips removed files */ 691 gchar *name = dir->d_name;
177 if (dir->d_ino > 0) 692 if (show_dot_files || !ishidden(name))
178 { 693 {
179 gchar *name = dir->d_name; 694 gchar *filepath = g_strconcat(pathl, "/", name, NULL);
180 if (show_dot_files || !file_is_hidden(name)) 695 if (stat(filepath, &ent_sbuf) >= 0)
181 { 696 {
182 gchar *filepath = g_strconcat(path, "/", name, NULL); 697 if (S_ISDIR(ent_sbuf.st_mode))
183 if (stat(filepath,&ent_sbuf) >= 0 && S_ISDIR(ent_sbuf.st_mode))
184 { 698 {
185 dir_list = g_list_prepend(dir_list, g_strdup(name)); 699 /* we ignore the .thumbnails dir for cleanliness */
700 if ((dirs) &&
701 !(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) &&
702 strcmp(name, GQVIEW_CACHE_LOCAL_THUMB) != 0 &&
703 strcmp(name, GQVIEW_CACHE_LOCAL_METADATA) != 0)
704 {
705 dlist = g_list_prepend(dlist, file_data_new(filepath, &ent_sbuf));
706 }
186 } 707 }
187 else 708 else
188 { 709 {
189 if (file_is_in_filter(name)) 710 if ((files) && filter_name_exists(name))
190 file_list = g_list_prepend(file_list, g_strdup(name));
191 }
192 g_free(filepath);
193 }
194 }
195 }
196
197 closedir(dp);
198
199 dir_list = g_list_sort(dir_list, (GCompareFunc) sort_list_cb);
200 file_list = g_list_sort(file_list, (GCompareFunc) sort_list_cb);
201 }
202
203 /*
204 *-----------------------------------------------------------------------------
205 * file list utilities to retrieve information (public)
206 *-----------------------------------------------------------------------------
207 */
208
209 gint file_count()
210 {
211 return g_list_length(file_list);
212 }
213
214 gint file_selection_count()
215 {
216 gint count = 0;
217 GList *work = GTK_CLIST(file_clist)->selection;
218 while(work)
219 {
220 count++;
221 if (debug) printf("s = %d\n", GPOINTER_TO_INT(work->data));
222 work = work->next;
223 }
224
225 if (debug) printf("files selected = %d\n", count);
226
227 return count;
228 }
229
230 gint find_file_in_list(gchar *path)
231 {
232 GList *work = file_list;
233 gchar *buf;
234 gchar *name;
235 gint count = -1;
236
237 if (!path) return -1;
238
239 buf = remove_level_from_path(path);
240 if (strcmp(buf, current_path) != 0)
241 {
242 g_free(buf);
243 return -1;
244 }
245 g_free(buf);
246
247 name = filename_from_path(path);
248 while(work)
249 {
250 count++;
251 if (strcmp(name, work->data) == 0) return count;
252 work = work->next;
253 }
254
255 return -1;
256 }
257
258 gchar *file_get_path(gint row)
259 {
260 gchar *path = NULL;
261 gchar *name = gtk_clist_get_row_data(GTK_CLIST(file_clist), row);
262
263 if (name) path = g_strconcat(current_path, "/", name, NULL);
264
265 return path;
266 }
267
268 gint file_is_selected(gint row)
269 {
270 GList *work = GTK_CLIST(file_clist)->selection;
271
272 while(work)
273 {
274 if (GPOINTER_TO_INT(work->data) == row) return TRUE;
275 work = work->next;
276 }
277
278 return FALSE;
279 }
280
281 /*
282 *-----------------------------------------------------------------------------
283 * utilities to retrieve list of selected files (public)
284 *-----------------------------------------------------------------------------
285 */
286
287 GList *file_get_selected_list()
288 {
289 GList *list = NULL;
290 GList *work = GTK_CLIST(file_clist)->selection;
291
292 while(work)
293 {
294 gchar *name = gtk_clist_get_row_data(GTK_CLIST(file_clist),
295 GPOINTER_TO_INT(work->data));
296 list = g_list_prepend(list, g_strconcat(current_path, "/", name, NULL));
297 work = work->next;
298 }
299
300 list = g_list_reverse(list);
301
302 return list;
303 }
304
305 void free_selected_list(GList *list)
306 {
307 g_list_foreach(list, (GFunc)g_free, NULL);
308 g_list_free(list);
309 }
310
311 gint file_clicked_is_selected()
312 {
313 return file_is_selected(filelist_click_row);
314 }
315
316 gchar *file_clicked_get_path()
317 {
318 return file_get_path(filelist_click_row);
319 }
320
321 /*
322 *-----------------------------------------------------------------------------
323 * image change routines
324 *-----------------------------------------------------------------------------
325 */
326
327 void file_image_change_to(gint row)
328 {
329 gtk_clist_unselect_all(GTK_CLIST(file_clist));
330 gtk_clist_select_row(GTK_CLIST(file_clist), row, -1);
331 if (gtk_clist_row_is_visible(GTK_CLIST(file_clist), row) != GTK_VISIBILITY_FULL)
332 {
333 gtk_clist_moveto(GTK_CLIST(file_clist), row, -1, 0.5, 0.0);
334 }
335 }
336
337 void file_next_image()
338 {
339 gint current;
340 gint total;
341
342 if (slideshow_is_running())
343 {
344 slideshow_next();
345 return;
346 }
347
348 current = find_file_in_list(image_get_path());
349 total = file_count();
350
351 if (current >= 0)
352 {
353 if (current < total - 1)
354 {
355 file_image_change_to(current + 1);
356 }
357 }
358 else
359 {
360 file_image_change_to(0);
361 }
362 }
363
364 void file_prev_image()
365 {
366 gint current;
367
368 if (slideshow_is_running())
369 {
370 slideshow_prev();
371 return;
372 }
373
374 current = find_file_in_list(image_get_path());
375
376 if (current >= 0)
377 {
378 if (current > 0)
379 {
380 file_image_change_to(current - 1);
381 }
382 }
383 else
384 {
385 file_image_change_to(file_count() - 1);
386 }
387 }
388
389 void file_first_image()
390 {
391 gint current = find_file_in_list(image_get_path());
392 if (current != 0 && file_count() > 0)
393 {
394 file_image_change_to(0);
395 }
396 }
397
398 void file_last_image()
399 {
400 gint current = find_file_in_list(image_get_path());
401 gint count = file_count();
402 if (current != count - 1 && count > 0)
403 {
404 file_image_change_to(count - 1);
405 }
406 }
407
408 /*
409 *-----------------------------------------------------------------------------
410 * file delete/rename update routines
411 *-----------------------------------------------------------------------------
412 */
413
414 static gint file_find_closest_unaccounted(gint row, gint count, GList *ignore_list)
415 {
416 GList *list = NULL;
417 GList *work;
418 gint rev = row - 1;
419 row ++;
420
421 work = ignore_list;
422 while(work)
423 {
424 gint f = find_file_in_list(work->data);
425 if (f >= 0) list = g_list_append(list, GINT_TO_POINTER(f));
426 work = work->next;
427 }
428
429 while(list)
430 {
431 gint c = TRUE;
432 work = list;
433 while(work && c)
434 {
435 gpointer p = work->data;
436 work = work->next;
437 if (row == GPOINTER_TO_INT(p))
438 {
439 row++;
440 c = FALSE;
441 }
442 if (rev == GPOINTER_TO_INT(p))
443 {
444 rev--;
445 c = FALSE;
446 }
447 if (!c) list = g_list_remove(list, p);
448 }
449 if (c && list)
450 {
451 g_list_free(list);
452 list = NULL;
453 }
454 }
455 if (row > count - 1)
456 {
457 if (rev < 0)
458 return -1;
459 else
460 return rev;
461 }
462 else
463 {
464 return row;
465 }
466 }
467
468 void file_is_gone(gchar *path, GList *ignore_list)
469 {
470 GList *list;
471 gchar *name;
472 gint row;
473 gint new_row = -1;
474 row = find_file_in_list(path);
475 if (row < 0) return;
476
477 if (file_is_selected(row) /* && file_selection_count() == 1 */)
478 {
479 gint n = file_count();
480 if (ignore_list)
481 {
482 new_row = file_find_closest_unaccounted(row, n, ignore_list);
483 if (debug) printf("row = %d, closest is %d\n", row, new_row);
484 }
485 else
486 {
487 if (row + 1 < n)
488 {
489 new_row = row + 1;
490 }
491 else if (row > 0)
492 {
493 new_row = row - 1;
494 }
495 }
496 gtk_clist_unselect_all(GTK_CLIST(file_clist));
497 if (new_row >= 0)
498 {
499 gtk_clist_select_row(GTK_CLIST(file_clist), new_row, -1);
500 file_image_change_to(new_row);
501 }
502 else
503 {
504 image_change_to(NULL);
505 }
506 }
507
508 gtk_clist_remove(GTK_CLIST(file_clist), row);
509 list = g_list_nth(file_list, row);
510 name = list->data;
511 file_list = g_list_remove(file_list, name);
512 g_free(name);
513 update_status_label(NULL);
514 }
515
516 void file_is_renamed(gchar *source, gchar *dest)
517 {
518 gint row;
519 gchar *source_base;
520 gchar *dest_base;
521
522 if (image_get_path() && !strcmp(source, image_get_path()))
523 {
524 image_set_path(dest);
525 }
526
527 row = find_file_in_list(source);
528 if (row < 0) return;
529
530 source_base = remove_level_from_path(source);
531 dest_base = remove_level_from_path(dest);
532
533 if (strcmp(source_base, dest_base) == 0)
534 {
535 gchar *name;
536 gint n;
537 GList *work = g_list_nth(file_list, row);
538 name = work->data;
539 file_list = g_list_remove(file_list, name);
540 g_free(name);
541 name = g_strdup(filename_from_path(dest));
542 file_list = g_list_insert_sorted(file_list, name, (GCompareFunc) sort_list_cb);
543 n = g_list_index(file_list, name);
544
545 if (gtk_clist_get_cell_type(GTK_CLIST(file_clist), row, 0) != GTK_CELL_PIXTEXT)
546 {
547 gtk_clist_set_text (GTK_CLIST(file_clist), row, 0, name);
548 }
549 else
550 {
551 guint8 spacing = 0;
552 GdkPixmap *pixmap = NULL;
553 GdkBitmap *mask = NULL;
554 gtk_clist_get_pixtext(GTK_CLIST(file_clist), row, 0,
555 NULL, &spacing, &pixmap, &mask);
556 gtk_clist_set_pixtext(GTK_CLIST(file_clist), row, 0,
557 name, spacing, pixmap, mask);
558 }
559
560 gtk_clist_set_row_data(GTK_CLIST(file_clist), row, name);
561 gtk_clist_row_move(GTK_CLIST(file_clist), row, n);
562 }
563 else
564 {
565 GList *work = g_list_nth(file_list, row);
566 gchar *name = work->data;
567 file_list = g_list_remove(file_list, name);
568 gtk_clist_remove(GTK_CLIST(file_clist), row);
569 g_free(name);
570 update_status_label(NULL);
571 }
572
573 g_free(source_base);
574 g_free(dest_base);
575
576 }
577
578 /*
579 *-----------------------------------------------------------------------------
580 * directory list callbacks
581 *-----------------------------------------------------------------------------
582 */
583
584 void dir_select_cb(GtkWidget *widget, gint row, gint col,
585 GdkEvent *event, gpointer data)
586 {
587 gchar *name;
588 gchar *new_path;
589 name = gtk_clist_get_row_data (GTK_CLIST(dir_clist), row);
590 if (strcmp(name, ".") == 0)
591 {
592 new_path = g_strdup(current_path);
593 }
594 else if (strcmp(name, "..") == 0)
595 {
596 new_path = remove_level_from_path(current_path);
597 }
598 else
599 {
600 if (strcmp(current_path, "/") == 0)
601 new_path = g_strconcat(current_path, name, NULL);
602 else
603 new_path = g_strconcat(current_path, "/", name, NULL);
604 }
605 filelist_change_to(new_path);
606 g_free(new_path);
607 }
608
609 void dir_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
610 {
611 gint row = -1;
612 gint col = -1;
613
614 gtk_clist_get_selection_info (GTK_CLIST (widget), bevent->x, bevent->y, &row, &col);
615
616 if (bevent->button == 2)
617 {
618 gtk_object_set_user_data(GTK_OBJECT(dir_clist), GINT_TO_POINTER(row));
619 }
620 }
621
622 /*
623 *-----------------------------------------------------------------------------
624 * file list callbacks
625 *-----------------------------------------------------------------------------
626 */
627
628 void file_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
629 {
630 gint row = -1;
631 gint col = -1;
632
633 gtk_clist_get_selection_info (GTK_CLIST (widget), bevent->x, bevent->y, &row, &col);
634 if (row == -1 || col == -1)
635 {
636 filelist_click_row = -1;
637 return;
638 }
639
640 filelist_click_row = row;
641
642 if (bevent->button == 3)
643 {
644 file_clist_highlight_set();
645 gtk_menu_popup (GTK_MENU(menu_file_popup), NULL, NULL, NULL, NULL,
646 bevent->button, bevent->time);
647 }
648 }
649
650 void file_select_cb(GtkWidget *widget, gint row, gint col,
651 GdkEvent *event, gpointer data)
652 {
653 gchar *name;
654 gchar *path;
655
656 if (file_selection_count() != 1)
657 {
658 update_status_label(NULL);
659 return;
660 }
661
662 name = gtk_clist_get_row_data(GTK_CLIST(file_clist), row);
663 path = g_strconcat(current_path, "/", name, NULL);
664 image_change_to(path);
665 update_status_label(NULL);
666 g_free(path);
667 }
668
669 void file_unselect_cb(GtkWidget *widget, gint row, gint col,
670 GdkEvent *event, gpointer data)
671 {
672 #if 0
673 gchar *name;
674 gchar *path;
675
676 name = gtk_clist_get_row_data(GTK_CLIST(file_clist), row);
677 path = g_strconcat(current_path, "/", name, NULL);
678
679 if (strcmp(path, image_get_path()) == 0)
680 {
681 if (file_selection_count() > 0 && !file_is_selected(find_file_in_list(image_get_path())) )
682 {
683 gint new_row = GPOINTER_TO_INT(GTK_CLIST(file_clist)->selection->data);
684 gchar *new_name = gtk_clist_get_row_data(GTK_CLIST(file_clist), new_row);
685 gchar *new_path = g_strconcat(current_path, "/", new_name, NULL);
686 image_change_to(new_path);
687 g_free(new_path);
688 }
689 }
690 g_free(path);
691 #endif
692 update_status_label(NULL);
693 }
694
695 /*
696 *-----------------------------------------------------------------------------
697 * file list highlight utils
698 *-----------------------------------------------------------------------------
699 */
700
701 void file_clist_highlight_set()
702 {
703 if (file_clicked_is_selected()) return;
704
705 gtk_clist_set_background(GTK_CLIST(file_clist), filelist_click_row,
706 &GTK_WIDGET (file_clist)->style->bg[GTK_STATE_PRELIGHT]);
707 gtk_clist_set_foreground(GTK_CLIST(file_clist), filelist_click_row,
708 &GTK_WIDGET (file_clist)->style->fg[GTK_STATE_PRELIGHT]);
709 }
710
711 void file_clist_highlight_unset()
712 {
713 if (file_clicked_is_selected()) return;
714
715 gtk_clist_set_background(GTK_CLIST(file_clist), filelist_click_row, NULL);
716 gtk_clist_set_foreground(GTK_CLIST(file_clist), filelist_click_row, NULL);
717 }
718
719 /*
720 *-----------------------------------------------------------------------------
721 * path entry and history menu
722 *-----------------------------------------------------------------------------
723 */
724
725 void path_entry_tab_cb(gchar *newdir, gpointer data)
726 {
727 gchar *new_path;
728 gchar *buf;
729 gint found = FALSE;
730
731 new_path = g_strdup(newdir);
732 parse_out_relatives(new_path);
733 buf = remove_level_from_path(new_path);
734
735 if (buf && current_path && strcmp(buf, current_path) == 0)
736 {
737 GList *work;
738 gchar *part;
739
740 part = filename_from_path(new_path);
741 work = file_list;
742
743 while(part && work)
744 {
745 gchar *name = work->data;
746 work = work->next;
747
748 if (strncmp(part, name, strlen(part)) == 0)
749 {
750 gint row = g_list_index(file_list, name);
751 if (!gtk_clist_row_is_visible(GTK_CLIST(file_clist), row) != GTK_VISIBILITY_FULL)
752 {
753 gtk_clist_moveto(GTK_CLIST(file_clist), row, -1, 0.5, 0.0);
754 }
755 found = TRUE;
756 break;
757 }
758 }
759 }
760
761 if (!found && new_path && current_path &&
762 strcmp(new_path, current_path) != 0 && isdir(new_path))
763 {
764 filelist_change_to(new_path);
765 /* we are doing tab completion, add '/' back */
766 gtk_entry_append_text(GTK_ENTRY(path_entry), "/");
767 }
768
769 g_free(buf);
770 g_free(new_path);
771 }
772
773 void path_entry_cb(gchar *newdir, gpointer data)
774 {
775 gchar *new_path = g_strdup(newdir);
776 parse_out_relatives(new_path);
777 if (isdir(new_path))
778 filelist_change_to(new_path);
779 else if (isfile(new_path))
780 {
781 gchar *path = remove_level_from_path(new_path);
782 filelist_change_to(path);
783 g_free(path);
784 image_change_to(new_path);
785 }
786 g_free(new_path);
787 }
788
789 static void history_menu_select_cb(GtkWidget *widget, gpointer data)
790 {
791 gchar *new_path = data;
792 filelist_change_to(new_path);
793 }
794
795 static gchar *truncate_hist_text(gchar *t, gint l)
796 {
797 gchar *tp;
798 gchar *tbuf;
799 if (l >= strlen(t)) return g_strdup(t);
800 tp = t + strlen(t) - l;
801 while (tp[0] != '/' && tp < t + strlen(t)) tp++;
802 /* this checks to see if directory name is longer than l, if so
803 * reset the length of name to l, it's better to have a partial
804 * name than no name at all.
805 */
806 if (tp >= t + strlen(t)) tp = t + strlen(t) - l;
807 tbuf = g_strconcat("/...", tp, NULL);
808 return tbuf;
809 }
810
811 static void filelist_set_history(gchar *path)
812 {
813 static GList *history_list = NULL;
814 gchar *buf;
815 gchar *buf_ptr;
816 GtkWidget *menu;
817 GtkWidget *item;
818
819 if (!path) return;
820
821 gtk_entry_set_text(GTK_ENTRY(path_entry), current_path);
822
823 if (history_list)
824 {
825 g_list_foreach(history_list, (GFunc)g_free, NULL);
826 g_list_free(history_list);
827 history_list = NULL;
828 }
829
830 menu = gtk_menu_new();
831
832 buf = g_strdup(path);
833 buf_ptr = buf + strlen(buf) - 1 ;
834 while (buf_ptr > buf)
835 {
836 gchar *full_path;
837 gchar *truncated;
838 truncated = truncate_hist_text(buf, 32);
839
840 full_path = g_strdup(buf);
841 history_list = g_list_append(history_list, full_path);
842
843 item = gtk_menu_item_new_with_label (truncated);
844 gtk_signal_connect (GTK_OBJECT (item), "activate",
845 (GtkSignalFunc) history_menu_select_cb, full_path);
846
847 gtk_menu_append (GTK_MENU (menu), item);
848 gtk_widget_show (item);
849
850 g_free(truncated);
851
852 while (buf_ptr[0] != '/' && buf_ptr > buf) buf_ptr--;
853 buf_ptr[0] = '\0';
854 }
855 g_free(buf);
856
857 item = gtk_menu_item_new_with_label ("/");
858
859 gtk_signal_connect (GTK_OBJECT (item), "activate",
860 (GtkSignalFunc) history_menu_select_cb, "/");
861
862 gtk_menu_append (GTK_MENU (menu), item);
863 gtk_widget_show (item);
864
865 gtk_option_menu_set_menu(GTK_OPTION_MENU(history_menu), menu);
866 }
867
868 /*
869 *-----------------------------------------------------------------------------
870 * list update routines (public)
871 *-----------------------------------------------------------------------------
872 */
873
874 static gint thumbs_running = 0;
875
876 void interrupt_thumbs()
877 {
878 if (thumbs_running > 0) thumbs_running ++;
879 }
880
881 void filelist_populate_clist()
882 {
883 GList *work;
884 gint width;
885 gint tmp_width;
886 gint row;
887 gchar *image_name = NULL;
888 gchar *buf;
889
890 gint row_p = 0;
891 gchar *text;
892 guint8 spacing;
893 GdkPixmap *nopixmap;
894 GdkBitmap *nomask;
895
896 interrupt_thumbs();
897
898 filelist_set_history(current_path);
899
900 gtk_clist_freeze (GTK_CLIST (dir_clist));
901 gtk_clist_clear (GTK_CLIST (dir_clist));
902
903 width = 0;
904 work = dir_list;
905 while(work)
906 {
907 gchar *buf[2];
908 buf[0] = work->data;
909 buf[1] = NULL;
910 row = gtk_clist_append(GTK_CLIST(dir_clist), buf);
911 gtk_clist_set_row_data (GTK_CLIST(dir_clist), row, work->data);
912 tmp_width = gdk_string_width(dir_clist->style->font, buf[0]);
913 if (tmp_width > width) width = tmp_width;
914 work = work->next;
915 }
916
917 gtk_clist_set_column_width(GTK_CLIST(dir_clist), 0, width);
918 gtk_clist_thaw(GTK_CLIST (dir_clist));
919
920 buf = remove_level_from_path(image_get_path());
921 if (buf && strcmp(buf, current_path) == 0)
922 {
923 image_name = image_get_name();
924 }
925 g_free(buf);
926
927 gtk_clist_freeze (GTK_CLIST (file_clist));
928
929 if (!thumbnails_enabled)
930 {
931 gtk_clist_set_row_height (GTK_CLIST(file_clist),
932 GTK_WIDGET(file_clist)->style->font->ascent +
933 GTK_WIDGET(file_clist)->style->font->descent + 1);
934 }
935 else
936 {
937 gtk_clist_set_row_height (GTK_CLIST(file_clist), thumb_max_height + 2);
938 maintain_thumbnail_dir(current_path, FALSE);
939 }
940
941 width = 0;
942 work = file_list;
943
944 while(work)
945 {
946 gint has_pixmap;
947 gint match;
948 gchar *name = work->data;
949 gint done = FALSE;
950
951 while (!done)
952 {
953 if (GTK_CLIST(file_clist)->rows > row_p)
954 {
955 if (gtk_clist_get_cell_type(GTK_CLIST(file_clist),row_p, 0) == GTK_CELL_PIXTEXT)
956 {
957 gtk_clist_get_pixtext(GTK_CLIST(file_clist), row_p, 0, &text, &spacing, &nopixmap, &nomask);
958 has_pixmap = TRUE;
959 }
960 else
961 {
962 gtk_clist_get_text(GTK_CLIST(file_clist), row_p, 0, &text);
963 has_pixmap = FALSE;
964 }
965 match = strcmp(name, text);
966 }
967 else
968 {
969 match = -1;
970 }
971
972 if (match < 0)
973 {
974 gchar *buf[2];
975 buf[0] = name;
976 buf[1] = NULL;
977 row = gtk_clist_insert(GTK_CLIST(file_clist), row_p, buf);
978 gtk_clist_set_row_data (GTK_CLIST(file_clist), row, name);
979 if (thumbnails_enabled)
980 gtk_clist_set_shift(GTK_CLIST(file_clist), row, 0, 0, 5 + thumb_max_width);
981 done = TRUE;
982 if (image_name && strcmp(name, image_name) == 0)
983 gtk_clist_select_row(GTK_CLIST(file_clist), row, 0);
984 }
985 else if (match > 0)
986 {
987 gtk_clist_remove(GTK_CLIST(file_clist), row_p);
988 }
989 else
990 {
991 if (thumbnails_enabled && !has_pixmap)
992 gtk_clist_set_shift(GTK_CLIST(file_clist), row_p, 0, 0, 5 + thumb_max_width);
993 if (!thumbnails_enabled/* && has_pixmap*/)
994 {
995 gtk_clist_set_text(GTK_CLIST(file_clist), row_p, 0, name);
996 gtk_clist_set_shift(GTK_CLIST(file_clist), row_p, 0, 0, 0);
997 }
998 gtk_clist_set_row_data (GTK_CLIST(file_clist), row_p, name);
999 done = TRUE;
1000 }
1001 }
1002 row_p++;
1003
1004 if (thumbnails_enabled)
1005 tmp_width = gdk_string_width(file_clist->style->font, name) + thumb_max_width + 5;
1006 else
1007 tmp_width = gdk_string_width(file_clist->style->font, name);
1008 if (tmp_width > width) width = tmp_width;
1009 work = work->next;
1010 }
1011
1012 while (GTK_CLIST(file_clist)->rows > row_p)
1013 gtk_clist_remove(GTK_CLIST(file_clist), row_p);
1014
1015 gtk_clist_set_column_width(GTK_CLIST(file_clist), 0, width);
1016 gtk_clist_thaw(GTK_CLIST (file_clist));
1017
1018 if (thumbnails_enabled)
1019 {
1020 GList *done_list = NULL;
1021 gint past_run;
1022 gint finished = FALSE;
1023 gint j;
1024 gint count = 0;
1025 update_status_label(_("Loading thumbs..."));
1026
1027 for (j = 0; j < GTK_CLIST(file_clist)->rows; j++)
1028 {
1029 done_list = g_list_prepend(done_list, GINT_TO_POINTER(FALSE));
1030 }
1031
1032 /* load thumbs */
1033
1034 while (!finished && done_list)
1035 {
1036 gint p = -1;
1037 gint r = -1;
1038 gint c = -1;
1039 gtk_clist_get_selection_info (GTK_CLIST(file_clist), 1, 1, &r, &c);
1040 if (r != -1)
1041 {
1042 work = g_list_nth(done_list, r);
1043 while (work)
1044 {
1045 if (gtk_clist_row_is_visible(GTK_CLIST(file_clist), r))
1046 { 711 {
1047 if (!GPOINTER_TO_INT(work->data)) 712 flist = g_list_prepend(flist, file_data_new(filepath, &ent_sbuf));
1048 {
1049 work->data = GINT_TO_POINTER(TRUE);
1050 p = r;
1051 work = NULL;
1052 }
1053 else
1054 {
1055 r++;
1056 work = work->next;
1057 }
1058 }
1059 else
1060 {
1061 work = NULL;
1062 } 713 }
1063 } 714 }
1064 } 715 }
1065 if (p == -1) 716 g_free(filepath);
1066 { 717 }
1067 work = done_list; 718 }
1068 r = 0; 719
1069 while(work && p == -1) 720 closedir(dp);
1070 { 721
1071 if (!GPOINTER_TO_INT(work->data)) 722 g_free(pathl);
1072 { 723
1073 p = r; 724 if (dirs) *dirs = dlist;
1074 work->data = GINT_TO_POINTER(TRUE); 725 if (files) *files = flist;
1075 } 726
1076 else 727 return TRUE;
1077 { 728 }
1078 r++; 729
1079 work = work->next; 730 void filelist_free(GList *list)
1080 if (!work) finished = TRUE; 731 {
1081 } 732 GList *work;
1082 } 733
1083 } 734 work = list;
1084 735 while (work)
1085 count++; 736 {
1086 737 file_data_free((FileData *)work->data);
1087 if (!finished && gtk_clist_get_cell_type(GTK_CLIST(file_clist), p, 0) != GTK_CELL_PIXTEXT) 738 work = work->next;
1088 { 739 }
1089 GdkPixmap *pixmap = NULL; 740
1090 GdkBitmap *mask = NULL; 741 g_list_free(list);
1091 gchar *name; 742 }
1092 gchar *path; 743
1093 744
1094 thumbs_running ++;
1095 past_run = thumbs_running;
1096 while(gtk_events_pending()) gtk_main_iteration();
1097 if (thumbs_running > past_run)
1098 {
1099 thumbs_running -= 2;
1100 update_progressbar(0.0);
1101 update_status_label(NULL);
1102 g_list_free(done_list);
1103 return;
1104 }
1105 thumbs_running --;
1106
1107 name = gtk_clist_get_row_data(GTK_CLIST(file_clist), p);
1108 path = g_strconcat (current_path, "/", name, NULL);
1109 spacing = create_thumbnail(path, &pixmap, &mask);
1110 g_free(path);
1111 gtk_clist_set_pixtext (GTK_CLIST(file_clist), p, 0, name, spacing + 5, pixmap, mask);
1112 gtk_clist_set_shift(GTK_CLIST(file_clist), p, 0, 0, 0);
1113
1114 update_progressbar((gfloat)(count) / GTK_CLIST(file_clist)->rows);
1115 }
1116 }
1117 update_progressbar(0.0);
1118 g_list_free(done_list);
1119 }
1120
1121 update_status_label(NULL);
1122 }
1123
1124 void filelist_refresh()
1125 {
1126 filelist_read(current_path);
1127 filelist_populate_clist();
1128 filelist_click_row = -1;
1129 }
1130
1131 void filelist_change_to(gchar *path)
1132 {
1133 if (!isdir(path)) return;
1134
1135 g_free(current_path);
1136 current_path = g_strdup(path);
1137
1138 filelist_refresh();
1139 }