2.5: File Selector: display operator properties in the side region,
[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_interface.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         int has_func;
117         short prv_w;
118         short prv_h;
119         short hide_dot;
120         unsigned int filter;
121         short changed;
122         ListBase loadimages;
123         ListBase threads;
124 } FileList;
125
126 #define SPECIAL_IMG_SIZE 48
127 #define SPECIAL_IMG_ROWS 4
128 #define SPECIAL_IMG_COLS 4
129
130 #define SPECIAL_IMG_FOLDER 0
131 #define SPECIAL_IMG_PARENT 1
132 #define SPECIAL_IMG_REFRESH 2
133 #define SPECIAL_IMG_BLENDFILE 3
134 #define SPECIAL_IMG_SOUNDFILE 4
135 #define SPECIAL_IMG_MOVIEFILE 5
136 #define SPECIAL_IMG_PYTHONFILE 6
137 #define SPECIAL_IMG_TEXTFILE 7
138 #define SPECIAL_IMG_FONTFILE 8
139 #define SPECIAL_IMG_UNKNOWNFILE 9
140 #define SPECIAL_IMG_LOADING 10
141 #define SPECIAL_IMG_MAX SPECIAL_IMG_LOADING + 1
142
143 static ImBuf* gSpecialFileImages[SPECIAL_IMG_MAX];
144
145
146 /* ******************* SORT ******************* */
147
148 static int compare_name(const void *a1, const void *a2)
149 {
150         const struct direntry *entry1=a1, *entry2=a2;
151
152         /* type is is equal to stat.st_mode */
153
154         if (S_ISDIR(entry1->type)){
155                 if (S_ISDIR(entry2->type)==0) return (-1);
156         } else{
157                 if (S_ISDIR(entry2->type)) return (1);
158         }
159         if (S_ISREG(entry1->type)){
160                 if (S_ISREG(entry2->type)==0) return (-1);
161         } else{
162                 if (S_ISREG(entry2->type)) return (1);
163         }
164         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
165         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
166         
167         /* make sure "." and ".." are always first */
168         if( strcmp(entry1->relname, ".")==0 ) return (-1);
169         if( strcmp(entry2->relname, ".")==0 ) return (1);
170         if( strcmp(entry1->relname, "..")==0 ) return (-1);
171         if( strcmp(entry2->relname, "..")==0 ) return (1);
172         
173         return (BLI_natstrcmp(entry1->relname,entry2->relname));
174 }
175
176 static int compare_date(const void *a1, const void *a2) 
177 {
178         const struct direntry *entry1=a1, *entry2=a2;
179         
180         /* type is equal to stat.st_mode */
181
182         if (S_ISDIR(entry1->type)){
183                 if (S_ISDIR(entry2->type)==0) return (-1);
184         } else{
185                 if (S_ISDIR(entry2->type)) return (1);
186         }
187         if (S_ISREG(entry1->type)){
188                 if (S_ISREG(entry2->type)==0) return (-1);
189         } else{
190                 if (S_ISREG(entry2->type)) return (1);
191         }
192         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
193         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
194
195         /* make sure "." and ".." are always first */
196         if( strcmp(entry1->relname, ".")==0 ) return (-1);
197         if( strcmp(entry2->relname, ".")==0 ) return (1);
198         if( strcmp(entry1->relname, "..")==0 ) return (-1);
199         if( strcmp(entry2->relname, "..")==0 ) return (1);
200         
201         if ( entry1->s.st_mtime < entry2->s.st_mtime) return 1;
202         if ( entry1->s.st_mtime > entry2->s.st_mtime) return -1;
203         
204         else return BLI_natstrcmp(entry1->relname,entry2->relname);
205 }
206
207 static int compare_size(const void *a1, const void *a2) 
208 {
209         const struct direntry *entry1=a1, *entry2=a2;
210
211         /* type is equal to stat.st_mode */
212
213         if (S_ISDIR(entry1->type)){
214                 if (S_ISDIR(entry2->type)==0) return (-1);
215         } else{
216                 if (S_ISDIR(entry2->type)) return (1);
217         }
218         if (S_ISREG(entry1->type)){
219                 if (S_ISREG(entry2->type)==0) return (-1);
220         } else{
221                 if (S_ISREG(entry2->type)) return (1);
222         }
223         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
224         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
225
226         /* make sure "." and ".." are always first */
227         if( strcmp(entry1->relname, ".")==0 ) return (-1);
228         if( strcmp(entry2->relname, ".")==0 ) return (1);
229         if( strcmp(entry1->relname, "..")==0 ) return (-1);
230         if( strcmp(entry2->relname, "..")==0 ) return (1);
231         
232         if ( entry1->s.st_size < entry2->s.st_size) return 1;
233         if ( entry1->s.st_size > entry2->s.st_size) return -1;
234         else return BLI_natstrcmp(entry1->relname,entry2->relname);
235 }
236
237 static int compare_extension(const void *a1, const void *a2) {
238         const struct direntry *entry1=a1, *entry2=a2;
239         char *sufix1, *sufix2;
240         char *nil="";
241
242         if (!(sufix1= strstr (entry1->relname, ".blend.gz"))) 
243                 sufix1= strrchr (entry1->relname, '.');
244         if (!(sufix2= strstr (entry2->relname, ".blend.gz")))
245                 sufix2= strrchr (entry2->relname, '.');
246         if (!sufix1) sufix1= nil;
247         if (!sufix2) sufix2= nil;
248
249         /* type is is equal to stat.st_mode */
250
251         if (S_ISDIR(entry1->type)){
252                 if (S_ISDIR(entry2->type)==0) return (-1);
253         } else{
254                 if (S_ISDIR(entry2->type)) return (1);
255         }
256         if (S_ISREG(entry1->type)){
257                 if (S_ISREG(entry2->type)==0) return (-1);
258         } else{
259                 if (S_ISREG(entry2->type)) return (1);
260         }
261         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
262         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
263         
264         /* make sure "." and ".." are always first */
265         if( strcmp(entry1->relname, ".")==0 ) return (-1);
266         if( strcmp(entry2->relname, ".")==0 ) return (1);
267         if( strcmp(entry1->relname, "..")==0 ) return (-1);
268         if( strcmp(entry2->relname, "..")==0 ) return (1);
269         
270         return (BLI_strcasecmp(sufix1, sufix2));
271 }
272
273 void filelist_filter(FileList* filelist)
274 {
275         int num_filtered = 0;
276         int i, j;
277         
278         if (!filelist->filelist)
279                 return;
280         
281         if (!filelist->filter) {
282                 if (filelist->fidx) {
283                         MEM_freeN(filelist->fidx);
284                         filelist->fidx = NULL;
285                 }
286                 filelist->fidx = (int *)MEM_callocN(filelist->numfiles*sizeof(int), "filteridx");
287                 for (i = 0; i < filelist->numfiles; ++i) {
288                         filelist->fidx[i] = i;
289                 }
290                 filelist->numfiltered = filelist->numfiles;
291                 return;
292         }
293
294         // How many files are left after filter ?
295         for (i = 0; i < filelist->numfiles; ++i) {
296                 if (filelist->filelist[i].flags & filelist->filter) {
297                         num_filtered++;
298                 } 
299                 else if (filelist->filelist[i].type & S_IFDIR) {
300                         if (filelist->filter & FOLDERFILE) {
301                                 num_filtered++;
302                         }
303                 }               
304         }
305         
306         if (filelist->fidx) {
307                         MEM_freeN(filelist->fidx);
308                         filelist->fidx = NULL;
309         }
310         filelist->fidx = (int *)MEM_callocN(num_filtered*sizeof(int), "filteridx");
311         filelist->numfiltered = num_filtered;
312
313         for (i = 0, j=0; i < filelist->numfiles; ++i) {
314                 if (filelist->filelist[i].flags & filelist->filter) {
315                         filelist->fidx[j++] = i;
316                 }
317                 else if (filelist->filelist[i].type & S_IFDIR) {
318                         if (filelist->filter & FOLDERFILE) {
319                                 filelist->fidx[j++] = i;
320                         }
321                 }  
322         }
323 }
324
325 void filelist_init_icons()
326 {
327         short x, y, k;
328         ImBuf *bbuf;
329         ImBuf *ibuf;
330         bbuf = IMB_ibImageFromMemory((int *)datatoc_prvicons, datatoc_prvicons_size, IB_rect);
331         if (bbuf) {
332                 for (y=0; y<SPECIAL_IMG_ROWS; y++) {
333                         for (x=0; x<SPECIAL_IMG_COLS; x++) {
334                                 int tile = SPECIAL_IMG_COLS*y + x; 
335                                 if (tile < SPECIAL_IMG_MAX) {
336                                         ibuf = IMB_allocImBuf(SPECIAL_IMG_SIZE, SPECIAL_IMG_SIZE, 32, IB_rect, 0);
337                                         for (k=0; k<SPECIAL_IMG_SIZE; k++) {
338                                                 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));
339                                         }
340                                         gSpecialFileImages[tile] = ibuf;
341                                 }
342                         }
343                 }
344                 IMB_freeImBuf(bbuf);
345         }
346 }
347
348 void filelist_free_icons()
349 {
350         int i;
351         for (i=0; i < SPECIAL_IMG_MAX; ++i) {
352                 IMB_freeImBuf(gSpecialFileImages[i]);
353                 gSpecialFileImages[i] = NULL;
354         }
355 }
356
357 struct FileList*        filelist_new()
358 {
359         FileList* p = MEM_callocN( sizeof(FileList), "filelist" );
360         return p;
361 }
362
363 struct FileList*        filelist_copy(struct FileList* filelist)
364 {
365         FileList* p = filelist_new();
366         BLI_strncpy(p->dir, filelist->dir, FILE_MAX);
367         p->filelist = NULL;
368         p->fidx = NULL;
369
370         return p;
371 }
372
373 void filelist_free(struct FileList* filelist)
374 {
375         int i;
376
377         if (!filelist) {
378                 printf("Attemtping to delete empty filelist.\n");
379                 return;
380         }
381
382         BLI_end_threads(&filelist->threads);
383         BLI_freelistN(&filelist->loadimages);
384         
385         if (filelist->fidx) {
386                 MEM_freeN(filelist->fidx);
387                 filelist->fidx = NULL;
388         }
389
390         for (i = 0; i < filelist->numfiles; ++i) {
391                 if (filelist->filelist[i].image) {                      
392                         IMB_freeImBuf(filelist->filelist[i].image);
393                 }
394                 filelist->filelist[i].image = 0;
395                 if (filelist->filelist[i].relname)
396                         MEM_freeN(filelist->filelist[i].relname);
397                 filelist->filelist[i].relname = 0;
398                 if (filelist->filelist[i].string)
399                         MEM_freeN(filelist->filelist[i].string);
400                 filelist->filelist[i].string = 0;
401         }
402         
403         filelist->numfiles = 0;
404         free(filelist->filelist);
405         filelist->filelist = 0; 
406         filelist->filter = 0;
407         filelist->numfiltered =0;
408         filelist->hide_dot =0;
409 }
410
411 int     filelist_numfiles(struct FileList* filelist)
412 {
413         return filelist->numfiltered;
414 }
415
416 const char * filelist_dir(struct FileList* filelist)
417 {
418         return filelist->dir;
419 }
420
421 void filelist_setdir(struct FileList* filelist, const char *dir)
422 {
423         BLI_strncpy(filelist->dir, dir, FILE_MAX);
424 }
425
426 void filelist_imgsize(struct FileList* filelist, short w, short h)
427 {
428         filelist->prv_w = w;
429         filelist->prv_h = h;
430 }
431
432
433 static void *exec_loadimages(void *list_v)
434 {
435         FileImage* img = (FileImage*)list_v;
436         struct FileList *filelist = img->filelist;
437
438         ImBuf *imb = NULL;
439         int fidx = img->index;
440         
441         if ( filelist->filelist[fidx].flags & IMAGEFILE ) {                             
442                 imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_IMAGE);
443         } else if ( filelist->filelist[fidx].flags & MOVIEFILE ) {                              
444                 imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_MOVIE);
445                 if (!imb) {
446                         /* remember that file can't be loaded via IMB_open_anim */
447                         filelist->filelist[fidx].flags &= ~MOVIEFILE;
448                         filelist->filelist[fidx].flags |= MOVIEFILE_ICON;
449                 }
450         }
451         if (imb) {
452                 IMB_freeImBuf(imb);
453         }
454         img->done=1;
455         return 0;
456 }
457
458 short filelist_changed(struct FileList* filelist)
459 {
460         return filelist->changed;
461 }
462
463 void filelist_loadimage_timer(struct FileList* filelist)
464 {
465         FileImage *limg = filelist->loadimages.first;
466         short refresh=0;
467
468         // as long as threads are available and there is work to do
469         while (limg) {
470                 if (BLI_available_threads(&filelist->threads)>0) {
471                         if (!limg->lock) {
472                                 limg->lock=1;
473                                 BLI_insert_thread(&filelist->threads, limg);
474                         }
475                 }
476                 if (limg->done) {
477                         FileImage *oimg = limg;
478                         BLI_remlink(&filelist->loadimages, oimg);
479                         BLI_remove_thread(&filelist->threads, oimg);
480                         limg = oimg->next;
481                         MEM_freeN(oimg);
482                         refresh = 1;
483                 } else {
484                         limg= limg->next;
485                 }
486         }
487         filelist->changed=refresh;
488 }
489
490 void filelist_loadimage(struct FileList* filelist, int index)
491 {
492         ImBuf *imb = NULL;
493         int imgwidth = filelist->prv_w;
494         int imgheight = filelist->prv_h;
495         short ex, ey, dx, dy;
496         float scaledx, scaledy;
497         int fidx = 0;
498         
499         if ( (index < 0) || (index >= filelist->numfiltered) ) {
500                 return;
501         }
502         fidx = filelist->fidx[index];
503
504         if (!filelist->filelist[fidx].image)
505         {
506
507                 if ( (filelist->filelist[fidx].flags & IMAGEFILE) || (filelist->filelist[fidx].flags & MOVIEFILE) ) {                           
508                         imb = IMB_thumb_read(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL);
509                 } 
510                 if (imb) {
511                         if (imb->x > imb->y) {
512                                 scaledx = (float)imgwidth;
513                                 scaledy =  ( (float)imb->y/(float)imb->x )*imgwidth;
514                         }
515                         else {
516                                 scaledy = (float)imgheight;
517                                 scaledx =  ( (float)imb->x/(float)imb->y )*imgheight;
518                         }
519                         ex = (short)scaledx;
520                         ey = (short)scaledy;
521                         
522                         dx = imgwidth - ex;
523                         dy = imgheight - ey;
524                         
525                         // IMB_scaleImBuf(imb, ex, ey);
526                         filelist->filelist[fidx].image = imb;
527                 } else {
528                         /* prevent loading image twice */
529                         FileImage* limg = filelist->loadimages.first;
530                         short found= 0;
531                         while(limg) {
532                                 if (limg->index == fidx) {
533                                         found= 1;
534                                         break;
535                                 }
536                                 limg= limg->next;
537                         }
538                         if (!found) {
539                                 FileImage* limg = MEM_callocN(sizeof(struct FileImage), "loadimage");
540                                 limg->index= fidx;
541                                 limg->lock= 0;
542                                 limg->filelist= filelist;
543                                 BLI_addtail(&filelist->loadimages, limg);
544                         }
545                 }               
546         }
547 }
548
549 struct ImBuf * filelist_getimage(struct FileList* filelist, int index)
550 {
551         ImBuf* ibuf = NULL;
552         int fidx = 0;   
553         if ( (index < 0) || (index >= filelist->numfiltered) ) {
554                 return NULL;
555         }
556         fidx = filelist->fidx[index];
557         ibuf = filelist->filelist[fidx].image;
558
559         return ibuf;
560 }
561
562 struct ImBuf * filelist_geticon(struct FileList* filelist, int index)
563 {
564         ImBuf* ibuf= NULL;
565         struct direntry *file= NULL;
566         int fidx = 0;   
567         if ( (index < 0) || (index >= filelist->numfiltered) ) {
568                 return NULL;
569         }
570         fidx = filelist->fidx[index];
571         file = &filelist->filelist[fidx];
572         if (file->type & S_IFDIR) {
573                         if ( strcmp(filelist->filelist[fidx].relname, "..") == 0) {
574                                 ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
575                         } else if  ( strcmp(filelist->filelist[fidx].relname, ".") == 0) {
576                                 ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
577                         } else {
578                 ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
579                         }
580         } else {
581                 ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
582         }
583
584         if (file->flags & BLENDERFILE) {
585                 ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
586         } else if ( (file->flags & MOVIEFILE) || (file->flags & MOVIEFILE_ICON) ) {
587                 ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
588         } else if (file->flags & SOUNDFILE) {
589                 ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
590         } else if (file->flags & PYSCRIPTFILE) {
591                 ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
592         } else if (file->flags & FTFONTFILE) {
593                 ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
594         } else if (file->flags & TEXTFILE) {
595                 ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
596         } else if (file->flags & IMAGEFILE) {
597                 ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING];
598         }
599
600         return ibuf;
601 }
602
603 struct direntry * filelist_file(struct FileList* filelist, int index)
604 {
605         int fidx = 0;
606         
607         if ( (index < 0) || (index >= filelist->numfiltered) ) {
608                 return NULL;
609         }
610         fidx = filelist->fidx[index];
611
612         return &filelist->filelist[fidx];
613 }
614
615
616 int filelist_find(struct FileList* filelist, char *file)
617 {
618         int index = -1;
619         int i;
620         int fidx = -1;
621         
622         if (!filelist->fidx) 
623                 return fidx;
624
625         
626         for (i = 0; i < filelist->numfiles; ++i) {
627                 if ( strcmp(filelist->filelist[i].relname, file) == 0) {
628                         index = i;
629                         break;
630                 }
631         }
632
633         for (i = 0; i < filelist->numfiltered; ++i) {
634                 if (filelist->fidx[i] == index) {
635                         fidx = i;
636                         break;
637                 }
638         }
639         return fidx;
640 }
641
642 void filelist_hidedot(struct FileList* filelist, short hide)
643 {
644         filelist->hide_dot = hide;
645 }
646
647 void filelist_setfilter(struct FileList* filelist, unsigned int filter)
648 {
649         filelist->filter = filter;
650 }
651
652 void filelist_readdir(struct FileList* filelist)
653 {
654         char wdir[FILE_MAX];
655
656         if (!filelist) return;
657         filelist->fidx = 0;
658         filelist->filelist = 0;
659
660         BLI_getwdN(wdir);        
661         
662         BLI_cleanup_dir(G.sce, filelist->dir);
663         BLI_hide_dot_files(filelist->hide_dot);
664         filelist->numfiles = BLI_getdir(filelist->dir, &(filelist->filelist));
665
666         chdir(wdir);
667         filelist_setfiletypes(filelist, G.have_quicktime);
668         filelist_filter(filelist);
669         
670         if (!filelist->threads.first) {
671                 BLI_init_threads(&filelist->threads, exec_loadimages, 2);
672         }
673 }
674
675 int filelist_empty(struct FileList* filelist)
676 {       
677         return filelist->filelist == 0;
678 }
679
680 void filelist_parent(struct FileList* filelist)
681 {
682         BLI_parent_dir(filelist->dir);
683         BLI_make_exist(filelist->dir);
684         filelist_readdir(filelist);
685 }
686
687 void filelist_setfiletypes(struct FileList* filelist, short has_quicktime)
688 {
689         struct direntry *file;
690         int num;
691
692         file= filelist->filelist;
693
694         for(num=0; num<filelist->numfiles; num++, file++) {
695                 file->flags= 0;
696                 file->type= file->s.st_mode;    /* restore the mess below */ 
697
698                         /* Don't check extensions for directories */ 
699                 if (file->type & S_IFDIR)
700                         continue;
701                                 
702                 
703                 
704                 if(BLO_has_bfile_extension(file->relname)) {
705                         file->flags |= BLENDERFILE;
706                 } else if(BLI_testextensie(file->relname, ".py")) {
707                                 file->flags |= PYSCRIPTFILE;
708                 } else if(BLI_testextensie(file->relname, ".txt")) {
709                                 file->flags |= TEXTFILE;
710                 } else if( BLI_testextensie(file->relname, ".ttf")
711                                         || BLI_testextensie(file->relname, ".ttc")
712                                         || BLI_testextensie(file->relname, ".pfb")
713                                         || BLI_testextensie(file->relname, ".otf")
714                                         || BLI_testextensie(file->relname, ".otc")) {
715                                 file->flags |= FTFONTFILE;                      
716                 } else if (has_quicktime){
717                         if(             BLI_testextensie(file->relname, ".int")
718                                 ||  BLI_testextensie(file->relname, ".inta")
719                                 ||  BLI_testextensie(file->relname, ".jpg")
720 #ifdef WITH_OPENJPEG
721                                 ||  BLI_testextensie(file->relname, ".jp2")
722 #endif
723                                 ||      BLI_testextensie(file->relname, ".jpeg")
724                                 ||      BLI_testextensie(file->relname, ".tga")
725                                 ||      BLI_testextensie(file->relname, ".rgb")
726                                 ||      BLI_testextensie(file->relname, ".rgba")
727                                 ||      BLI_testextensie(file->relname, ".bmp")
728                                 ||      BLI_testextensie(file->relname, ".png")
729                                 ||      BLI_testextensie(file->relname, ".iff")
730                                 ||      BLI_testextensie(file->relname, ".lbm")
731                                 ||      BLI_testextensie(file->relname, ".gif")
732                                 ||      BLI_testextensie(file->relname, ".psd")
733                                 ||      BLI_testextensie(file->relname, ".tif")
734                                 ||      BLI_testextensie(file->relname, ".tiff")
735                                 ||      BLI_testextensie(file->relname, ".pct")
736                                 ||      BLI_testextensie(file->relname, ".pict")
737                                 ||      BLI_testextensie(file->relname, ".pntg") //macpaint
738                                 ||      BLI_testextensie(file->relname, ".qtif")
739                                 ||      BLI_testextensie(file->relname, ".sgi")
740                                 ||      BLI_testextensie(file->relname, ".hdr")
741 #ifdef WITH_DDS
742                                 ||      BLI_testextensie(file->relname, ".dds")
743 #endif
744 #ifdef WITH_OPENEXR
745                                 ||      BLI_testextensie(file->relname, ".exr")
746 #endif
747                             ) {
748                                 file->flags |= IMAGEFILE;                       
749                         }
750                         else if(BLI_testextensie(file->relname, ".avi")
751                                 ||      BLI_testextensie(file->relname, ".flc")
752                                 ||      BLI_testextensie(file->relname, ".mov")
753                                 ||      BLI_testextensie(file->relname, ".movie")
754                                 ||      BLI_testextensie(file->relname, ".mp4")
755                                 ||      BLI_testextensie(file->relname, ".m4v")
756                                 ||      BLI_testextensie(file->relname, ".mv")) {
757                                 file->flags |= MOVIEFILE;                       
758                         }
759                         else if(BLI_testextensie(file->relname, ".wav")) {
760                                 file->flags |= SOUNDFILE;
761                         }
762                 } else { // no quicktime
763                         if(BLI_testextensie(file->relname, ".int")
764                                 ||      BLI_testextensie(file->relname, ".inta")
765                                 ||      BLI_testextensie(file->relname, ".jpg")
766                                 ||  BLI_testextensie(file->relname, ".jpeg")
767 #ifdef WITH_OPENJPEG
768                                 ||  BLI_testextensie(file->relname, ".jp2")
769 #endif
770                                 ||      BLI_testextensie(file->relname, ".tga")
771                                 ||      BLI_testextensie(file->relname, ".rgb")
772                                 ||      BLI_testextensie(file->relname, ".rgba")
773                                 ||      BLI_testextensie(file->relname, ".bmp")
774                                 ||      BLI_testextensie(file->relname, ".png")
775                                 ||      BLI_testextensie(file->relname, ".iff")
776                                 ||      BLI_testextensie(file->relname, ".tif")
777                                 ||      BLI_testextensie(file->relname, ".tiff")
778                                 ||      BLI_testextensie(file->relname, ".hdr")
779 #ifdef WITH_DDS
780                                 ||      BLI_testextensie(file->relname, ".dds")
781 #endif
782 #ifdef WITH_OPENEXR
783                                 ||      BLI_testextensie(file->relname, ".exr")
784 #endif
785                                 ||      BLI_testextensie(file->relname, ".lbm")
786                                 ||      BLI_testextensie(file->relname, ".sgi")) {
787                                 file->flags |= IMAGEFILE;                       
788                         }
789                         else if(BLI_testextensie(file->relname, ".avi")
790                                 ||      BLI_testextensie(file->relname, ".mp4")
791                                 ||      BLI_testextensie(file->relname, ".mv")) {
792                                 file->flags |= MOVIEFILE;                       
793                         }
794                         else if(BLI_testextensie(file->relname, ".wav")) {
795                                 file->flags |= SOUNDFILE;
796                         }
797                 }
798         }
799 }
800
801 void filelist_swapselect(struct FileList* filelist)
802 {
803         struct direntry *file;
804         int num, act= 0;
805         
806         file= filelist->filelist;
807         for(num=0; num<filelist->numfiles; num++, file++) {
808                 if(file->flags & ACTIVE) {
809                         act= 1;
810                         break;
811                 }
812         }
813         file= filelist->filelist+2;
814         for(num=2; num<filelist->numfiles; num++, file++) {
815                 if(act) file->flags &= ~ACTIVE;
816                 else file->flags |= ACTIVE;
817         }
818 }
819
820 void filelist_sort(struct FileList* filelist, short sort)
821 {
822         struct direntry *file;
823         int num;/*  , act= 0; */
824
825         switch(sort) {
826         case FILE_SORTALPHA:
827                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_name);   
828                 break;
829         case FILE_SORTDATE:
830                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_date);   
831                 break;
832         case FILE_SORTSIZE:
833                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_size);   
834                 break;
835         case FILE_SORTEXTENS:
836                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_extension);      
837         }
838
839         file= filelist->filelist;
840         for(num=0; num<filelist->numfiles; num++, file++) {
841                 file->flags &= ~HILITE;
842         }
843         filelist_filter(filelist);
844 }