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