2.5 filebrowser WIP commit
[blender-staging.git] / source / blender / editors / space_file / filelist.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2007 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30
31 /* global includes */
32
33 #include <stdlib.h>
34 #include <math.h>
35 #include <string.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #ifndef WIN32
42 #include <unistd.h>
43 #else
44 #include <io.h>
45 #include <direct.h>
46 #endif   
47 #include "MEM_guardedalloc.h"
48
49 #include "BLI_blenlib.h"
50 #include "BLI_linklist.h"
51 #include "BLI_storage_types.h"
52 #include "BLI_threads.h"
53
54 #ifdef WIN32
55 #include "BLI_winstuff.h"
56 #endif
57
58 #include "BKE_utildefines.h"
59 #include "BKE_global.h"
60 #include "BKE_library.h"
61 #include "BKE_global.h"
62 #include "BKE_main.h"
63 #include "BLO_readfile.h"
64
65 #include "DNA_space_types.h"
66 #include "DNA_ipo_types.h"
67 #include "DNA_ID.h"
68 #include "DNA_object_types.h"
69 #include "DNA_listBase.h"
70 #include "DNA_lamp_types.h"
71 #include "DNA_material_types.h"
72 #include "DNA_texture_types.h"
73 #include "DNA_world_types.h"
74 #include "DNA_scene_types.h"
75 #include "DNA_userdef_types.h"
76
77 #include "ED_datafiles.h"
78
79 #include "IMB_imbuf.h"
80 #include "IMB_imbuf_types.h"
81 #include "IMB_thumbs.h"
82
83 #include "PIL_time.h"
84
85 #include "UI_text.h"
86
87 #include "filelist.h"
88
89 /* Elubie: VERY, really very ugly and evil! Remove asap!!! */
90 /* for state of file */
91 #define ACTIVE                          2
92
93 /* max length of library group name within filesel */
94 #define GROUP_MAX 32
95
96 static void *exec_loadimages(void *list_v);
97
98 struct FileList;
99
100 typedef struct FileImage {
101         struct FileImage *next, *prev;
102         int index;
103         short lock;
104         short done;
105         struct FileList* filelist;
106 } FileImage;
107
108 typedef struct FileList
109 {
110         struct direntry *filelist;
111         int *fidx;
112
113         int numfiles;
114         int numfiltered;
115         char dir[FILE_MAX];
116         short type;
117         int has_func;
118         short prv_w;
119         short prv_h;
120         short hide_dot;
121         unsigned int filter;
122         short changed;
123         int maxnamelen;
124         ListBase loadimages;
125         ListBase threads;
126 } FileList;
127
128 #define SPECIAL_IMG_SIZE 48
129 #define SPECIAL_IMG_ROWS 4
130 #define SPECIAL_IMG_COLS 4
131
132 #define SPECIAL_IMG_FOLDER 0
133 #define SPECIAL_IMG_PARENT 1
134 #define SPECIAL_IMG_REFRESH 2
135 #define SPECIAL_IMG_BLENDFILE 3
136 #define SPECIAL_IMG_SOUNDFILE 4
137 #define SPECIAL_IMG_MOVIEFILE 5
138 #define SPECIAL_IMG_PYTHONFILE 6
139 #define SPECIAL_IMG_TEXTFILE 7
140 #define SPECIAL_IMG_FONTFILE 8
141 #define SPECIAL_IMG_UNKNOWNFILE 9
142 #define SPECIAL_IMG_LOADING 10
143 #define SPECIAL_IMG_MAX SPECIAL_IMG_LOADING + 1
144
145 static ImBuf* gSpecialFileImages[SPECIAL_IMG_MAX];
146
147
148 /* ******************* SORT ******************* */
149
150 static int compare_name(const void *a1, const void *a2)
151 {
152         const struct direntry *entry1=a1, *entry2=a2;
153
154         /* type is is equal to stat.st_mode */
155
156         if (S_ISDIR(entry1->type)){
157                 if (S_ISDIR(entry2->type)==0) return (-1);
158         } else{
159                 if (S_ISDIR(entry2->type)) return (1);
160         }
161         if (S_ISREG(entry1->type)){
162                 if (S_ISREG(entry2->type)==0) return (-1);
163         } else{
164                 if (S_ISREG(entry2->type)) return (1);
165         }
166         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
167         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
168         
169         /* make sure "." and ".." are always first */
170         if( strcmp(entry1->relname, ".")==0 ) return (-1);
171         if( strcmp(entry2->relname, ".")==0 ) return (1);
172         if( strcmp(entry1->relname, "..")==0 ) return (-1);
173         if( strcmp(entry2->relname, "..")==0 ) return (1);
174         
175         return (BLI_strcasecmp(entry1->relname,entry2->relname));
176 }
177
178 static int compare_date(const void *a1, const void *a2) 
179 {
180         const struct direntry *entry1=a1, *entry2=a2;
181         
182         /* type is equal to stat.st_mode */
183
184         if (S_ISDIR(entry1->type)){
185                 if (S_ISDIR(entry2->type)==0) return (-1);
186         } else{
187                 if (S_ISDIR(entry2->type)) return (1);
188         }
189         if (S_ISREG(entry1->type)){
190                 if (S_ISREG(entry2->type)==0) return (-1);
191         } else{
192                 if (S_ISREG(entry2->type)) return (1);
193         }
194         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
195         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
196
197         /* make sure "." and ".." are always first */
198         if( strcmp(entry1->relname, ".")==0 ) return (-1);
199         if( strcmp(entry2->relname, ".")==0 ) return (1);
200         if( strcmp(entry1->relname, "..")==0 ) return (-1);
201         if( strcmp(entry2->relname, "..")==0 ) return (1);
202         
203         if ( entry1->s.st_mtime < entry2->s.st_mtime) return 1;
204         if ( entry1->s.st_mtime > entry2->s.st_mtime) return -1;
205         
206         else return BLI_strcasecmp(entry1->relname,entry2->relname);
207 }
208
209 static int compare_size(const void *a1, const void *a2) 
210 {
211         const struct direntry *entry1=a1, *entry2=a2;
212
213         /* type is equal to stat.st_mode */
214
215         if (S_ISDIR(entry1->type)){
216                 if (S_ISDIR(entry2->type)==0) return (-1);
217         } else{
218                 if (S_ISDIR(entry2->type)) return (1);
219         }
220         if (S_ISREG(entry1->type)){
221                 if (S_ISREG(entry2->type)==0) return (-1);
222         } else{
223                 if (S_ISREG(entry2->type)) return (1);
224         }
225         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
226         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
227
228         /* make sure "." and ".." are always first */
229         if( strcmp(entry1->relname, ".")==0 ) return (-1);
230         if( strcmp(entry2->relname, ".")==0 ) return (1);
231         if( strcmp(entry1->relname, "..")==0 ) return (-1);
232         if( strcmp(entry2->relname, "..")==0 ) return (1);
233         
234         if ( entry1->s.st_size < entry2->s.st_size) return 1;
235         if ( entry1->s.st_size > entry2->s.st_size) return -1;
236         else return BLI_strcasecmp(entry1->relname,entry2->relname);
237 }
238
239 static int compare_extension(const void *a1, const void *a2) {
240         const struct direntry *entry1=a1, *entry2=a2;
241         char *sufix1, *sufix2;
242         char *nil="";
243
244         if (!(sufix1= strstr (entry1->relname, ".blend.gz"))) 
245                 sufix1= strrchr (entry1->relname, '.');
246         if (!(sufix2= strstr (entry2->relname, ".blend.gz")))
247                 sufix2= strrchr (entry2->relname, '.');
248         if (!sufix1) sufix1= nil;
249         if (!sufix2) sufix2= nil;
250
251         /* type is is equal to stat.st_mode */
252
253         if (S_ISDIR(entry1->type)){
254                 if (S_ISDIR(entry2->type)==0) return (-1);
255         } else{
256                 if (S_ISDIR(entry2->type)) return (1);
257         }
258         if (S_ISREG(entry1->type)){
259                 if (S_ISREG(entry2->type)==0) return (-1);
260         } else{
261                 if (S_ISREG(entry2->type)) return (1);
262         }
263         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
264         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
265         
266         /* make sure "." and ".." are always first */
267         if( strcmp(entry1->relname, ".")==0 ) return (-1);
268         if( strcmp(entry2->relname, ".")==0 ) return (1);
269         if( strcmp(entry1->relname, "..")==0 ) return (-1);
270         if( strcmp(entry2->relname, "..")==0 ) return (1);
271         
272         return (BLI_strcasecmp(sufix1, sufix2));
273 }
274
275 void filelist_filter(FileList* filelist)
276 {
277         char dir[FILE_MAX], group[GROUP_MAX];
278         int num_filtered = 0;
279         int i, j;
280         
281         if (!filelist->filelist)
282                 return;
283         
284         if (!filelist->filter) {
285                 if (filelist->fidx) {
286                         MEM_freeN(filelist->fidx);
287                         filelist->fidx = NULL;
288                 }
289                 filelist->fidx = (int *)MEM_callocN(filelist->numfiles*sizeof(int), "filteridx");
290                 for (i = 0; i < filelist->numfiles; ++i) {
291                         filelist->fidx[i] = i;
292                 }
293                 filelist->numfiltered = filelist->numfiles;
294                 return;
295         }
296
297         // How many files are left after filter ?
298         for (i = 0; i < filelist->numfiles; ++i) {
299                 if (filelist->filelist[i].flags & filelist->filter) {
300                         num_filtered++;
301                 } 
302                 else if (filelist->filelist[i].type & S_IFDIR) {
303                         if (filelist->filter & FOLDERFILE) {
304                                 num_filtered++;
305                         }
306                 }               
307         }
308         
309         if (filelist->fidx) {
310                         MEM_freeN(filelist->fidx);
311                         filelist->fidx = NULL;
312         }
313         filelist->fidx = (int *)MEM_callocN(num_filtered*sizeof(int), "filteridx");
314         filelist->numfiltered = num_filtered;
315
316         for (i = 0, j=0; i < filelist->numfiles; ++i) {
317                 if (filelist->filelist[i].flags & filelist->filter) {
318                         filelist->fidx[j++] = i;
319                 }
320                 else if (filelist->filelist[i].type & S_IFDIR) {
321                         if (filelist->filter & FOLDERFILE) {
322                                 filelist->fidx[j++] = i;
323                         }
324                 }  
325         }
326 }
327
328 void filelist_init_icons()
329 {
330         short x, y, k;
331         ImBuf *bbuf;
332         ImBuf *ibuf;
333         bbuf = IMB_ibImageFromMemory((int *)datatoc_prvicons, datatoc_prvicons_size, IB_rect);
334         if (bbuf) {
335                 for (y=0; y<SPECIAL_IMG_ROWS; y++) {
336                         for (x=0; x<SPECIAL_IMG_COLS; x++) {
337                                 int tile = SPECIAL_IMG_COLS*y + x; 
338                                 if (tile < SPECIAL_IMG_MAX) {
339                                         ibuf = IMB_allocImBuf(SPECIAL_IMG_SIZE, SPECIAL_IMG_SIZE, 32, IB_rect, 0);
340                                         for (k=0; k<SPECIAL_IMG_SIZE; k++) {
341                                                 memcpy(&ibuf->rect[k*SPECIAL_IMG_SIZE], &bbuf->rect[(k+y*SPECIAL_IMG_SIZE)*SPECIAL_IMG_SIZE*SPECIAL_IMG_COLS+x*SPECIAL_IMG_SIZE], SPECIAL_IMG_SIZE*sizeof(int));
342                                         }
343                                         gSpecialFileImages[tile] = ibuf;
344                                 }
345                         }
346                 }
347                 IMB_freeImBuf(bbuf);
348         }
349 }
350
351 void filelist_free_icons()
352 {
353         int i;
354         for (i=0; i < SPECIAL_IMG_MAX; ++i) {
355                 IMB_freeImBuf(gSpecialFileImages[i]);
356                 gSpecialFileImages[i] = NULL;
357         }
358 }
359
360 struct FileList*        filelist_new()
361 {
362         FileList* p = MEM_callocN( sizeof(FileList), "filelist" );
363         p->filelist = 0;
364         p->numfiles = 0;
365         p->dir[0] = '\0';
366         p->type = 0;
367         p->has_func = 0;
368         p->filter = 0;
369         return p;
370 }
371
372 struct FileList*        filelist_copy(struct FileList* filelist)
373 {
374         FileList* p = filelist_new();
375         BLI_strncpy(p->dir, filelist->dir, FILE_MAX);
376         p->filelist = NULL;
377         p->fidx = NULL;
378         p->type = filelist->type;
379
380         return p;
381 }
382
383 void filelist_free(struct FileList* filelist)
384 {
385         int i;
386
387         if (!filelist) {
388                 printf("Attemtping to delete empty filelist.\n");
389                 return;
390         }
391
392         BLI_end_threads(&filelist->threads);
393         BLI_freelistN(&filelist->loadimages);
394         
395         if (filelist->fidx) {
396                 MEM_freeN(filelist->fidx);
397                 filelist->fidx = NULL;
398         }
399
400         for (i = 0; i < filelist->numfiles; ++i) {
401                 if (filelist->filelist[i].image) {                      
402                         IMB_freeImBuf(filelist->filelist[i].image);
403                 }
404                 filelist->filelist[i].image = 0;
405                 if (filelist->filelist[i].relname)
406                         MEM_freeN(filelist->filelist[i].relname);
407                 filelist->filelist[i].relname = 0;
408                 if (filelist->filelist[i].string)
409                         MEM_freeN(filelist->filelist[i].string);
410                 filelist->filelist[i].string = 0;
411         }
412         
413         filelist->numfiles = 0;
414         free(filelist->filelist);
415         filelist->filelist = 0; 
416         filelist->filter = 0;
417         filelist->numfiltered =0;
418 }
419
420 int     filelist_numfiles(struct FileList* filelist)
421 {
422         return filelist->numfiltered;
423 }
424
425 const char * filelist_dir(struct FileList* filelist)
426 {
427         return filelist->dir;
428 }
429
430 void filelist_setdir(struct FileList* filelist, const char *dir)
431 {
432         BLI_strncpy(filelist->dir, dir, FILE_MAX);
433 }
434
435 void filelist_imgsize(struct FileList* filelist, short w, short h)
436 {
437         filelist->prv_w = w;
438         filelist->prv_h = h;
439 }
440
441
442 static void *exec_loadimages(void *list_v)
443 {
444         FileImage* img = (FileImage*)list_v;
445         struct FileList *filelist = img->filelist;
446
447         ImBuf *imb = NULL;
448         int fidx = img->index;
449         
450         if ( filelist->filelist[fidx].flags & IMAGEFILE ) {                             
451                 imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_IMAGE);
452         } else if ( filelist->filelist[fidx].flags & MOVIEFILE ) {                              
453                 imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_MOVIE);
454                 if (!imb) {
455                         /* remember that file can't be loaded via IMB_open_anim */
456                         filelist->filelist[fidx].flags &= ~MOVIEFILE;
457                         filelist->filelist[fidx].flags |= MOVIEFILE_ICON;
458                 }
459         }
460         if (imb) {
461                 IMB_freeImBuf(imb);
462         }
463         img->done=1;
464         return 0;
465 }
466
467 short filelist_changed(struct FileList* filelist)
468 {
469         return filelist->changed;
470 }
471
472 void filelist_loadimage_timer(struct FileList* filelist)
473 {
474         FileImage *limg = filelist->loadimages.first;
475         short refresh=0;
476
477         // as long as threads are available and there is work to do
478         while (limg) {
479                 if (BLI_available_threads(&filelist->threads)>0) {
480                         if (!limg->lock) {
481                                 limg->lock=1;
482                                 BLI_insert_thread(&filelist->threads, limg);
483                         }
484                 }
485                 if (limg->done) {
486                         FileImage *oimg = limg;
487                         BLI_remlink(&filelist->loadimages, oimg);
488                         BLI_remove_thread(&filelist->threads, oimg);
489                         limg = oimg->next;
490                         MEM_freeN(oimg);
491                         refresh = 1;
492                 } else {
493                         limg= limg->next;
494                 }
495         }
496         filelist->changed=refresh;
497 }
498
499 void filelist_loadimage(struct FileList* filelist, int index)
500 {
501         ImBuf *imb = NULL;
502         int imgwidth = filelist->prv_w;
503         int imgheight = filelist->prv_h;
504         short ex, ey, dx, dy;
505         float scaledx, scaledy;
506         int fidx = 0;
507         
508         if ( (index < 0) || (index >= filelist->numfiltered) ) {
509                 return;
510         }
511         fidx = filelist->fidx[index];
512
513         if (!filelist->filelist[fidx].image)
514         {
515                 if (filelist->type != FILE_MAIN)
516                 {
517                         if ( (filelist->filelist[fidx].flags & IMAGEFILE) || (filelist->filelist[fidx].flags & MOVIEFILE) ) {                           
518                                 imb = IMB_thumb_read(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL);
519                         } 
520                         if (imb) {
521                                 if (imb->x > imb->y) {
522                                         scaledx = (float)imgwidth;
523                                         scaledy =  ( (float)imb->y/(float)imb->x )*imgwidth;
524                                 }
525                                 else {
526                                         scaledy = (float)imgheight;
527                                         scaledx =  ( (float)imb->x/(float)imb->y )*imgheight;
528                                 }
529                                 ex = (short)scaledx;
530                                 ey = (short)scaledy;
531                                 
532                                 dx = imgwidth - ex;
533                                 dy = imgheight - ey;
534                                 
535                                 IMB_scaleImBuf(imb, ex, ey);
536                                 filelist->filelist[fidx].image = imb;
537                         } else {
538                                 /* prevent loading image twice */
539                                 FileImage* limg = filelist->loadimages.first;
540                                 short found= 0;
541                                 while(limg) {
542                                         if (limg->index == fidx) {
543                                                 found= 1;
544                                                 break;
545                                         }
546                                         limg= limg->next;
547                                 }
548                                 if (!found) {
549                                         FileImage* limg = MEM_callocN(sizeof(struct FileImage), "loadimage");
550                                         limg->index= fidx;
551                                         limg->lock= 0;
552                                         limg->filelist= filelist;
553                                         BLI_addtail(&filelist->loadimages, limg);
554                                 }
555                         }               
556                 }
557         }
558 }
559
560 struct ImBuf * filelist_getimage(struct FileList* filelist, int index)
561 {
562         ImBuf* ibuf = NULL;
563         int fidx = 0;   
564         if ( (index < 0) || (index >= filelist->numfiltered) ) {
565                 return NULL;
566         }
567         fidx = filelist->fidx[index];
568         ibuf = filelist->filelist[fidx].image;
569
570         return ibuf;
571 }
572
573 struct ImBuf * filelist_geticon(struct FileList* filelist, int index)
574 {
575         ImBuf* ibuf= NULL;
576         struct direntry *file= NULL;
577         int fidx = 0;   
578         if ( (index < 0) || (index >= filelist->numfiltered) ) {
579                 return NULL;
580         }
581         fidx = filelist->fidx[index];
582         file = &filelist->filelist[fidx];
583         if (file->type & S_IFDIR) {
584                         if ( strcmp(filelist->filelist[fidx].relname, "..") == 0) {
585                                 ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
586                         } else if  ( strcmp(filelist->filelist[fidx].relname, ".") == 0) {
587                                 ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
588                         } else {
589                 ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
590                         }
591         } else {
592                 ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
593         }
594
595         if (file->flags & BLENDERFILE) {
596                 ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
597         } else if ( (file->flags & MOVIEFILE) || (file->flags & MOVIEFILE_ICON) ) {
598                 ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
599         } else if (file->flags & SOUNDFILE) {
600                 ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
601         } else if (file->flags & PYSCRIPTFILE) {
602                 ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
603         } else if (file->flags & FTFONTFILE) {
604                 ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
605         } else if (file->flags & TEXTFILE) {
606                 ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
607         } else if (file->flags & IMAGEFILE) {
608                 ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING];
609         }
610
611         return ibuf;
612 }
613
614 struct direntry * filelist_file(struct FileList* filelist, int index)
615 {
616         int fidx = 0;
617         
618         if ( (index < 0) || (index >= filelist->numfiltered) ) {
619                 return NULL;
620         }
621         fidx = filelist->fidx[index];
622
623         return &filelist->filelist[fidx];
624 }
625
626 int filelist_find(struct FileList* filelist, char *file)
627 {
628         int index = -1;
629         int i;
630         int fidx = -1;
631         
632         if (!filelist->fidx) 
633                 return fidx;
634
635         
636         for (i = 0; i < filelist->numfiles; ++i) {
637                 if ( strcmp(filelist->filelist[i].relname, file) == 0) {
638                         index = i;
639                         break;
640                 }
641         }
642
643         for (i = 0; i < filelist->numfiltered; ++i) {
644                 if (filelist->fidx[i] == index) {
645                         fidx = i;
646                         break;
647                 }
648         }
649         return fidx;
650 }
651
652 void filelist_hidedot(struct FileList* filelist, short hide)
653 {
654         filelist->hide_dot = hide;
655 }
656
657 void filelist_setfilter(struct FileList* filelist, unsigned int filter)
658 {
659         filelist->filter = filter;
660 }
661
662 int     filelist_maxnamelen(struct FileList* filelist)
663 {
664         return filelist->maxnamelen;
665 }
666
667 void filelist_readdir(struct FileList* filelist)
668 {
669         char wdir[FILE_MAX];
670         int finished = 0;
671         int i;
672
673         if (!filelist) return;
674         filelist->fidx = 0;
675         filelist->filelist = 0;
676
677         BLI_getwdN(wdir);        
678         
679         BLI_cleanup_dir(G.sce, filelist->dir);
680         BLI_hide_dot_files(filelist->hide_dot);
681         filelist->numfiles = BLI_getdir(filelist->dir, &(filelist->filelist));
682
683         chdir(wdir);
684         filelist_setfiletypes(filelist, G.have_quicktime);
685         filelist_filter(filelist);
686         
687         if (!filelist->threads.first) {
688                 BLI_init_threads(&filelist->threads, exec_loadimages, 2);
689         }
690
691         filelist->maxnamelen = 0;
692         for (i=0; (i < filelist->numfiles); ++i)
693         {
694                 struct direntry* file = filelist_file(filelist, i);     
695                 int len = UI_GetStringWidth(G.font, file->relname,0)+UI_GetStringWidth(G.font, file->size,0);
696                 if (len > filelist->maxnamelen) filelist->maxnamelen = len;
697         }
698 }
699
700 int filelist_empty(struct FileList* filelist)
701 {       
702         return filelist->filelist == 0;
703 }
704
705 void filelist_parent(struct FileList* filelist)
706 {
707         BLI_parent_dir(filelist->dir);
708         BLI_make_exist(filelist->dir);
709         filelist_readdir(filelist);
710 }
711
712 void filelist_setfiletypes(struct FileList* filelist, short has_quicktime)
713 {
714         struct direntry *file;
715         int num;
716
717         file= filelist->filelist;
718
719         for(num=0; num<filelist->numfiles; num++, file++) {
720                 file->flags= 0;
721                 file->type= file->s.st_mode;    /* restore the mess below */ 
722
723                         /* Don't check extensions for directories */ 
724                 if (file->type & S_IFDIR)
725                         continue;
726                                 
727                 
728                 
729                 if(BLO_has_bfile_extension(file->relname)) {
730                         file->flags |= BLENDERFILE;
731                         if(filelist->type==FILE_LOADLIB) {              
732                                 char name[FILE_MAXDIR+FILE_MAXFILE];
733                                 BLI_strncpy(name, filelist->dir, sizeof(name));
734                                 strcat(name, file->relname);
735                                 
736                                 /* prevent current file being used as acceptable dir */
737                                 if (BLI_streq(G.main->name, name)==0) {
738                                         file->type &= ~S_IFMT;
739                                         file->type |= S_IFDIR;
740                                 }
741                         }
742                 } else if(BLI_testextensie(file->relname, ".py")) {
743                                 file->flags |= PYSCRIPTFILE;
744                 } else if(BLI_testextensie(file->relname, ".txt")) {
745                                 file->flags |= TEXTFILE;
746                 } else if( BLI_testextensie(file->relname, ".ttf")
747                                         || BLI_testextensie(file->relname, ".ttc")
748                                         || BLI_testextensie(file->relname, ".pfb")
749                                         || BLI_testextensie(file->relname, ".otf")
750                                         || BLI_testextensie(file->relname, ".otc")) {
751                                 file->flags |= FTFONTFILE;                      
752                 } else if (has_quicktime){
753                         if(             BLI_testextensie(file->relname, ".int")
754                                 ||  BLI_testextensie(file->relname, ".inta")
755                                 ||  BLI_testextensie(file->relname, ".jpg")
756 #ifdef WITH_OPENJPEG
757                                 ||  BLI_testextensie(file->relname, ".jp2")
758 #endif
759                                 ||      BLI_testextensie(file->relname, ".jpeg")
760                                 ||      BLI_testextensie(file->relname, ".tga")
761                                 ||      BLI_testextensie(file->relname, ".rgb")
762                                 ||      BLI_testextensie(file->relname, ".rgba")
763                                 ||      BLI_testextensie(file->relname, ".bmp")
764                                 ||      BLI_testextensie(file->relname, ".png")
765                                 ||      BLI_testextensie(file->relname, ".iff")
766                                 ||      BLI_testextensie(file->relname, ".lbm")
767                                 ||      BLI_testextensie(file->relname, ".gif")
768                                 ||      BLI_testextensie(file->relname, ".psd")
769                                 ||      BLI_testextensie(file->relname, ".tif")
770                                 ||      BLI_testextensie(file->relname, ".tiff")
771                                 ||      BLI_testextensie(file->relname, ".pct")
772                                 ||      BLI_testextensie(file->relname, ".pict")
773                                 ||      BLI_testextensie(file->relname, ".pntg") //macpaint
774                                 ||      BLI_testextensie(file->relname, ".qtif")
775                                 ||      BLI_testextensie(file->relname, ".sgi")
776                                 ||      BLI_testextensie(file->relname, ".hdr")
777 #ifdef WITH_DDS
778                                 ||      BLI_testextensie(file->relname, ".dds")
779 #endif
780 #ifdef WITH_OPENEXR
781                                 ||      BLI_testextensie(file->relname, ".exr")
782 #endif
783                             ) {
784                                 file->flags |= IMAGEFILE;                       
785                         }
786                         else if(BLI_testextensie(file->relname, ".avi")
787                                 ||      BLI_testextensie(file->relname, ".flc")
788                                 ||      BLI_testextensie(file->relname, ".mov")
789                                 ||      BLI_testextensie(file->relname, ".movie")
790                                 ||      BLI_testextensie(file->relname, ".mp4")
791                                 ||      BLI_testextensie(file->relname, ".m4v")
792                                 ||      BLI_testextensie(file->relname, ".mv")) {
793                                 file->flags |= MOVIEFILE;                       
794                         }
795                         else if(BLI_testextensie(file->relname, ".wav")) {
796                                 file->flags |= SOUNDFILE;
797                         }
798                 } else { // no quicktime
799                         if(BLI_testextensie(file->relname, ".int")
800                                 ||      BLI_testextensie(file->relname, ".inta")
801                                 ||      BLI_testextensie(file->relname, ".jpg")
802                                 ||  BLI_testextensie(file->relname, ".jpeg")
803 #ifdef WITH_OPENJPEG
804                                 ||  BLI_testextensie(file->relname, ".jp2")
805 #endif
806                                 ||      BLI_testextensie(file->relname, ".tga")
807                                 ||      BLI_testextensie(file->relname, ".rgb")
808                                 ||      BLI_testextensie(file->relname, ".rgba")
809                                 ||      BLI_testextensie(file->relname, ".bmp")
810                                 ||      BLI_testextensie(file->relname, ".png")
811                                 ||      BLI_testextensie(file->relname, ".iff")
812                                 ||      BLI_testextensie(file->relname, ".tif")
813                                 ||      BLI_testextensie(file->relname, ".tiff")
814                                 ||      BLI_testextensie(file->relname, ".hdr")
815 #ifdef WITH_DDS
816                                 ||      BLI_testextensie(file->relname, ".dds")
817 #endif
818 #ifdef WITH_OPENEXR
819                                 ||      BLI_testextensie(file->relname, ".exr")
820 #endif
821                                 ||      BLI_testextensie(file->relname, ".lbm")
822                                 ||      BLI_testextensie(file->relname, ".sgi")) {
823                                 file->flags |= IMAGEFILE;                       
824                         }
825                         else if(BLI_testextensie(file->relname, ".avi")
826                                 ||      BLI_testextensie(file->relname, ".mp4")
827                                 ||      BLI_testextensie(file->relname, ".mv")) {
828                                 file->flags |= MOVIEFILE;                       
829                         }
830                         else if(BLI_testextensie(file->relname, ".wav")) {
831                                 file->flags |= SOUNDFILE;
832                         }
833                 }
834         }
835 }
836
837 void filelist_swapselect(struct FileList* filelist)
838 {
839         struct direntry *file;
840         int num, act= 0;
841         
842         file= filelist->filelist;
843         for(num=0; num<filelist->numfiles; num++, file++) {
844                 if(file->flags & ACTIVE) {
845                         act= 1;
846                         break;
847                 }
848         }
849         file= filelist->filelist+2;
850         for(num=2; num<filelist->numfiles; num++, file++) {
851                 if(act) file->flags &= ~ACTIVE;
852                 else file->flags |= ACTIVE;
853         }
854 }
855
856 void filelist_settype(struct FileList* filelist, int type)
857 {
858         filelist->type = type;
859 }
860
861 short filelist_gettype(struct FileList* filelist)
862 {
863         return filelist->type;
864 }
865
866 void filelist_sort(struct FileList* filelist, short sort)
867 {
868         struct direntry *file;
869         int num;/*  , act= 0; */
870
871         switch(sort) {
872         case FILE_SORTALPHA:
873                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_name);   
874                 break;
875         case FILE_SORTDATE:
876                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_date);   
877                 break;
878         case FILE_SORTSIZE:
879                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_size);   
880                 break;
881         case FILE_SORTEXTENS:
882                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_extension);      
883         }
884
885         file= filelist->filelist;
886         for(num=0; num<filelist->numfiles; num++, file++) {
887                 file->flags &= ~HILITE;
888         }
889         filelist_filter(filelist);
890 }