=== Custom Transform Orientation ===
[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         int *fidx;
95
96         int numfiles;
97         int numfiltered;
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         char dir[FILE_MAX], group[GROUP_MAX];
269         int num_filtered = 0;
270         int i, j;
271         
272         if (!filelist->filelist)
273                 return;
274         
275         if ( ( (filelist->type == FILE_LOADLIB) &&  BIF_filelist_islibrary(filelist, dir, group)) 
276                 || (filelist->type == FILE_MAIN) ) {
277                 filelist->filter = 0;
278         }
279
280         if (!filelist->filter) {
281                 if (filelist->fidx) {
282                         MEM_freeN(filelist->fidx);
283                         filelist->fidx = NULL;
284                 }
285                 filelist->fidx = (int *)MEM_callocN(filelist->numfiles*sizeof(int), "filteridx");
286                 for (i = 0; i < filelist->numfiles; ++i) {
287                         filelist->fidx[i] = i;
288                 }
289                 filelist->numfiltered = filelist->numfiles;
290                 return;
291         }
292
293         // How many files are left after filter ?
294         for (i = 0; i < filelist->numfiles; ++i) {
295                 if (filelist->filelist[i].flags & filelist->filter) {
296                         num_filtered++;
297                 } 
298                 else if (filelist->filelist[i].type & S_IFDIR) {
299                         if (filelist->filter & FOLDERFILE) {
300                                 num_filtered++;
301                         }
302                 }               
303         }
304         
305         if (filelist->fidx) {
306                         MEM_freeN(filelist->fidx);
307                         filelist->fidx = NULL;
308         }
309         filelist->fidx = (int *)MEM_callocN(num_filtered*sizeof(int), "filteridx");
310         filelist->numfiltered = num_filtered;
311
312         for (i = 0, j=0; i < filelist->numfiles; ++i) {
313                 if (filelist->filelist[i].flags & filelist->filter) {
314                         filelist->fidx[j++] = i;
315                 }
316                 else if (filelist->filelist[i].type & S_IFDIR) {
317                         if (filelist->filter & FOLDERFILE) {
318                                 filelist->fidx[j++] = i;
319                         }
320                 }  
321         }
322 }
323
324 void BIF_filelist_init_icons()
325 {
326         short x, y, k;
327         ImBuf *bbuf;
328         ImBuf *ibuf;
329         bbuf = IMB_ibImageFromMemory((int *)datatoc_prvicons, datatoc_prvicons_size, IB_rect);
330         if (bbuf) {
331                 for (y=0; y<SPECIAL_IMG_ROWS; y++) {
332                         for (x=0; x<SPECIAL_IMG_COLS; x++) {
333                                 int tile = SPECIAL_IMG_COLS*y + x; 
334                                 if (tile < SPECIAL_IMG_MAX) {
335                                         ibuf = IMB_allocImBuf(SPECIAL_IMG_SIZE, SPECIAL_IMG_SIZE, 32, IB_rect, 0);
336                                         for (k=0; k<SPECIAL_IMG_SIZE; k++) {
337                                                 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));
338                                         }
339                                         gSpecialFileImages[tile] = ibuf;
340                                 }
341                         }
342                 }
343                 IMB_freeImBuf(bbuf);
344         }
345
346 }
347
348 void BIF_filelist_free_icons()
349 {
350         int i;
351         for (i=0; i < SPECIAL_IMG_MAX; ++i) {
352                 IMB_freeImBuf(gSpecialFileImages[i]);
353                 gSpecialFileImages[i] = NULL;
354         }
355 }
356
357 struct FileList*        BIF_filelist_new()
358 {
359         FileList* p = MEM_callocN( sizeof(FileList), "filelist" );
360         p->filelist = 0;
361         p->numfiles = 0;
362         p->dir[0] = '\0';
363         p->libfiledata = 0;
364         p->type = 0;
365         p->has_func = 0;
366         p->filter = 0;
367         return p;
368 }
369
370 struct FileList*        BIF_filelist_copy(struct FileList* filelist)
371 {
372         FileList* p = BIF_filelist_new();
373         BLI_strncpy(p->dir, filelist->dir, FILE_MAXDIR);
374         p->filelist = NULL;
375         p->fidx = NULL;
376         p->type = filelist->type;
377         p->ipotype = filelist->ipotype;
378         p->has_func = filelist->has_func;
379
380         return p;
381 }
382
383 void BIF_filelist_free(struct FileList* filelist)
384 {
385         int i;
386
387         if (!filelist) {
388                 printf("Attemtping to delete empty filelist.\n");
389                 return;
390         }
391
392         if (filelist->fidx) {
393                 MEM_freeN(filelist->fidx);
394                 filelist->fidx = NULL;
395         }
396
397         for (i = 0; i < filelist->numfiles; ++i) {
398                 if (filelist->filelist[i].image) {                      
399                         IMB_freeImBuf(filelist->filelist[i].image);
400                 }
401                 filelist->filelist[i].image = 0;
402                 if (filelist->filelist[i].relname)
403                         MEM_freeN(filelist->filelist[i].relname);
404                 filelist->filelist[i].relname = 0;
405                 if (filelist->filelist[i].string)
406                         MEM_freeN(filelist->filelist[i].string);
407                 filelist->filelist[i].string = 0;
408         }
409         
410         filelist->numfiles = 0;
411         free(filelist->filelist);
412         filelist->filelist = 0; 
413         filelist->filter = 0;
414         filelist->numfiltered =0;
415 }
416
417 void BIF_filelist_freelib(struct FileList* filelist)
418 {
419         if(filelist->libfiledata)       
420                 BLO_blendhandle_close(filelist->libfiledata);
421         filelist->libfiledata= 0;
422 }
423
424 struct BlendHandle *BIF_filelist_lib(struct FileList* filelist)
425 {
426         return filelist->libfiledata;
427 }
428
429 int     BIF_filelist_numfiles(struct FileList* filelist)
430 {
431         return filelist->numfiltered;
432 }
433
434 const char * BIF_filelist_dir(struct FileList* filelist)
435 {
436         return filelist->dir;
437 }
438
439 void BIF_filelist_setdir(struct FileList* filelist, const char *dir)
440 {
441         BLI_strncpy(filelist->dir, dir, FILE_MAXDIR);
442 }
443
444 void BIF_filelist_imgsize(struct FileList* filelist, short w, short h)
445 {
446         filelist->prv_w = w;
447         filelist->prv_h = h;
448 }
449
450 void BIF_filelist_loadimage(struct FileList* filelist, int index)
451 {
452         ImBuf *imb = NULL;
453         int imgwidth = filelist->prv_w;
454         int imgheight = filelist->prv_h;
455         short ex, ey, dx, dy;
456         float scaledx, scaledy;
457         int fidx = 0;
458         
459         if ( (index < 0) || (index >= filelist->numfiltered) ) {
460                 return;
461         }
462         fidx = filelist->fidx[index];
463
464         if (!filelist->filelist[fidx].image)
465         {
466                 if (filelist->type != FILE_MAIN)
467                 {
468                         if ( filelist->filelist[fidx].flags & IMAGEFILE ) {                             
469                                 imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_IMAGE);
470                         } else if ( filelist->filelist[fidx].flags & MOVIEFILE ) {                              
471                                 imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_MOVIE);
472                                 if (!imb) {
473                                         /* remember that file can't be loaded via IMB_open_anim */
474                                         filelist->filelist[fidx].flags &= ~MOVIEFILE;
475                                         filelist->filelist[fidx].flags |= MOVIEFILE_ICON;
476                                 }
477                         }
478                         if (imb) {
479                                 if (imb->x > imb->y) {
480                                         scaledx = (float)imgwidth;
481                                         scaledy =  ( (float)imb->y/(float)imb->x )*imgwidth;
482                                 }
483                                 else {
484                                         scaledy = (float)imgheight;
485                                         scaledx =  ( (float)imb->x/(float)imb->y )*imgheight;
486                                 }
487                                 ex = (short)scaledx;
488                                 ey = (short)scaledy;
489                                 
490                                 dx = imgwidth - ex;
491                                 dy = imgheight - ey;
492                                 
493                                 IMB_scaleImBuf(imb, ex, ey);
494
495                         } 
496                         filelist->filelist[fidx].image = imb;
497                         
498                 }
499         }
500 }
501
502 struct ImBuf * BIF_filelist_getimage(struct FileList* filelist, int index)
503 {
504         ImBuf* ibuf = NULL;
505         int fidx = 0;   
506         if ( (index < 0) || (index >= filelist->numfiltered) ) {
507                 return NULL;
508         }
509         fidx = filelist->fidx[index];
510         ibuf = filelist->filelist[fidx].image;
511
512         if (ibuf == NULL) {
513                 struct direntry *file = &filelist->filelist[fidx];
514                 if (file->type & S_IFDIR) {
515                         if ( strcmp(filelist->filelist[fidx].relname, "..") == 0) {
516                                 ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
517                         } else if  ( strcmp(filelist->filelist[fidx].relname, ".") == 0) {
518                                 ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
519                         } else {
520                                 ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
521                         }
522                 } else {
523                         ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
524                 }
525
526                 if (file->flags & BLENDERFILE) {
527                         ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
528                 } else if ( (file->flags & MOVIEFILE) || (file->flags & MOVIEFILE_ICON) ) {
529                         ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
530                 } else if (file->flags & SOUNDFILE) {
531                         ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
532                 } else if (file->flags & PYSCRIPTFILE) {
533                         ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
534                 } else if (file->flags & FTFONTFILE) {
535                         ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
536                 } else if (file->flags & TEXTFILE) {
537                         ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
538                 } 
539         }
540         return ibuf;
541 }
542
543 struct direntry * BIF_filelist_file(struct FileList* filelist, int index)
544 {
545         int fidx = 0;
546         
547         if ( (index < 0) || (index >= filelist->numfiltered) ) {
548                 return NULL;
549         }
550         fidx = filelist->fidx[index];
551
552         return &filelist->filelist[fidx];
553 }
554
555 int BIF_filelist_find(struct FileList* filelist, char *file)
556 {
557         int index = -1;
558         int i;
559         int fidx = -1;
560         
561         if (!filelist->fidx) 
562                 return fidx;
563
564         
565         for (i = 0; i < filelist->numfiles; ++i) {
566                 if ( strcmp(filelist->filelist[i].relname, file) == 0) {
567                         index = i;
568                         break;
569                 }
570         }
571
572         for (i = 0; i < filelist->numfiltered; ++i) {
573                 if (filelist->fidx[i] == index) {
574                         fidx = i;
575                         break;
576                 }
577         }
578         return fidx;
579 }
580
581 void BIF_filelist_hidedot(struct FileList* filelist, short hide)
582 {
583         filelist->hide_dot = hide;
584 }
585
586 void BIF_filelist_setfilter(struct FileList* filelist, unsigned int filter)
587 {
588         filelist->filter = filter;
589 }
590
591 void BIF_filelist_readdir(struct FileList* filelist)
592 {
593         char wdir[FILE_MAXDIR];
594         int finished = 0;
595
596         if (!filelist) return;
597         filelist->fidx = 0;
598         filelist->filelist = 0;
599
600         if(filelist->type==FILE_MAIN) {
601                 BIF_filelist_from_main(filelist);
602                 finished = 1;
603         } else if(filelist->type==FILE_LOADLIB) {
604                 BLI_cleanup_dir(G.sce, filelist->dir);
605                 BIF_filelist_from_library(filelist);
606                 if(filelist->libfiledata) {
607                         finished = 1;
608                 }
609         }
610
611         if (!finished) {
612                 BLI_getwdN(wdir);        
613                 
614                 BLI_cleanup_dir(G.sce, filelist->dir);
615                 BLI_hide_dot_files(filelist->hide_dot);
616                 filelist->numfiles = BLI_getdir(filelist->dir, &(filelist->filelist));
617
618                 chdir(wdir);
619                 BIF_filelist_setfiletypes(filelist, G.have_quicktime);
620                 BIF_filelist_filter(filelist);
621
622         }
623 }
624
625 int BIF_filelist_empty(struct FileList* filelist)
626 {       
627         return filelist->filelist == 0;
628 }
629
630 void BIF_filelist_parent(struct FileList* filelist)
631 {
632 #ifdef WIN32
633         char c = '\\';
634 #else
635         char c = '/';
636 #endif
637         char *dir = filelist->dir;
638         size_t len = strlen(dir);
639         
640         while( (len > 0) && (dir[len-1] == c)  )
641         {
642                 --len;
643                 dir[len] = '\0';
644         }
645         while ( (len > 0) && (dir[len-1] != c) )
646         {
647                 --len;
648                 dir[len] = '\0';
649         }
650         if (len == 0)
651         {
652                 dir[0] = c; dir[1] = '\0';
653         }
654 #ifdef WIN32
655         strcat(filelist->dir, "\\");
656 #else
657         strcat(filelist->dir, "/");
658 #endif
659         
660         BLI_cleanup_dir(G.sce, filelist->dir);
661         BLI_make_exist(filelist->dir);
662         BIF_filelist_readdir(filelist);
663 }
664
665 void BIF_filelist_setfiletypes(struct FileList* filelist, short has_quicktime)
666 {
667         struct direntry *file;
668         int num;
669
670         file= filelist->filelist;
671
672         for(num=0; num<filelist->numfiles; num++, file++) {
673                 file->flags= 0;
674                 file->type= file->s.st_mode;    /* restore the mess below */ 
675
676                         /* Don't check extensions for directories */ 
677                 if (file->type & S_IFDIR)
678                         continue;
679                                 
680                 
681                 
682                 if(BLO_has_bfile_extension(file->relname)) {
683                         file->flags |= BLENDERFILE;
684                         if(filelist->type==FILE_LOADLIB) {              
685                                 char name[FILE_MAXDIR+FILE_MAXFILE];
686                                 BLI_strncpy(name, filelist->dir, sizeof(name));
687                                 strcat(name, file->relname);
688                                 
689                                 /* prevent current file being used as acceptable dir */
690                                 if (BLI_streq(G.main->name, name)==0) {
691                                         file->type &= ~S_IFMT;
692                                         file->type |= S_IFDIR;
693                                 }
694                         }
695                 } else if(BLI_testextensie(file->relname, ".py")) {
696                                 file->flags |= PYSCRIPTFILE;
697                 } else if(BLI_testextensie(file->relname, ".txt")) {
698                                 file->flags |= TEXTFILE;
699                 } else if( BLI_testextensie(file->relname, ".ttf")
700                                         || BLI_testextensie(file->relname, ".ttc")
701                                         || BLI_testextensie(file->relname, ".pfb")
702                                         || BLI_testextensie(file->relname, ".otf")
703                                         || BLI_testextensie(file->relname, ".otc")) {
704                                 file->flags |= FTFONTFILE;                      
705                 } else if (has_quicktime){
706                         if(             BLI_testextensie(file->relname, ".int")
707                                 ||  BLI_testextensie(file->relname, ".inta")
708                                 ||  BLI_testextensie(file->relname, ".jpg")
709                                 ||      BLI_testextensie(file->relname, ".jpeg")
710                                 ||      BLI_testextensie(file->relname, ".tga")
711                                 ||      BLI_testextensie(file->relname, ".rgb")
712                                 ||      BLI_testextensie(file->relname, ".rgba")
713                                 ||      BLI_testextensie(file->relname, ".bmp")
714                                 ||      BLI_testextensie(file->relname, ".png")
715                                 ||      BLI_testextensie(file->relname, ".iff")
716                                 ||      BLI_testextensie(file->relname, ".lbm")
717                                 ||      BLI_testextensie(file->relname, ".gif")
718                                 ||      BLI_testextensie(file->relname, ".psd")
719                                 ||      BLI_testextensie(file->relname, ".tif")
720                                 ||      BLI_testextensie(file->relname, ".tiff")
721                                 ||      BLI_testextensie(file->relname, ".pct")
722                                 ||      BLI_testextensie(file->relname, ".pict")
723                                 ||      BLI_testextensie(file->relname, ".pntg") //macpaint
724                                 ||      BLI_testextensie(file->relname, ".qtif")
725                                 ||      BLI_testextensie(file->relname, ".sgi")
726 #ifdef WITH_DDS
727                                 ||      BLI_testextensie(file->relname, ".dds")
728 #endif
729 #ifdef WITH_OPENEXR
730                                 ||      BLI_testextensie(file->relname, ".exr")
731 #endif
732                             ) {
733                                 file->flags |= IMAGEFILE;                       
734                         }
735                         else if(BLI_testextensie(file->relname, ".avi")
736                                 ||      BLI_testextensie(file->relname, ".flc")
737                                 ||      BLI_testextensie(file->relname, ".mov")
738                                 ||      BLI_testextensie(file->relname, ".movie")
739                                 ||      BLI_testextensie(file->relname, ".mp4")
740                                 ||      BLI_testextensie(file->relname, ".m4v")
741                                 ||      BLI_testextensie(file->relname, ".mv")) {
742                                 file->flags |= MOVIEFILE;                       
743                         }
744                         else if(BLI_testextensie(file->relname, ".wav")) {
745                                 file->flags |= SOUNDFILE;
746                         }
747                 } else { // no quicktime
748                         if(BLI_testextensie(file->relname, ".int")
749                                 ||      BLI_testextensie(file->relname, ".inta")
750                                 ||      BLI_testextensie(file->relname, ".jpg")
751                                 ||      BLI_testextensie(file->relname, ".tga")
752                                 ||      BLI_testextensie(file->relname, ".rgb")
753                                 ||      BLI_testextensie(file->relname, ".rgba")
754                                 ||      BLI_testextensie(file->relname, ".bmp")
755                                 ||      BLI_testextensie(file->relname, ".png")
756                                 ||      BLI_testextensie(file->relname, ".iff")
757                                 ||      BLI_testextensie(file->relname, ".tif")
758                                 ||      BLI_testextensie(file->relname, ".tiff")
759 #ifdef WITH_DDS
760                                 ||      BLI_testextensie(file->relname, ".dds")
761 #endif
762 #ifdef WITH_OPENEXR
763                                 ||      BLI_testextensie(file->relname, ".exr")
764 #endif
765                                 ||      BLI_testextensie(file->relname, ".lbm")
766                                 ||      BLI_testextensie(file->relname, ".sgi")) {
767                                 file->flags |= IMAGEFILE;                       
768                         }
769                         else if(BLI_testextensie(file->relname, ".avi")
770                                 ||      BLI_testextensie(file->relname, ".mp4")
771                                 ||      BLI_testextensie(file->relname, ".mv")) {
772                                 file->flags |= MOVIEFILE;                       
773                         }
774                         else if(BLI_testextensie(file->relname, ".wav")) {
775                                 file->flags |= SOUNDFILE;
776                         }
777                 }
778         }
779 }
780
781 void BIF_filelist_swapselect(struct FileList* filelist)
782 {
783         struct direntry *file;
784         int num, act= 0;
785         
786         file= filelist->filelist;
787         for(num=0; num<filelist->numfiles; num++, file++) {
788                 if(file->flags & ACTIVE) {
789                         act= 1;
790                         break;
791                 }
792         }
793         file= filelist->filelist+2;
794         for(num=2; num<filelist->numfiles; num++, file++) {
795                 if(act) file->flags &= ~ACTIVE;
796                 else file->flags |= ACTIVE;
797         }
798 }
799
800 int BIF_filelist_islibrary(struct FileList* filelist, char* dir, char* group)
801 {
802          /* return ok when a blenderfile, in dir is the filename,
803          * in group the type of libdata
804          */
805         int len;
806         char *fd;
807         
808         strcpy(dir, filelist->dir);
809         len= strlen(dir);
810         if(len<7) return 0;
811         if( dir[len-1] != '/' && dir[len-1] != '\\') return 0;
812                 
813         group[0]= 0;
814         dir[len-1]= 0;
815
816         /* Find the last slash */
817         fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
818
819         if(fd==0) return 0;
820         *fd= 0;
821         if(BLO_has_bfile_extension(fd+1)) {
822                 *fd= '/';
823         }
824         else {
825                 char *gp = fd+1; // in case we have a .blend file, gp points to the group
826
827                 /* Find the last slash */
828                 fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
829                 if (!fd || !BLO_has_bfile_extension(fd+1)) return 0;
830
831                 /* now we know that we are in a blend file and it is safe to 
832                    assume that gp actually points to a group */
833                 BLI_strncpy(group, gp, GROUP_MAX);
834         }
835         return 1;
836 }
837
838 void BIF_filelist_from_library(struct FileList* filelist)
839 {
840         LinkNode *l, *names, *previews;
841         struct ImBuf* ima;
842         int ok, i, nnames, idcode;
843         char filename[FILE_MAXDIR+FILE_MAXFILE];
844         char dir[FILE_MAXDIR], group[GROUP_MAX];        
845         
846         filelist->type = FILE_LOADLIB;
847
848         /* name test */
849         ok= BIF_filelist_islibrary(filelist, dir, group);
850         if (!ok) {
851                 /* free */
852                 if(filelist->libfiledata) BLO_blendhandle_close(filelist->libfiledata);
853                 filelist->libfiledata= 0;
854                 return;
855         }
856         
857         BLI_strncpy(filename, G.sce, sizeof(filename)); // G.sce = last file loaded, for UI
858
859         /* there we go */
860         /* for the time being only read filedata when libfiledata==0 */
861         if (filelist->libfiledata==0) {
862                 filelist->libfiledata= BLO_blendhandle_from_file(dir);
863                 if(filelist->libfiledata==0) return;
864         }
865         
866         idcode= BIF_groupname_to_code(group);
867
868                 // memory for strings is passed into filelist[i].relname
869                 // and free'd in freefilelist
870         previews = NULL;
871         if (idcode) {
872                 previews= BLO_blendhandle_get_previews(filelist->libfiledata, idcode);
873                 names= BLO_blendhandle_get_datablock_names(filelist->libfiledata, idcode);
874                 /* ugh, no rewind, need to reopen */
875                 BLO_blendhandle_close(filelist->libfiledata);
876                 filelist->libfiledata= BLO_blendhandle_from_file(dir);
877                 
878         } else {
879                 names= BLO_blendhandle_get_linkable_groups(filelist->libfiledata);
880         }
881         
882         nnames= BLI_linklist_length(names);
883
884         filelist->numfiles= nnames + 2;
885         filelist->filelist= malloc(filelist->numfiles * sizeof(*filelist->filelist));
886         memset(filelist->filelist, 0, filelist->numfiles * sizeof(*filelist->filelist));
887
888         filelist->filelist[0].relname= BLI_strdup(".");
889         filelist->filelist[0].type |= S_IFDIR;
890         filelist->filelist[1].relname= BLI_strdup("..");
891         filelist->filelist[1].type |= S_IFDIR;
892                 
893         for (i=0, l= names; i<nnames; i++, l= l->next) {
894                 char *blockname= l->link;
895
896                 filelist->filelist[i + 2].relname= BLI_strdup(blockname);
897                 if (!idcode)
898                         filelist->filelist[i + 2].type |= S_IFDIR;
899         }
900         
901         if(previews) {
902                 for (i=0, l= previews; i<nnames; i++, l= l->next) {
903                         PreviewImage *img= l->link;
904                         
905                         if (img) {
906                                 unsigned int w = img->w[PREVIEW_MIPMAP_LARGE];
907                                 unsigned int h = img->h[PREVIEW_MIPMAP_LARGE];
908                                 unsigned int *rect = img->rect[PREVIEW_MIPMAP_LARGE];
909
910                                 /* first allocate imbuf for copying preview into it */
911                                 if (w > 0 && h > 0 && rect) {
912                                         ima = IMB_allocImBuf(w, h, 32, IB_rect, 0);
913                                         memcpy(ima->rect, rect, w*h*sizeof(unsigned int));
914                                         filelist->filelist[i + 2].image = ima;
915                                         filelist->filelist[i + 2].flags = IMAGEFILE;
916                                 }
917                         }
918                 }
919         }
920
921         BLI_linklist_free(names, free);
922         if (previews) BLI_linklist_free(previews, (void(*)(void*)) MEM_freeN);
923
924         BIF_filelist_sort(filelist, FILE_SORTALPHA);
925
926         BLI_strncpy(G.sce, filename, sizeof(filename)); // prevent G.sce to change
927
928         filelist->filter = 0;
929         BIF_filelist_filter(filelist);
930 }
931
932 void BIF_filelist_append_library(struct FileList *filelist, char *dir, char *file, short flag, int idcode)
933 {
934         BLO_library_append_(&filelist->libfiledata, filelist->filelist, filelist->numfiles, dir, file, flag, idcode);
935 }
936
937 void BIF_filelist_from_main(struct FileList *filelist)
938 {
939         ID *id;
940         struct direntry *files, *firstlib = NULL;
941         ListBase *lb;
942         int a, fake, idcode, ok, totlib, totbl;
943         
944         filelist->type = FILE_MAIN;
945
946         if(filelist->dir[0]=='/') filelist->dir[0]= 0;
947         
948         if(filelist->dir[0]) {
949                 idcode= BIF_groupname_to_code(filelist->dir);
950                 if(idcode==0) filelist->dir[0]= 0;
951         }
952         
953         if( filelist->dir[0]==0) {
954                 
955                 /* make directories */
956                 filelist->numfiles= 23;
957                 filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry));
958                 
959                 for(a=0; a<filelist->numfiles; a++) {
960                         memset( &(filelist->filelist[a]), 0 , sizeof(struct direntry));
961                         filelist->filelist[a].type |= S_IFDIR;
962                 }
963                 
964                 filelist->filelist[0].relname= BLI_strdup("..");
965                 filelist->filelist[1].relname= BLI_strdup(".");
966                 filelist->filelist[2].relname= BLI_strdup("Scene");
967                 filelist->filelist[3].relname= BLI_strdup("Object");
968                 filelist->filelist[4].relname= BLI_strdup("Mesh");
969                 filelist->filelist[5].relname= BLI_strdup("Curve");
970                 filelist->filelist[6].relname= BLI_strdup("Metaball");
971                 filelist->filelist[7].relname= BLI_strdup("Material");
972                 filelist->filelist[8].relname= BLI_strdup("Texture");
973                 filelist->filelist[9].relname= BLI_strdup("Image");
974                 filelist->filelist[10].relname= BLI_strdup("Ika");
975                 filelist->filelist[11].relname= BLI_strdup("Wave");
976                 filelist->filelist[12].relname= BLI_strdup("Lattice");
977                 filelist->filelist[13].relname= BLI_strdup("Lamp");
978                 filelist->filelist[14].relname= BLI_strdup("Camera");
979                 filelist->filelist[15].relname= BLI_strdup("Ipo");
980                 filelist->filelist[16].relname= BLI_strdup("World");
981                 filelist->filelist[17].relname= BLI_strdup("Screen");
982                 filelist->filelist[18].relname= BLI_strdup("VFont");
983                 filelist->filelist[19].relname= BLI_strdup("Text");
984                 filelist->filelist[20].relname= BLI_strdup("Armature");
985                 filelist->filelist[21].relname= BLI_strdup("Action");
986                 filelist->filelist[22].relname= BLI_strdup("NodeTree");
987                 BIF_filelist_sort(filelist, FILE_SORTALPHA);
988         }
989         else {
990
991                 /* make files */
992                 idcode= BIF_groupname_to_code(filelist->dir);
993                 
994                 lb= wich_libbase(G.main, idcode );
995                 if(lb==0) return;
996                 
997                 id= lb->first;
998                 filelist->numfiles= 0;
999                 while(id) {
1000                         
1001                         if(filelist->has_func && idcode==ID_IP) {
1002                                 if(filelist->ipotype== ((Ipo *)id)->blocktype) filelist->numfiles++;
1003                         }
1004                         else if (!filelist->hide_dot || id->name[2] != '.') {
1005                                 filelist->numfiles++;
1006                         }
1007                         
1008                         id= id->next;
1009                 }
1010                 
1011                 if(!filelist->has_func) filelist->numfiles+= 2;
1012                 filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry));
1013                 
1014                 files = filelist->filelist;
1015                 
1016                 if(!filelist->has_func) {
1017                         memset( &(filelist->filelist[0]), 0 , sizeof(struct direntry));
1018                         filelist->filelist[0].relname= BLI_strdup(".");
1019                         filelist->filelist[0].type |= S_IFDIR;
1020                         memset( &(filelist->filelist[1]), 0 , sizeof(struct direntry));
1021                         filelist->filelist[1].relname= BLI_strdup("..");
1022                         filelist->filelist[1].type |= S_IFDIR;
1023                 
1024                         files+= 2;
1025                 }
1026                 
1027                 id= lb->first;
1028                 totlib= totbl= 0;
1029                 
1030                 while(id) {
1031                         
1032                         ok= 0;
1033                         if(filelist->has_func && idcode==ID_IP) {
1034                                 if(filelist->ipotype== ((Ipo *)id)->blocktype) ok= 1;
1035                         }
1036                         else ok= 1;
1037                         
1038                         if(ok) {
1039                                 /* TODO: hide dot files - elubie */
1040                                 memset( files, 0 , sizeof(struct direntry));
1041                                 if(id->lib==NULL)
1042                                         files->relname= BLI_strdup(id->name+2);
1043                                 else {
1044                                         files->relname= MEM_mallocN(FILE_MAXDIR+FILE_MAXFILE+32, "filename for lib");
1045                                         sprintf(files->relname, "%s | %s", id->lib->name, id->name+2);
1046                                 }
1047                                 /* files->type |= S_IFDIR; */
1048                                 if(!filelist->has_func) { /* F4 DATA BROWSE */
1049                                         if(idcode==ID_OB) {
1050                                                 if( ((Object *)id)->flag & SELECT) files->flags |= ACTIVE;
1051                                         }
1052                                         else if(idcode==ID_SCE) {
1053                                                 if( ((Scene *)id)->r.scemode & R_BG_RENDER) files->flags |= ACTIVE;
1054                                         }                                       
1055                                 }
1056                                 files->nr= totbl+1;
1057                                 files->poin= id;
1058                                 fake= id->flag & LIB_FAKEUSER;
1059                                 if(idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO || idcode == ID_IM) {
1060                                         files->flags |= IMAGEFILE;
1061                                 }
1062                                 if(id->lib && fake) sprintf(files->extra, "LF %d", id->us);
1063                                 else if(id->lib) sprintf(files->extra, "L    %d", id->us);
1064                                 else if(fake) sprintf(files->extra, "F    %d", id->us);
1065                                 else sprintf(files->extra, "      %d", id->us);
1066                                 
1067                                 if(id->lib) {
1068                                         if(totlib==0) firstlib= files;
1069                                         totlib++;
1070                                 }
1071                                 
1072                                 files++;
1073                                 totbl++;
1074                         }
1075                         
1076                         id= id->next;
1077                 }
1078                 
1079                 /* only qsort of library blocks */
1080                 if(totlib>1) {
1081                         qsort(firstlib, totlib, sizeof(struct direntry), compare_name);
1082                 }
1083         }
1084         filelist->filter = 0;
1085         BIF_filelist_filter(filelist);
1086 }
1087
1088
1089 void BIF_filelist_settype(struct FileList* filelist, int type)
1090 {
1091         filelist->type = type;
1092 }
1093
1094 short BIF_filelist_gettype(struct FileList* filelist)
1095 {
1096         return filelist->type;
1097 }
1098
1099 void BIF_filelist_sort(struct FileList* filelist, short sort)
1100 {
1101         struct direntry *file;
1102         int num;/*  , act= 0; */
1103
1104         switch(sort) {
1105         case FILE_SORTALPHA:
1106                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_name);   
1107                 break;
1108         case FILE_SORTDATE:
1109                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_date);   
1110                 break;
1111         case FILE_SORTSIZE:
1112                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_size);   
1113                 break;
1114         case FILE_SORTEXTENS:
1115                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_extension);      
1116         }
1117
1118         file= filelist->filelist;
1119         for(num=0; num<filelist->numfiles; num++, file++) {
1120                 file->flags &= ~HILITE;
1121         }
1122         BIF_filelist_filter(filelist);
1123 }
1124
1125
1126 void BIF_filelist_setipotype(struct FileList* filelist, short ipotype)
1127 {
1128         filelist->ipotype = ipotype;
1129 }
1130
1131 void BIF_filelist_hasfunc(struct FileList* filelist, int has_func)
1132 {
1133         filelist->has_func = has_func;
1134 }
1135