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