2.5
[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
53 #ifdef WIN32
54 #include "BLI_winstuff.h"
55 #endif
56
57 #include "BKE_utildefines.h"
58 #include "BKE_global.h"
59 #include "BKE_library.h"
60 #include "BKE_global.h"
61 #include "BKE_main.h"
62 #include "BLO_readfile.h"
63
64 #include "DNA_space_types.h"
65 #include "DNA_ipo_types.h"
66 #include "DNA_ID.h"
67 #include "DNA_object_types.h"
68 #include "DNA_lamp_types.h"
69 #include "DNA_material_types.h"
70 #include "DNA_texture_types.h"
71 #include "DNA_world_types.h"
72 #include "DNA_scene_types.h"
73 #include "DNA_userdef_types.h"
74
75 #include "IMB_imbuf.h"
76 #include "IMB_imbuf_types.h"
77 #include "IMB_thumbs.h"
78
79 #include "PIL_time.h"
80
81 #include "ED_datafiles.h"
82
83 #include "filelist.h"
84
85 /* Elubie: VERY, really very ugly and evil! Remove asap!!! */
86 /* for state of file */
87 #define ACTIVE                          2
88
89 /* max length of library group name within filesel */
90 #define GROUP_MAX 32
91
92 typedef struct FileList
93 {
94         struct direntry *filelist;
95         int *fidx;
96
97         int numfiles;
98         int numfiltered;
99         char dir[FILE_MAX];
100         short type;
101         short ipotype;
102         struct BlendHandle *libfiledata;
103         int has_func;
104         short prv_w;
105         short prv_h;
106         short hide_dot;
107         unsigned int filter;
108 } FileList;
109
110 int BIF_groupname_to_code(char *group)
111 {
112         char buf[32];
113         char *lslash;
114         
115         BLI_strncpy(buf, group, 31);
116         lslash= BLI_last_slash(buf);
117         if (lslash)
118                 lslash[0]= '\0';
119
120         return BLO_idcode_from_name(buf);
121 }
122
123
124 #define SPECIAL_IMG_SIZE 48
125 #define SPECIAL_IMG_ROWS 4
126 #define SPECIAL_IMG_COLS 4
127
128 #define SPECIAL_IMG_FOLDER 0
129 #define SPECIAL_IMG_PARENT 1
130 #define SPECIAL_IMG_REFRESH 2
131 #define SPECIAL_IMG_BLENDFILE 3
132 #define SPECIAL_IMG_SOUNDFILE 4
133 #define SPECIAL_IMG_MOVIEFILE 5
134 #define SPECIAL_IMG_PYTHONFILE 6
135 #define SPECIAL_IMG_TEXTFILE 7
136 #define SPECIAL_IMG_FONTFILE 8
137 #define SPECIAL_IMG_UNKNOWNFILE 9
138 #define SPECIAL_IMG_MAX SPECIAL_IMG_UNKNOWNFILE + 1
139
140 static ImBuf* gSpecialFileImages[SPECIAL_IMG_MAX];
141
142
143 /* ******************* SORT ******************* */
144
145 static int compare_name(const void *a1, const void *a2)
146 {
147         const struct direntry *entry1=a1, *entry2=a2;
148
149         /* type is is equal to stat.st_mode */
150
151         if (S_ISDIR(entry1->type)){
152                 if (S_ISDIR(entry2->type)==0) return (-1);
153         } else{
154                 if (S_ISDIR(entry2->type)) return (1);
155         }
156         if (S_ISREG(entry1->type)){
157                 if (S_ISREG(entry2->type)==0) return (-1);
158         } else{
159                 if (S_ISREG(entry2->type)) return (1);
160         }
161         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
162         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
163         
164         /* make sure "." and ".." are always first */
165         if( strcmp(entry1->relname, ".")==0 ) return (-1);
166         if( strcmp(entry2->relname, ".")==0 ) return (1);
167         if( strcmp(entry1->relname, "..")==0 ) return (-1);
168         
169         return (BLI_strcasecmp(entry1->relname,entry2->relname));
170 }
171
172 static int compare_date(const void *a1, const void *a2) 
173 {
174         const struct direntry *entry1=a1, *entry2=a2;
175         
176         /* type is equal to stat.st_mode */
177
178         if (S_ISDIR(entry1->type)){
179                 if (S_ISDIR(entry2->type)==0) return (-1);
180         } else{
181                 if (S_ISDIR(entry2->type)) return (1);
182         }
183         if (S_ISREG(entry1->type)){
184                 if (S_ISREG(entry2->type)==0) return (-1);
185         } else{
186                 if (S_ISREG(entry2->type)) return (1);
187         }
188         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
189         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
190
191         /* make sure "." and ".." are always first */
192         if( strcmp(entry1->relname, ".")==0 ) return (-1);
193         if( strcmp(entry2->relname, ".")==0 ) return (1);
194         if( strcmp(entry1->relname, "..")==0 ) return (-1);
195         
196         if ( entry1->s.st_mtime < entry2->s.st_mtime) return 1;
197         if ( entry1->s.st_mtime > entry2->s.st_mtime) return -1;
198         
199         else return BLI_strcasecmp(entry1->relname,entry2->relname);
200 }
201
202 static int compare_size(const void *a1, const void *a2) 
203 {
204         const struct direntry *entry1=a1, *entry2=a2;
205
206         /* type is equal to stat.st_mode */
207
208         if (S_ISDIR(entry1->type)){
209                 if (S_ISDIR(entry2->type)==0) return (-1);
210         } else{
211                 if (S_ISDIR(entry2->type)) return (1);
212         }
213         if (S_ISREG(entry1->type)){
214                 if (S_ISREG(entry2->type)==0) return (-1);
215         } else{
216                 if (S_ISREG(entry2->type)) return (1);
217         }
218         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
219         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
220
221         /* make sure "." and ".." are always first */
222         if( strcmp(entry1->relname, ".")==0 ) return (-1);
223         if( strcmp(entry2->relname, ".")==0 ) return (1);
224         if( strcmp(entry1->relname, "..")==0 ) return (-1);
225         
226         if ( entry1->s.st_size < entry2->s.st_size) return 1;
227         if ( entry1->s.st_size > entry2->s.st_size) return -1;
228         else return BLI_strcasecmp(entry1->relname,entry2->relname);
229 }
230
231 static int compare_extension(const void *a1, const void *a2) {
232         const struct direntry *entry1=a1, *entry2=a2;
233         char *sufix1, *sufix2;
234         char *nil="";
235
236         if (!(sufix1= strstr (entry1->relname, ".blend.gz"))) 
237                 sufix1= strrchr (entry1->relname, '.');
238         if (!(sufix2= strstr (entry2->relname, ".blend.gz")))
239                 sufix2= strrchr (entry2->relname, '.');
240         if (!sufix1) sufix1= nil;
241         if (!sufix2) sufix2= nil;
242
243         /* type is is equal to stat.st_mode */
244
245         if (S_ISDIR(entry1->type)){
246                 if (S_ISDIR(entry2->type)==0) return (-1);
247         } else{
248                 if (S_ISDIR(entry2->type)) return (1);
249         }
250         if (S_ISREG(entry1->type)){
251                 if (S_ISREG(entry2->type)==0) return (-1);
252         } else{
253                 if (S_ISREG(entry2->type)) return (1);
254         }
255         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
256         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
257         
258         /* make sure "." and ".." are always first */
259         if( strcmp(entry1->relname, ".")==0 ) return (-1);
260         if( strcmp(entry2->relname, ".")==0 ) return (1);
261         if( strcmp(entry1->relname, "..")==0 ) return (-1);
262         if( strcmp(entry2->relname, "..")==0 ) return (-1);
263         
264         return (BLI_strcasecmp(sufix1, sufix2));
265 }
266
267 void filelist_filter(FileList* filelist)
268 {
269         char dir[FILE_MAX], group[GROUP_MAX];
270         int num_filtered = 0;
271         int i, j;
272         
273         if (!filelist->filelist)
274                 return;
275         
276         if ( ( (filelist->type == FILE_LOADLIB) &&  filelist_islibrary(filelist, dir, group)) 
277                 || (filelist->type == FILE_MAIN) ) {
278                 filelist->filter = 0;
279         }
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 #if 0 /* XXX add icons here */
328         short x, y, k;
329         ImBuf *bbuf;
330         ImBuf *ibuf;
331         bbuf = IMB_ibImageFromMemory((int *)datatoc_prvicons, datatoc_prvicons_size, IB_rect);
332         if (bbuf) {
333                 for (y=0; y<SPECIAL_IMG_ROWS; y++) {
334                         for (x=0; x<SPECIAL_IMG_COLS; x++) {
335                                 int tile = SPECIAL_IMG_COLS*y + x; 
336                                 if (tile < SPECIAL_IMG_MAX) {
337                                         ibuf = IMB_allocImBuf(SPECIAL_IMG_SIZE, SPECIAL_IMG_SIZE, 32, IB_rect, 0);
338                                         for (k=0; k<SPECIAL_IMG_SIZE; k++) {
339                                                 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));
340                                         }
341                                         gSpecialFileImages[tile] = ibuf;
342                                 }
343                         }
344                 }
345                 IMB_freeImBuf(bbuf);
346         }
347 #endif
348 }
349
350 void filelist_free_icons()
351 {
352         int i;
353         for (i=0; i < SPECIAL_IMG_MAX; ++i) {
354                 IMB_freeImBuf(gSpecialFileImages[i]);
355                 gSpecialFileImages[i] = NULL;
356         }
357 }
358
359 struct FileList*        filelist_new()
360 {
361         FileList* p = MEM_callocN( sizeof(FileList), "filelist" );
362         p->filelist = 0;
363         p->numfiles = 0;
364         p->dir[0] = '\0';
365         p->libfiledata = 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         p->ipotype = filelist->ipotype;
380         p->has_func = filelist->has_func;
381
382         return p;
383 }
384
385 void filelist_free(struct FileList* filelist)
386 {
387         int i;
388
389         if (!filelist) {
390                 printf("Attemtping to delete empty filelist.\n");
391                 return;
392         }
393
394         if (filelist->fidx) {
395                 MEM_freeN(filelist->fidx);
396                 filelist->fidx = NULL;
397         }
398
399         for (i = 0; i < filelist->numfiles; ++i) {
400                 if (filelist->filelist[i].image) {                      
401                         IMB_freeImBuf(filelist->filelist[i].image);
402                 }
403                 filelist->filelist[i].image = 0;
404                 if (filelist->filelist[i].relname)
405                         MEM_freeN(filelist->filelist[i].relname);
406                 filelist->filelist[i].relname = 0;
407                 if (filelist->filelist[i].string)
408                         MEM_freeN(filelist->filelist[i].string);
409                 filelist->filelist[i].string = 0;
410         }
411         
412         filelist->numfiles = 0;
413         free(filelist->filelist);
414         filelist->filelist = 0; 
415         filelist->filter = 0;
416         filelist->numfiltered =0;
417 }
418
419 void filelist_freelib(struct FileList* filelist)
420 {
421         if(filelist->libfiledata)       
422                 BLO_blendhandle_close(filelist->libfiledata);
423         filelist->libfiledata= 0;
424 }
425
426 struct BlendHandle *filelist_lib(struct FileList* filelist)
427 {
428         return filelist->libfiledata;
429 }
430
431 int     filelist_numfiles(struct FileList* filelist)
432 {
433         return filelist->numfiltered;
434 }
435
436 const char * filelist_dir(struct FileList* filelist)
437 {
438         return filelist->dir;
439 }
440
441 void filelist_setdir(struct FileList* filelist, const char *dir)
442 {
443         BLI_strncpy(filelist->dir, dir, FILE_MAX);
444 }
445
446 void filelist_imgsize(struct FileList* filelist, short w, short h)
447 {
448         filelist->prv_w = w;
449         filelist->prv_h = h;
450 }
451
452 void filelist_loadimage(struct FileList* filelist, int index)
453 {
454         ImBuf *imb = NULL;
455         int imgwidth = filelist->prv_w;
456         int imgheight = filelist->prv_h;
457         short ex, ey, dx, dy;
458         float scaledx, scaledy;
459         int fidx = 0;
460         
461         if ( (index < 0) || (index >= filelist->numfiltered) ) {
462                 return;
463         }
464         fidx = filelist->fidx[index];
465
466         if (!filelist->filelist[fidx].image)
467         {
468                 if (filelist->type != FILE_MAIN)
469                 {
470                         if ( filelist->filelist[fidx].flags & IMAGEFILE ) {                             
471                                 imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_IMAGE);
472                         } else if ( filelist->filelist[fidx].flags & MOVIEFILE ) {                              
473                                 imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_MOVIE);
474                                 if (!imb) {
475                                         /* remember that file can't be loaded via IMB_open_anim */
476                                         filelist->filelist[fidx].flags &= ~MOVIEFILE;
477                                         filelist->filelist[fidx].flags |= MOVIEFILE_ICON;
478                                 }
479                         }
480                         if (imb) {
481                                 if (imb->x > imb->y) {
482                                         scaledx = (float)imgwidth;
483                                         scaledy =  ( (float)imb->y/(float)imb->x )*imgwidth;
484                                 }
485                                 else {
486                                         scaledy = (float)imgheight;
487                                         scaledx =  ( (float)imb->x/(float)imb->y )*imgheight;
488                                 }
489                                 ex = (short)scaledx;
490                                 ey = (short)scaledy;
491                                 
492                                 dx = imgwidth - ex;
493                                 dy = imgheight - ey;
494                                 
495                                 IMB_scaleImBuf(imb, ex, ey);
496
497                         } 
498                         filelist->filelist[fidx].image = imb;
499                         
500                 }
501         }
502 }
503
504 struct ImBuf * filelist_getimage(struct FileList* filelist, int index)
505 {
506         ImBuf* ibuf = NULL;
507         int fidx = 0;   
508         if ( (index < 0) || (index >= filelist->numfiltered) ) {
509                 return NULL;
510         }
511         fidx = filelist->fidx[index];
512         ibuf = filelist->filelist[fidx].image;
513
514         if (ibuf == NULL) {
515                 struct direntry *file = &filelist->filelist[fidx];
516                 if (file->type & S_IFDIR) {
517                         if ( strcmp(filelist->filelist[fidx].relname, "..") == 0) {
518                                 ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
519                         } else if  ( strcmp(filelist->filelist[fidx].relname, ".") == 0) {
520                                 ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
521                         } else {
522                                 ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
523                         }
524                 } else {
525                         ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
526                 }
527
528                 if (file->flags & BLENDERFILE) {
529                         ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
530                 } else if ( (file->flags & MOVIEFILE) || (file->flags & MOVIEFILE_ICON) ) {
531                         ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
532                 } else if (file->flags & SOUNDFILE) {
533                         ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
534                 } else if (file->flags & PYSCRIPTFILE) {
535                         ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
536                 } else if (file->flags & FTFONTFILE) {
537                         ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
538                 } else if (file->flags & TEXTFILE) {
539                         ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
540                 } 
541         }
542         return ibuf;
543 }
544
545 struct direntry * filelist_file(struct FileList* filelist, int index)
546 {
547         int fidx = 0;
548         
549         if ( (index < 0) || (index >= filelist->numfiltered) ) {
550                 return NULL;
551         }
552         fidx = filelist->fidx[index];
553
554         return &filelist->filelist[fidx];
555 }
556
557 int filelist_find(struct FileList* filelist, char *file)
558 {
559         int index = -1;
560         int i;
561         int fidx = -1;
562         
563         if (!filelist->fidx) 
564                 return fidx;
565
566         
567         for (i = 0; i < filelist->numfiles; ++i) {
568                 if ( strcmp(filelist->filelist[i].relname, file) == 0) {
569                         index = i;
570                         break;
571                 }
572         }
573
574         for (i = 0; i < filelist->numfiltered; ++i) {
575                 if (filelist->fidx[i] == index) {
576                         fidx = i;
577                         break;
578                 }
579         }
580         return fidx;
581 }
582
583 void filelist_hidedot(struct FileList* filelist, short hide)
584 {
585         filelist->hide_dot = hide;
586 }
587
588 void filelist_setfilter(struct FileList* filelist, unsigned int filter)
589 {
590         filelist->filter = filter;
591 }
592
593 void filelist_readdir(struct FileList* filelist)
594 {
595         char wdir[FILE_MAX];
596         int finished = 0;
597
598         if (!filelist) return;
599         filelist->fidx = 0;
600         filelist->filelist = 0;
601
602         if(filelist->type==FILE_MAIN) {
603                 filelist_from_main(filelist);
604                 finished = 1;
605         } else if(filelist->type==FILE_LOADLIB) {
606                 BLI_cleanup_dir(G.sce, filelist->dir);
607                 filelist_from_library(filelist);
608                 if(filelist->libfiledata) {
609                         finished = 1;
610                 }
611         }
612
613         if (!finished) {
614                 BLI_getwdN(wdir);        
615                 
616                 BLI_cleanup_dir(G.sce, filelist->dir);
617                 BLI_hide_dot_files(filelist->hide_dot);
618                 filelist->numfiles = BLI_getdir(filelist->dir, &(filelist->filelist));
619
620                 chdir(wdir);
621                 filelist_setfiletypes(filelist, G.have_quicktime);
622                 filelist_filter(filelist);
623
624         }
625 }
626
627 int filelist_empty(struct FileList* filelist)
628 {       
629         return filelist->filelist == 0;
630 }
631
632 void filelist_parent(struct FileList* filelist)
633 {
634         BLI_parent_dir(filelist->dir);
635         BLI_make_exist(filelist->dir);
636         filelist_readdir(filelist);
637 }
638
639 void filelist_setfiletypes(struct FileList* filelist, short has_quicktime)
640 {
641         struct direntry *file;
642         int num;
643
644         file= filelist->filelist;
645
646         for(num=0; num<filelist->numfiles; num++, file++) {
647                 file->flags= 0;
648                 file->type= file->s.st_mode;    /* restore the mess below */ 
649
650                         /* Don't check extensions for directories */ 
651                 if (file->type & S_IFDIR)
652                         continue;
653                                 
654                 
655                 
656                 if(BLO_has_bfile_extension(file->relname)) {
657                         file->flags |= BLENDERFILE;
658                         if(filelist->type==FILE_LOADLIB) {              
659                                 char name[FILE_MAXDIR+FILE_MAXFILE];
660                                 BLI_strncpy(name, filelist->dir, sizeof(name));
661                                 strcat(name, file->relname);
662                                 
663                                 /* prevent current file being used as acceptable dir */
664                                 if (BLI_streq(G.main->name, name)==0) {
665                                         file->type &= ~S_IFMT;
666                                         file->type |= S_IFDIR;
667                                 }
668                         }
669                 } else if(BLI_testextensie(file->relname, ".py")) {
670                                 file->flags |= PYSCRIPTFILE;
671                 } else if(BLI_testextensie(file->relname, ".txt")) {
672                                 file->flags |= TEXTFILE;
673                 } else if( BLI_testextensie(file->relname, ".ttf")
674                                         || BLI_testextensie(file->relname, ".ttc")
675                                         || BLI_testextensie(file->relname, ".pfb")
676                                         || BLI_testextensie(file->relname, ".otf")
677                                         || BLI_testextensie(file->relname, ".otc")) {
678                                 file->flags |= FTFONTFILE;                      
679                 } else if (has_quicktime){
680                         if(             BLI_testextensie(file->relname, ".int")
681                                 ||  BLI_testextensie(file->relname, ".inta")
682                                 ||  BLI_testextensie(file->relname, ".jpg")
683                                 ||      BLI_testextensie(file->relname, ".jpeg")
684                                 ||      BLI_testextensie(file->relname, ".tga")
685                                 ||      BLI_testextensie(file->relname, ".rgb")
686                                 ||      BLI_testextensie(file->relname, ".rgba")
687                                 ||      BLI_testextensie(file->relname, ".bmp")
688                                 ||      BLI_testextensie(file->relname, ".png")
689                                 ||      BLI_testextensie(file->relname, ".iff")
690                                 ||      BLI_testextensie(file->relname, ".lbm")
691                                 ||      BLI_testextensie(file->relname, ".gif")
692                                 ||      BLI_testextensie(file->relname, ".psd")
693                                 ||      BLI_testextensie(file->relname, ".tif")
694                                 ||      BLI_testextensie(file->relname, ".tiff")
695                                 ||      BLI_testextensie(file->relname, ".pct")
696                                 ||      BLI_testextensie(file->relname, ".pict")
697                                 ||      BLI_testextensie(file->relname, ".pntg") //macpaint
698                                 ||      BLI_testextensie(file->relname, ".qtif")
699                                 ||      BLI_testextensie(file->relname, ".sgi")
700                                 ||      BLI_testextensie(file->relname, ".hdr")
701 #ifdef WITH_DDS
702                                 ||      BLI_testextensie(file->relname, ".dds")
703 #endif
704 #ifdef WITH_OPENEXR
705                                 ||      BLI_testextensie(file->relname, ".exr")
706 #endif
707                             ) {
708                                 file->flags |= IMAGEFILE;                       
709                         }
710                         else if(BLI_testextensie(file->relname, ".avi")
711                                 ||      BLI_testextensie(file->relname, ".flc")
712                                 ||      BLI_testextensie(file->relname, ".mov")
713                                 ||      BLI_testextensie(file->relname, ".movie")
714                                 ||      BLI_testextensie(file->relname, ".mp4")
715                                 ||      BLI_testextensie(file->relname, ".m4v")
716                                 ||      BLI_testextensie(file->relname, ".mv")) {
717                                 file->flags |= MOVIEFILE;                       
718                         }
719                         else if(BLI_testextensie(file->relname, ".wav")) {
720                                 file->flags |= SOUNDFILE;
721                         }
722                 } else { // no quicktime
723                         if(BLI_testextensie(file->relname, ".int")
724                                 ||      BLI_testextensie(file->relname, ".inta")
725                                 ||      BLI_testextensie(file->relname, ".jpg")
726                                 ||      BLI_testextensie(file->relname, ".tga")
727                                 ||      BLI_testextensie(file->relname, ".rgb")
728                                 ||      BLI_testextensie(file->relname, ".rgba")
729                                 ||      BLI_testextensie(file->relname, ".bmp")
730                                 ||      BLI_testextensie(file->relname, ".png")
731                                 ||      BLI_testextensie(file->relname, ".iff")
732                                 ||      BLI_testextensie(file->relname, ".tif")
733                                 ||      BLI_testextensie(file->relname, ".tiff")
734                                 ||      BLI_testextensie(file->relname, ".hdr")
735 #ifdef WITH_DDS
736                                 ||      BLI_testextensie(file->relname, ".dds")
737 #endif
738 #ifdef WITH_OPENEXR
739                                 ||      BLI_testextensie(file->relname, ".exr")
740 #endif
741                                 ||      BLI_testextensie(file->relname, ".lbm")
742                                 ||      BLI_testextensie(file->relname, ".sgi")) {
743                                 file->flags |= IMAGEFILE;                       
744                         }
745                         else if(BLI_testextensie(file->relname, ".avi")
746                                 ||      BLI_testextensie(file->relname, ".mp4")
747                                 ||      BLI_testextensie(file->relname, ".mv")) {
748                                 file->flags |= MOVIEFILE;                       
749                         }
750                         else if(BLI_testextensie(file->relname, ".wav")) {
751                                 file->flags |= SOUNDFILE;
752                         }
753                 }
754         }
755 }
756
757 void filelist_swapselect(struct FileList* filelist)
758 {
759         struct direntry *file;
760         int num, act= 0;
761         
762         file= filelist->filelist;
763         for(num=0; num<filelist->numfiles; num++, file++) {
764                 if(file->flags & ACTIVE) {
765                         act= 1;
766                         break;
767                 }
768         }
769         file= filelist->filelist+2;
770         for(num=2; num<filelist->numfiles; num++, file++) {
771                 if(act) file->flags &= ~ACTIVE;
772                 else file->flags |= ACTIVE;
773         }
774 }
775
776 int filelist_islibrary(struct FileList* filelist, char* dir, char* group)
777 {
778          /* return ok when a blenderfile, in dir is the filename,
779          * in group the type of libdata
780          */
781         int len;
782         char *fd;
783         
784         strcpy(dir, filelist->dir);
785         len= strlen(dir);
786         if(len<7) return 0;
787         if( dir[len-1] != '/' && dir[len-1] != '\\') return 0;
788                 
789         group[0]= 0;
790         dir[len-1]= 0;
791
792         /* Find the last slash */
793         fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
794
795         if(fd==0) return 0;
796         *fd= 0;
797         if(BLO_has_bfile_extension(fd+1)) {
798                 *fd= '/';
799         }
800         else {
801                 char *gp = fd+1; // in case we have a .blend file, gp points to the group
802
803                 /* Find the last slash */
804                 fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
805                 if (!fd || !BLO_has_bfile_extension(fd+1)) return 0;
806
807                 /* now we know that we are in a blend file and it is safe to 
808                    assume that gp actually points to a group */
809                 BLI_strncpy(group, gp, GROUP_MAX);
810         }
811         return 1;
812 }
813
814 void filelist_from_library(struct FileList* filelist)
815 {
816         LinkNode *l, *names, *previews;
817         struct ImBuf* ima;
818         int ok, i, nnames, idcode;
819         char filename[FILE_MAXDIR+FILE_MAXFILE];
820         char dir[FILE_MAX], group[GROUP_MAX];   
821         
822         filelist->type = FILE_LOADLIB;
823
824         /* name test */
825         ok= filelist_islibrary(filelist, dir, group);
826         if (!ok) {
827                 /* free */
828                 if(filelist->libfiledata) BLO_blendhandle_close(filelist->libfiledata);
829                 filelist->libfiledata= 0;
830                 return;
831         }
832         
833         BLI_strncpy(filename, G.sce, sizeof(filename)); // G.sce = last file loaded, for UI
834
835         /* there we go */
836         /* for the time being only read filedata when libfiledata==0 */
837         if (filelist->libfiledata==0) {
838                 filelist->libfiledata= BLO_blendhandle_from_file(dir);
839                 if(filelist->libfiledata==0) return;
840         }
841         
842         idcode= BIF_groupname_to_code(group);
843
844                 // memory for strings is passed into filelist[i].relname
845                 // and free'd in freefilelist
846         previews = NULL;
847         if (idcode) {
848                 previews= BLO_blendhandle_get_previews(filelist->libfiledata, idcode);
849                 names= BLO_blendhandle_get_datablock_names(filelist->libfiledata, idcode);
850                 /* ugh, no rewind, need to reopen */
851                 BLO_blendhandle_close(filelist->libfiledata);
852                 filelist->libfiledata= BLO_blendhandle_from_file(dir);
853                 
854         } else {
855                 names= BLO_blendhandle_get_linkable_groups(filelist->libfiledata);
856         }
857         
858         nnames= BLI_linklist_length(names);
859
860         filelist->numfiles= nnames + 2;
861         filelist->filelist= malloc(filelist->numfiles * sizeof(*filelist->filelist));
862         memset(filelist->filelist, 0, filelist->numfiles * sizeof(*filelist->filelist));
863
864         filelist->filelist[0].relname= BLI_strdup(".");
865         filelist->filelist[0].type |= S_IFDIR;
866         filelist->filelist[1].relname= BLI_strdup("..");
867         filelist->filelist[1].type |= S_IFDIR;
868                 
869         for (i=0, l= names; i<nnames; i++, l= l->next) {
870                 char *blockname= l->link;
871
872                 filelist->filelist[i + 2].relname= BLI_strdup(blockname);
873                 if (!idcode)
874                         filelist->filelist[i + 2].type |= S_IFDIR;
875         }
876         
877         if(previews) {
878                 for (i=0, l= previews; i<nnames; i++, l= l->next) {
879                         PreviewImage *img= l->link;
880                         
881                         if (img) {
882                                 unsigned int w = img->w[PREVIEW_MIPMAP_LARGE];
883                                 unsigned int h = img->h[PREVIEW_MIPMAP_LARGE];
884                                 unsigned int *rect = img->rect[PREVIEW_MIPMAP_LARGE];
885
886                                 /* first allocate imbuf for copying preview into it */
887                                 if (w > 0 && h > 0 && rect) {
888                                         ima = IMB_allocImBuf(w, h, 32, IB_rect, 0);
889                                         memcpy(ima->rect, rect, w*h*sizeof(unsigned int));
890                                         filelist->filelist[i + 2].image = ima;
891                                         filelist->filelist[i + 2].flags = IMAGEFILE;
892                                 }
893                         }
894                 }
895         }
896
897         BLI_linklist_free(names, free);
898         if (previews) BLI_linklist_free(previews, (void(*)(void*)) MEM_freeN);
899
900         filelist_sort(filelist, FILE_SORTALPHA);
901
902         BLI_strncpy(G.sce, filename, sizeof(filename)); // prevent G.sce to change
903
904         filelist->filter = 0;
905         filelist_filter(filelist);
906 }
907
908 void filelist_append_library(struct FileList *filelist, char *dir, char *file, short flag, int idcode, struct Scene* scene)
909 {
910         BLO_library_append_(&filelist->libfiledata, filelist->filelist, filelist->numfiles, dir, file, flag, idcode, scene);
911 }
912
913 void filelist_from_main(struct FileList *filelist)
914 {
915         ID *id;
916         struct direntry *files, *firstlib = NULL;
917         ListBase *lb;
918         int a, fake, idcode, ok, totlib, totbl;
919         
920         filelist->type = FILE_MAIN;
921
922         if(filelist->dir[0]=='/') filelist->dir[0]= 0;
923         
924         if(filelist->dir[0]) {
925                 idcode= BIF_groupname_to_code(filelist->dir);
926                 if(idcode==0) filelist->dir[0]= 0;
927         }
928         
929         if( filelist->dir[0]==0) {
930                 
931                 /* make directories */
932                 filelist->numfiles= 23;
933                 filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry));
934                 
935                 for(a=0; a<filelist->numfiles; a++) {
936                         memset( &(filelist->filelist[a]), 0 , sizeof(struct direntry));
937                         filelist->filelist[a].type |= S_IFDIR;
938                 }
939                 
940                 filelist->filelist[0].relname= BLI_strdup("..");
941                 filelist->filelist[1].relname= BLI_strdup(".");
942                 filelist->filelist[2].relname= BLI_strdup("Scene");
943                 filelist->filelist[3].relname= BLI_strdup("Object");
944                 filelist->filelist[4].relname= BLI_strdup("Mesh");
945                 filelist->filelist[5].relname= BLI_strdup("Curve");
946                 filelist->filelist[6].relname= BLI_strdup("Metaball");
947                 filelist->filelist[7].relname= BLI_strdup("Material");
948                 filelist->filelist[8].relname= BLI_strdup("Texture");
949                 filelist->filelist[9].relname= BLI_strdup("Image");
950                 filelist->filelist[10].relname= BLI_strdup("Ika");
951                 filelist->filelist[11].relname= BLI_strdup("Wave");
952                 filelist->filelist[12].relname= BLI_strdup("Lattice");
953                 filelist->filelist[13].relname= BLI_strdup("Lamp");
954                 filelist->filelist[14].relname= BLI_strdup("Camera");
955                 filelist->filelist[15].relname= BLI_strdup("Ipo");
956                 filelist->filelist[16].relname= BLI_strdup("World");
957                 filelist->filelist[17].relname= BLI_strdup("Screen");
958                 filelist->filelist[18].relname= BLI_strdup("VFont");
959                 filelist->filelist[19].relname= BLI_strdup("Text");
960                 filelist->filelist[20].relname= BLI_strdup("Armature");
961                 filelist->filelist[21].relname= BLI_strdup("Action");
962                 filelist->filelist[22].relname= BLI_strdup("NodeTree");
963                 filelist_sort(filelist, FILE_SORTALPHA);
964         }
965         else {
966
967                 /* make files */
968                 idcode= BIF_groupname_to_code(filelist->dir);
969                 
970                 lb= wich_libbase(G.main, idcode );
971                 if(lb==0) return;
972                 
973                 id= lb->first;
974                 filelist->numfiles= 0;
975                 while(id) {
976                         
977                         if(filelist->has_func && idcode==ID_IP) {
978                                 if(filelist->ipotype== ((Ipo *)id)->blocktype) filelist->numfiles++;
979                         }
980                         else if (!filelist->hide_dot || id->name[2] != '.') {
981                                 filelist->numfiles++;
982                         }
983                         
984                         id= id->next;
985                 }
986                 
987                 if(!filelist->has_func) filelist->numfiles+= 2;
988                 filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry));
989                 
990                 files = filelist->filelist;
991                 
992                 if(!filelist->has_func) {
993                         memset( &(filelist->filelist[0]), 0 , sizeof(struct direntry));
994                         filelist->filelist[0].relname= BLI_strdup(".");
995                         filelist->filelist[0].type |= S_IFDIR;
996                         memset( &(filelist->filelist[1]), 0 , sizeof(struct direntry));
997                         filelist->filelist[1].relname= BLI_strdup("..");
998                         filelist->filelist[1].type |= S_IFDIR;
999                 
1000                         files+= 2;
1001                 }
1002                 
1003                 id= lb->first;
1004                 totlib= totbl= 0;
1005                 
1006                 while(id) {
1007                         
1008                         ok= 0;
1009                         if(filelist->has_func && idcode==ID_IP) {
1010                                 if(filelist->ipotype== ((Ipo *)id)->blocktype) ok= 1;
1011                         }
1012                         else ok= 1;
1013                         
1014                         if(ok) {
1015                                 /* TODO: hide dot files - elubie */
1016                                 memset( files, 0 , sizeof(struct direntry));
1017                                 if(id->lib==NULL)
1018                                         files->relname= BLI_strdup(id->name+2);
1019                                 else {
1020                                         files->relname= MEM_mallocN(FILE_MAXDIR+FILE_MAXFILE+32, "filename for lib");
1021                                         sprintf(files->relname, "%s | %s", id->lib->name, id->name+2);
1022                                 }
1023                                 /* files->type |= S_IFDIR; */
1024                                 if(!filelist->has_func) { /* F4 DATA BROWSE */
1025                                         if(idcode==ID_OB) {
1026                                                 if( ((Object *)id)->flag & SELECT) files->flags |= ACTIVE;
1027                                         }
1028                                         else if(idcode==ID_SCE) {
1029                                                 if( ((Scene *)id)->r.scemode & R_BG_RENDER) files->flags |= ACTIVE;
1030                                         }                                       
1031                                 }
1032                                 files->nr= totbl+1;
1033                                 files->poin= id;
1034                                 fake= id->flag & LIB_FAKEUSER;
1035                                 if(idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO || idcode == ID_IM) {
1036                                         files->flags |= IMAGEFILE;
1037                                 }
1038                                 if(id->lib && fake) sprintf(files->extra, "LF %d", id->us);
1039                                 else if(id->lib) sprintf(files->extra, "L    %d", id->us);
1040                                 else if(fake) sprintf(files->extra, "F    %d", id->us);
1041                                 else sprintf(files->extra, "      %d", id->us);
1042                                 
1043                                 if(id->lib) {
1044                                         if(totlib==0) firstlib= files;
1045                                         totlib++;
1046                                 }
1047                                 
1048                                 files++;
1049                                 totbl++;
1050                         }
1051                         
1052                         id= id->next;
1053                 }
1054                 
1055                 /* only qsort of library blocks */
1056                 if(totlib>1) {
1057                         qsort(firstlib, totlib, sizeof(struct direntry), compare_name);
1058                 }
1059         }
1060         filelist->filter = 0;
1061         filelist_filter(filelist);
1062 }
1063
1064
1065 void filelist_settype(struct FileList* filelist, int type)
1066 {
1067         filelist->type = type;
1068 }
1069
1070 short filelist_gettype(struct FileList* filelist)
1071 {
1072         return filelist->type;
1073 }
1074
1075 void filelist_sort(struct FileList* filelist, short sort)
1076 {
1077         struct direntry *file;
1078         int num;/*  , act= 0; */
1079
1080         switch(sort) {
1081         case FILE_SORTALPHA:
1082                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_name);   
1083                 break;
1084         case FILE_SORTDATE:
1085                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_date);   
1086                 break;
1087         case FILE_SORTSIZE:
1088                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_size);   
1089                 break;
1090         case FILE_SORTEXTENS:
1091                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_extension);      
1092         }
1093
1094         file= filelist->filelist;
1095         for(num=0; num<filelist->numfiles; num++, file++) {
1096                 file->flags &= ~HILITE;
1097         }
1098         filelist_filter(filelist);
1099 }
1100
1101
1102 void filelist_setipotype(struct FileList* filelist, short ipotype)
1103 {
1104         filelist->ipotype = ipotype;
1105 }
1106
1107 void filelist_hasfunc(struct FileList* filelist, int has_func)
1108 {
1109         filelist->has_func = has_func;
1110 }
1111