dbe9417fd2aed6941c268f4b1f92c50ee4bf385a
[blender-staging.git] / source / blender / editors / space_file / filelist.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2007 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30
31 /* global includes */
32
33 #include <stdlib.h>
34 #include <math.h>
35 #include <string.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #ifndef WIN32
42 #include <unistd.h>
43 #else
44 #include <io.h>
45 #include <direct.h>
46 #endif   
47 #include "MEM_guardedalloc.h"
48
49 #include "BLI_blenlib.h"
50 #include "BLI_linklist.h"
51 #include "BLI_storage_types.h"
52 #include "BLI_threads.h"
53
54 #ifdef WIN32
55 #include "BLI_winstuff.h"
56 #endif
57
58 #include "BKE_utildefines.h"
59 #include "BKE_global.h"
60 #include "BKE_library.h"
61 #include "BKE_global.h"
62 #include "BKE_main.h"
63 #include "BKE_report.h"
64 #include "BLO_readfile.h"
65
66 #include "DNA_space_types.h"
67 #include "DNA_ipo_types.h"
68 #include "DNA_ID.h"
69 #include "DNA_object_types.h"
70 #include "DNA_listBase.h"
71 #include "DNA_lamp_types.h"
72 #include "DNA_material_types.h"
73 #include "DNA_texture_types.h"
74 #include "DNA_world_types.h"
75 #include "DNA_scene_types.h"
76 #include "DNA_userdef_types.h"
77
78 #include "ED_datafiles.h"
79
80 #include "IMB_imbuf.h"
81 #include "IMB_imbuf_types.h"
82 #include "IMB_thumbs.h"
83
84 #include "PIL_time.h"
85
86 #include "UI_interface.h"
87
88 #include "filelist.h"
89
90 /* Elubie: VERY, really very ugly and evil! Remove asap!!! */
91 /* for state of file */
92 #define ACTIVE                          2
93
94 /* max length of library group name within filesel */
95 #define GROUP_MAX 32
96
97 static void *exec_loadimages(void *list_v);
98
99 struct FileList;
100
101 typedef struct FileImage {
102         struct FileImage *next, *prev;
103         int index;
104         short lock;
105         short done;
106         struct FileList* filelist;
107 } FileImage;
108
109 typedef struct FileList
110 {
111         struct direntry *filelist;
112         int *fidx;
113         int numfiles;
114         int numfiltered;
115         char dir[FILE_MAX];
116         short prv_w;
117         short prv_h;
118         short hide_dot;
119         unsigned int filter;
120         short changed;
121
122         struct BlendHandle *libfiledata;
123         short hide_parent;
124
125         void (*read)(struct FileList *);
126
127         ListBase loadimages;
128         ListBase threads;
129 } FileList;
130
131 typedef struct FolderList
132 {
133         struct FolderList *next, *prev;
134         char *foldername;
135 } FolderList;
136
137 #define SPECIAL_IMG_SIZE 48
138 #define SPECIAL_IMG_ROWS 4
139 #define SPECIAL_IMG_COLS 4
140
141 #define SPECIAL_IMG_FOLDER 0
142 #define SPECIAL_IMG_PARENT 1
143 #define SPECIAL_IMG_REFRESH 2
144 #define SPECIAL_IMG_BLENDFILE 3
145 #define SPECIAL_IMG_SOUNDFILE 4
146 #define SPECIAL_IMG_MOVIEFILE 5
147 #define SPECIAL_IMG_PYTHONFILE 6
148 #define SPECIAL_IMG_TEXTFILE 7
149 #define SPECIAL_IMG_FONTFILE 8
150 #define SPECIAL_IMG_UNKNOWNFILE 9
151 #define SPECIAL_IMG_LOADING 10
152 #define SPECIAL_IMG_MAX SPECIAL_IMG_LOADING + 1
153
154 static ImBuf* gSpecialFileImages[SPECIAL_IMG_MAX];
155
156
157 /* ******************* SORT ******************* */
158
159 static int compare_name(const void *a1, const void *a2)
160 {
161         const struct direntry *entry1=a1, *entry2=a2;
162
163         /* type is is equal to stat.st_mode */
164
165         if (S_ISDIR(entry1->type)){
166                 if (S_ISDIR(entry2->type)==0) return (-1);
167         } else{
168                 if (S_ISDIR(entry2->type)) return (1);
169         }
170         if (S_ISREG(entry1->type)){
171                 if (S_ISREG(entry2->type)==0) return (-1);
172         } else{
173                 if (S_ISREG(entry2->type)) return (1);
174         }
175         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
176         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
177         
178         /* make sure "." and ".." are always first */
179         if( strcmp(entry1->relname, ".")==0 ) return (-1);
180         if( strcmp(entry2->relname, ".")==0 ) return (1);
181         if( strcmp(entry1->relname, "..")==0 ) return (-1);
182         if( strcmp(entry2->relname, "..")==0 ) return (1);
183         
184         return (BLI_natstrcmp(entry1->relname,entry2->relname));
185 }
186
187 static int compare_date(const void *a1, const void *a2) 
188 {
189         const struct direntry *entry1=a1, *entry2=a2;
190         
191         /* type is equal to stat.st_mode */
192
193         if (S_ISDIR(entry1->type)){
194                 if (S_ISDIR(entry2->type)==0) return (-1);
195         } else{
196                 if (S_ISDIR(entry2->type)) return (1);
197         }
198         if (S_ISREG(entry1->type)){
199                 if (S_ISREG(entry2->type)==0) return (-1);
200         } else{
201                 if (S_ISREG(entry2->type)) return (1);
202         }
203         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
204         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
205
206         /* make sure "." and ".." are always first */
207         if( strcmp(entry1->relname, ".")==0 ) return (-1);
208         if( strcmp(entry2->relname, ".")==0 ) return (1);
209         if( strcmp(entry1->relname, "..")==0 ) return (-1);
210         if( strcmp(entry2->relname, "..")==0 ) return (1);
211         
212         if ( entry1->s.st_mtime < entry2->s.st_mtime) return 1;
213         if ( entry1->s.st_mtime > entry2->s.st_mtime) return -1;
214         
215         else return BLI_natstrcmp(entry1->relname,entry2->relname);
216 }
217
218 static int compare_size(const void *a1, const void *a2) 
219 {
220         const struct direntry *entry1=a1, *entry2=a2;
221
222         /* type is equal to stat.st_mode */
223
224         if (S_ISDIR(entry1->type)){
225                 if (S_ISDIR(entry2->type)==0) return (-1);
226         } else{
227                 if (S_ISDIR(entry2->type)) return (1);
228         }
229         if (S_ISREG(entry1->type)){
230                 if (S_ISREG(entry2->type)==0) return (-1);
231         } else{
232                 if (S_ISREG(entry2->type)) return (1);
233         }
234         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
235         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
236
237         /* make sure "." and ".." are always first */
238         if( strcmp(entry1->relname, ".")==0 ) return (-1);
239         if( strcmp(entry2->relname, ".")==0 ) return (1);
240         if( strcmp(entry1->relname, "..")==0 ) return (-1);
241         if( strcmp(entry2->relname, "..")==0 ) return (1);
242         
243         if ( entry1->s.st_size < entry2->s.st_size) return 1;
244         if ( entry1->s.st_size > entry2->s.st_size) return -1;
245         else return BLI_natstrcmp(entry1->relname,entry2->relname);
246 }
247
248 static int compare_extension(const void *a1, const void *a2) {
249         const struct direntry *entry1=a1, *entry2=a2;
250         char *sufix1, *sufix2;
251         char *nil="";
252
253         if (!(sufix1= strstr (entry1->relname, ".blend.gz"))) 
254                 sufix1= strrchr (entry1->relname, '.');
255         if (!(sufix2= strstr (entry2->relname, ".blend.gz")))
256                 sufix2= strrchr (entry2->relname, '.');
257         if (!sufix1) sufix1= nil;
258         if (!sufix2) sufix2= nil;
259
260         /* type is is equal to stat.st_mode */
261
262         if (S_ISDIR(entry1->type)){
263                 if (S_ISDIR(entry2->type)==0) return (-1);
264         } else{
265                 if (S_ISDIR(entry2->type)) return (1);
266         }
267         if (S_ISREG(entry1->type)){
268                 if (S_ISREG(entry2->type)==0) return (-1);
269         } else{
270                 if (S_ISREG(entry2->type)) return (1);
271         }
272         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
273         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
274         
275         /* make sure "." and ".." are always first */
276         if( strcmp(entry1->relname, ".")==0 ) return (-1);
277         if( strcmp(entry2->relname, ".")==0 ) return (1);
278         if( strcmp(entry1->relname, "..")==0 ) return (-1);
279         if( strcmp(entry2->relname, "..")==0 ) return (1);
280         
281         return (BLI_strcasecmp(sufix1, sufix2));
282 }
283
284 void filelist_filter(FileList* filelist)
285 {
286         /* char dir[FILE_MAX], group[GROUP_MAX]; XXXXX */
287         int num_filtered = 0;
288         int i, j;
289         
290         if (!filelist->filelist)
291                 return;
292         
293         /* XXXXX TODO: check if the filter can be handled outside the filelist 
294         if ( ( (filelist->type == FILE_LOADLIB) &&  BIF_filelist_islibrary(filelist, dir, group)) 
295                 || (filelist->type == FILE_MAIN) ) {
296                 filelist->filter = 0;
297         }
298         */
299
300         if (!filelist->filter) {
301                 if (filelist->fidx) {
302                         MEM_freeN(filelist->fidx);
303                         filelist->fidx = NULL;
304                 }
305                 filelist->fidx = (int *)MEM_callocN(filelist->numfiles*sizeof(int), "filteridx");
306                 for (i = 0; i < filelist->numfiles; ++i) {
307                         filelist->fidx[i] = i;
308                 }
309                 filelist->numfiltered = filelist->numfiles;
310                 return;
311         }
312
313         // How many files are left after filter ?
314         for (i = 0; i < filelist->numfiles; ++i) {
315                 if (filelist->filelist[i].flags & filelist->filter) {
316                         num_filtered++;
317                 } 
318                 else if (filelist->filelist[i].type & S_IFDIR) {
319                         if (filelist->filter & FOLDERFILE) {
320                                 num_filtered++;
321                         }
322                 }               
323         }
324         
325         if (filelist->fidx) {
326                         MEM_freeN(filelist->fidx);
327                         filelist->fidx = NULL;
328         }
329         filelist->fidx = (int *)MEM_callocN(num_filtered*sizeof(int), "filteridx");
330         filelist->numfiltered = num_filtered;
331
332         for (i = 0, j=0; i < filelist->numfiles; ++i) {
333                 if (filelist->filelist[i].flags & filelist->filter) {
334                         filelist->fidx[j++] = i;
335                 }
336                 else if (filelist->filelist[i].type & S_IFDIR) {
337                         if (filelist->filter & FOLDERFILE) {
338                                 filelist->fidx[j++] = i;
339                         }
340                 }  
341         }
342 }
343
344 void filelist_init_icons()
345 {
346         short x, y, k;
347         ImBuf *bbuf;
348         ImBuf *ibuf;
349         bbuf = IMB_ibImageFromMemory((int *)datatoc_prvicons, datatoc_prvicons_size, IB_rect);
350         if (bbuf) {
351                 for (y=0; y<SPECIAL_IMG_ROWS; y++) {
352                         for (x=0; x<SPECIAL_IMG_COLS; x++) {
353                                 int tile = SPECIAL_IMG_COLS*y + x; 
354                                 if (tile < SPECIAL_IMG_MAX) {
355                                         ibuf = IMB_allocImBuf(SPECIAL_IMG_SIZE, SPECIAL_IMG_SIZE, 32, IB_rect, 0);
356                                         for (k=0; k<SPECIAL_IMG_SIZE; k++) {
357                                                 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));
358                                         }
359                                         gSpecialFileImages[tile] = ibuf;
360                                 }
361                         }
362                 }
363                 IMB_freeImBuf(bbuf);
364         }
365 }
366
367 void filelist_free_icons()
368 {
369         int i;
370         for (i=0; i < SPECIAL_IMG_MAX; ++i) {
371                 IMB_freeImBuf(gSpecialFileImages[i]);
372                 gSpecialFileImages[i] = NULL;
373         }
374 }
375
376 //-----------------FOLDERLIST (previous/next) --------------//
377 struct ListBase* folderlist_new()
378 {
379         ListBase* p = MEM_callocN( sizeof(ListBase), "folderlist" );
380         return p;
381 }
382
383 void folderlist_popdir(struct ListBase* folderlist, char *dir)
384 {
385         const char *prev_dir;
386         struct FolderList *folder;
387         folder = folderlist->last;
388
389         if(folder){
390                 // remove the current directory
391                 MEM_freeN(folder->foldername);
392                 BLI_freelinkN(folderlist, folder);
393
394                 folder = folderlist->last;
395                 if(folder){
396                         prev_dir = folder->foldername;
397                         BLI_strncpy(dir, prev_dir, FILE_MAXDIR);
398                 }
399         }
400         // delete the folder next or use setdir directly before PREVIOUS OP
401 }
402
403 void folderlist_pushdir(ListBase* folderlist, const char *dir)
404 {
405         struct FolderList *folder, *previous_folder;
406         previous_folder = folderlist->last;
407
408         // check if already exists
409         if(previous_folder && previous_folder->foldername){
410                 if(! strcmp(previous_folder->foldername, dir)){
411                         return;
412                 }
413         }
414
415         // create next folder element
416         folder = (FolderList*)MEM_mallocN(sizeof(FolderList),"FolderList");
417         folder->foldername = (char*)MEM_mallocN(sizeof(char)*(strlen(dir)+1), "foldername");
418         folder->foldername[0] = '\0';
419
420         BLI_strncpy(folder->foldername, dir, FILE_MAXDIR);
421
422         // add it to the end of the list
423         BLI_addtail(folderlist, folder);
424 }
425
426 int folderlist_clear_next(struct SpaceFile *sfile)
427 {
428         struct FolderList *folder;
429
430         // if there is no folder_next there is nothing we can clear
431         if (!sfile->folders_next)
432                 return 0;
433
434         // if previous_folder, next_folder or refresh_folder operators are executed it doesn't clear folder_next
435         folder = sfile->folders_prev->last;
436         if ((!folder) ||(!strcmp(folder->foldername, sfile->params->dir)))
437                 return 0;
438
439         // eventually clear flist->folders_next
440         return 1;
441 }
442
443 /* not listbase itself */
444 void folderlist_free(ListBase* folderlist)
445 {
446         FolderList *folder;
447         if (folderlist){
448                 for(folder= folderlist->first; folder; folder= folder->next)
449                         MEM_freeN(folder->foldername);
450                 BLI_freelistN(folderlist);
451         }
452         folderlist= NULL;
453 }
454
455 ListBase *folderlist_duplicate(ListBase* folderlist)
456 {
457         
458         if (folderlist) {
459                 ListBase *folderlistn= MEM_callocN(sizeof(ListBase), "copy folderlist");
460                 FolderList *folder;
461                 
462                 BLI_duplicatelist(folderlistn, folderlist);
463                 
464                 for(folder= folderlistn->first; folder; folder= folder->next) {
465                         folder->foldername= MEM_dupallocN(folder->foldername);
466                 }
467                 return folderlistn;
468         }
469         return NULL;
470 }
471
472
473 static void filelist_read_main(struct FileList* filelist);
474 static void filelist_read_library(struct FileList* filelist);
475 static void filelist_read_dir(struct FileList* filelist);
476
477 //------------------FILELIST------------------------//
478 struct FileList*        filelist_new(short type)
479 {
480         FileList* p = MEM_callocN( sizeof(FileList), "filelist" );
481         switch(type) {
482                 case FILE_MAIN:
483                         p->read = filelist_read_main;
484                         break;
485                 case FILE_LOADLIB:
486                         p->read = filelist_read_library;
487                         break;
488                 default:
489                         p->read = filelist_read_dir;
490
491         }
492         return p;
493 }
494
495
496 void filelist_free(struct FileList* filelist)
497 {
498         int i;
499
500         if (!filelist) {
501                 printf("Attempting to delete empty filelist.\n");
502                 return;
503         }
504
505         BLI_end_threads(&filelist->threads);
506         BLI_freelistN(&filelist->loadimages);
507         
508         if (filelist->fidx) {
509                 MEM_freeN(filelist->fidx);
510                 filelist->fidx = NULL;
511         }
512
513         for (i = 0; i < filelist->numfiles; ++i) {
514                 if (filelist->filelist[i].image) {                      
515                         IMB_freeImBuf(filelist->filelist[i].image);
516                 }
517                 filelist->filelist[i].image = 0;
518                 if (filelist->filelist[i].relname)
519                         MEM_freeN(filelist->filelist[i].relname);
520                 if (filelist->filelist[i].path)
521                         MEM_freeN(filelist->filelist[i].path);
522                 filelist->filelist[i].relname = 0;
523                 if (filelist->filelist[i].string)
524                         MEM_freeN(filelist->filelist[i].string);
525                 filelist->filelist[i].string = 0;
526         }
527         
528         filelist->numfiles = 0;
529         free(filelist->filelist);
530         filelist->filelist = 0; 
531         filelist->filter = 0;
532         filelist->numfiltered =0;
533         filelist->hide_dot =0;
534 }
535
536 void filelist_freelib(struct FileList* filelist)
537 {
538         if(filelist->libfiledata)       
539                 BLO_blendhandle_close(filelist->libfiledata);
540         filelist->libfiledata= 0;
541 }
542
543 struct BlendHandle *filelist_lib(struct FileList* filelist)
544 {
545         return filelist->libfiledata;
546 }
547
548 int     filelist_numfiles(struct FileList* filelist)
549 {
550         return filelist->numfiltered;
551 }
552
553 const char * filelist_dir(struct FileList* filelist)
554 {
555         return filelist->dir;
556 }
557
558 void filelist_setdir(struct FileList* filelist, const char *dir)
559 {
560         BLI_strncpy(filelist->dir, dir, FILE_MAX);
561 }
562
563 void filelist_imgsize(struct FileList* filelist, short w, short h)
564 {
565         filelist->prv_w = w;
566         filelist->prv_h = h;
567 }
568
569
570 static void *exec_loadimages(void *list_v)
571 {
572         FileImage* img = (FileImage*)list_v;
573         struct FileList *filelist = img->filelist;
574
575         ImBuf *imb = NULL;
576         int fidx = img->index;
577         
578         if ( filelist->filelist[fidx].flags & IMAGEFILE ) {                             
579                 imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_IMAGE);
580         } else if ( filelist->filelist[fidx].flags & MOVIEFILE ) {                              
581                 imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_MOVIE);
582                 if (!imb) {
583                         /* remember that file can't be loaded via IMB_open_anim */
584                         filelist->filelist[fidx].flags &= ~MOVIEFILE;
585                         filelist->filelist[fidx].flags |= MOVIEFILE_ICON;
586                 }
587         }
588         if (imb) {
589                 IMB_freeImBuf(imb);
590         }
591         img->done=1;
592         return 0;
593 }
594
595 short filelist_changed(struct FileList* filelist)
596 {
597         return filelist->changed;
598 }
599
600 void filelist_loadimage_timer(struct FileList* filelist)
601 {
602         FileImage *limg = filelist->loadimages.first;
603         short refresh=0;
604
605         // as long as threads are available and there is work to do
606         while (limg) {
607                 if (BLI_available_threads(&filelist->threads)>0) {
608                         if (!limg->lock) {
609                                 limg->lock=1;
610                                 BLI_insert_thread(&filelist->threads, limg);
611                         }
612                 }
613                 if (limg->done) {
614                         FileImage *oimg = limg;
615                         BLI_remove_thread(&filelist->threads, oimg);
616                         /* brecht: keep failed images in the list, otherwise
617                            it keeps trying to load them over and over?
618                         BLI_remlink(&filelist->loadimages, oimg);
619                         MEM_freeN(oimg);*/
620                         limg = oimg->next;
621                         refresh = 1;
622                 } else {
623                         limg= limg->next;
624                 }
625         }
626         filelist->changed=refresh;
627 }
628
629 void filelist_loadimage(struct FileList* filelist, int index)
630 {
631         ImBuf *imb = NULL;
632         int imgwidth = filelist->prv_w;
633         int imgheight = filelist->prv_h;
634         short ex, ey, dx, dy;
635         float scaledx, scaledy;
636         int fidx = 0;
637         
638         if ( (index < 0) || (index >= filelist->numfiltered) ) {
639                 return;
640         }
641         fidx = filelist->fidx[index];
642
643         if (!filelist->filelist[fidx].image)
644         {
645
646                 if ( (filelist->filelist[fidx].flags & IMAGEFILE) || (filelist->filelist[fidx].flags & MOVIEFILE) ) {                           
647                         imb = IMB_thumb_read(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL);
648                 } 
649                 if (imb) {
650                         if (imb->x > imb->y) {
651                                 scaledx = (float)imgwidth;
652                                 scaledy =  ( (float)imb->y/(float)imb->x )*imgwidth;
653                         }
654                         else {
655                                 scaledy = (float)imgheight;
656                                 scaledx =  ( (float)imb->x/(float)imb->y )*imgheight;
657                         }
658                         ex = (short)scaledx;
659                         ey = (short)scaledy;
660                         
661                         dx = imgwidth - ex;
662                         dy = imgheight - ey;
663                         
664                         // IMB_scaleImBuf(imb, ex, ey);
665                         filelist->filelist[fidx].image = imb;
666                 } else {
667                         /* prevent loading image twice */
668                         FileImage* limg = filelist->loadimages.first;
669                         short found= 0;
670                         while(limg) {
671                                 if (limg->index == fidx) {
672                                         found= 1;
673                                         break;
674                                 }
675                                 limg= limg->next;
676                         }
677                         if (!found) {
678                                 FileImage* limg = MEM_callocN(sizeof(struct FileImage), "loadimage");
679                                 limg->index= fidx;
680                                 limg->lock= 0;
681                                 limg->filelist= filelist;
682                                 BLI_addtail(&filelist->loadimages, limg);
683                         }
684                 }               
685         }
686 }
687
688 struct ImBuf * filelist_getimage(struct FileList* filelist, int index)
689 {
690         ImBuf* ibuf = NULL;
691         int fidx = 0;   
692         if ( (index < 0) || (index >= filelist->numfiltered) ) {
693                 return NULL;
694         }
695         fidx = filelist->fidx[index];
696         ibuf = filelist->filelist[fidx].image;
697
698         return ibuf;
699 }
700
701 struct ImBuf * filelist_geticon(struct FileList* filelist, int index)
702 {
703         ImBuf* ibuf= NULL;
704         struct direntry *file= NULL;
705         int fidx = 0;   
706         if ( (index < 0) || (index >= filelist->numfiltered) ) {
707                 return NULL;
708         }
709         fidx = filelist->fidx[index];
710         file = &filelist->filelist[fidx];
711         if (file->type & S_IFDIR) {
712                         if ( strcmp(filelist->filelist[fidx].relname, "..") == 0) {
713                                 ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
714                         } else if  ( strcmp(filelist->filelist[fidx].relname, ".") == 0) {
715                                 ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
716                         } else {
717                 ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
718                         }
719         } else {
720                 ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
721         }
722
723         if (file->flags & BLENDERFILE) {
724                 ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
725         } else if ( (file->flags & MOVIEFILE) || (file->flags & MOVIEFILE_ICON) ) {
726                 ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
727         } else if (file->flags & SOUNDFILE) {
728                 ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
729         } else if (file->flags & PYSCRIPTFILE) {
730                 ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
731         } else if (file->flags & FTFONTFILE) {
732                 ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
733         } else if (file->flags & TEXTFILE) {
734                 ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
735         } else if (file->flags & IMAGEFILE) {
736                 ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING];
737         }
738
739         return ibuf;
740 }
741
742 struct direntry * filelist_file(struct FileList* filelist, int index)
743 {
744         int fidx = 0;
745         
746         if ( (index < 0) || (index >= filelist->numfiltered) ) {
747                 return NULL;
748         }
749         fidx = filelist->fidx[index];
750
751         return &filelist->filelist[fidx];
752 }
753
754 int filelist_find(struct FileList* filelist, char *file)
755 {
756         int index = -1;
757         int i;
758         int fidx = -1;
759         
760         if (!filelist->fidx) 
761                 return fidx;
762
763         
764         for (i = 0; i < filelist->numfiles; ++i) {
765                 if ( strcmp(filelist->filelist[i].relname, file) == 0) {
766                         index = i;
767                         break;
768                 }
769         }
770
771         for (i = 0; i < filelist->numfiltered; ++i) {
772                 if (filelist->fidx[i] == index) {
773                         fidx = i;
774                         break;
775                 }
776         }
777         return fidx;
778 }
779
780 void filelist_hidedot(struct FileList* filelist, short hide)
781 {
782         filelist->hide_dot = hide;
783 }
784
785 void filelist_setfilter(struct FileList* filelist, unsigned int filter)
786 {
787         filelist->filter = filter;
788 }
789
790 static void filelist_read_dir(struct FileList* filelist)
791 {
792         char wdir[FILE_MAX];
793         if (!filelist) return;
794
795         filelist->fidx = 0;
796         filelist->filelist = 0;
797
798         BLI_getwdN(wdir);        
799
800         BLI_cleanup_dir(G.sce, filelist->dir);
801         BLI_hide_dot_files(filelist->hide_dot);
802         filelist->numfiles = BLI_getdir(filelist->dir, &(filelist->filelist));
803
804         chdir(wdir);
805         filelist_setfiletypes(filelist, G.have_quicktime);
806         filelist_filter(filelist);
807
808         if (!filelist->threads.first) {
809                 BLI_init_threads(&filelist->threads, exec_loadimages, 2);
810         }
811 }
812
813 static void filelist_read_main(struct FileList* filelist)
814 {
815         if (!filelist) return;
816         filelist_from_main(filelist);
817 }
818
819 static void filelist_read_library(struct FileList* filelist)
820 {
821         if (!filelist) return;
822         BLI_cleanup_dir(G.sce, filelist->dir);
823         filelist_from_library(filelist);
824         if(!filelist->libfiledata) {
825                 int num;
826                 struct direntry *file;
827
828                 BLI_make_exist(filelist->dir);
829                 filelist_read_dir(filelist);
830                 file = filelist->filelist;
831                 for(num=0; num<filelist->numfiles; num++, file++) {
832                         if(BLO_has_bfile_extension(file->relname)) {
833                                 char name[FILE_MAXDIR+FILE_MAXFILE];
834                         
835                                 BLI_strncpy(name, filelist->dir, sizeof(name));
836                                 strcat(name, file->relname);
837                                 
838                                 /* prevent current file being used as acceptable dir */
839                                 if (BLI_streq(G.main->name, name)==0) {
840                                         file->type &= ~S_IFMT;
841                                         file->type |= S_IFDIR;
842                                 }
843                         }
844                 }
845         }
846 }
847
848 void filelist_readdir(struct FileList* filelist)
849 {
850         filelist->read(filelist);
851 }
852
853 int filelist_empty(struct FileList* filelist)
854 {       
855         return filelist->filelist == 0;
856 }
857
858 void filelist_parent(struct FileList* filelist)
859 {
860         BLI_parent_dir(filelist->dir);
861         BLI_make_exist(filelist->dir);
862         filelist_readdir(filelist);
863 }
864
865 void filelist_setfiletypes(struct FileList* filelist, short has_quicktime)
866 {
867         struct direntry *file;
868         int num;
869
870         file= filelist->filelist;
871
872         for(num=0; num<filelist->numfiles; num++, file++) {
873                 file->flags= 0;
874                 file->type= file->s.st_mode;    /* restore the mess below */ 
875
876                         /* Don't check extensions for directories */ 
877                 if (file->type & S_IFDIR)
878                         continue;
879                                 
880                 
881                 
882                 if(BLO_has_bfile_extension(file->relname)) {
883                         file->flags |= BLENDERFILE;
884                 } else if(BLI_testextensie(file->relname, ".py")) {
885                                 file->flags |= PYSCRIPTFILE;
886                 } else if(BLI_testextensie(file->relname, ".txt")
887                                         || BLI_testextensie(file->relname, ".glsl")
888                                         || BLI_testextensie(file->relname, ".data")) {
889                                 file->flags |= TEXTFILE;
890                 } else if( BLI_testextensie(file->relname, ".ttf")
891                                         || BLI_testextensie(file->relname, ".ttc")
892                                         || BLI_testextensie(file->relname, ".pfb")
893                                         || BLI_testextensie(file->relname, ".otf")
894                                         || BLI_testextensie(file->relname, ".otc")) {
895                                 file->flags |= FTFONTFILE;                      
896                 } else if(BLI_testextensie(file->relname, ".btx")) {
897                                 file->flags |= BTXFILE;
898                 } else if (has_quicktime){
899                         if(             BLI_testextensie(file->relname, ".int")
900                                 ||  BLI_testextensie(file->relname, ".inta")
901                                 ||  BLI_testextensie(file->relname, ".jpg")
902 #ifdef WITH_OPENJPEG
903                                 ||  BLI_testextensie(file->relname, ".jp2")
904 #endif
905                                 ||      BLI_testextensie(file->relname, ".jpeg")
906                                 ||      BLI_testextensie(file->relname, ".tga")
907                                 ||      BLI_testextensie(file->relname, ".rgb")
908                                 ||      BLI_testextensie(file->relname, ".rgba")
909                                 ||      BLI_testextensie(file->relname, ".bmp")
910                                 ||      BLI_testextensie(file->relname, ".png")
911                                 ||      BLI_testextensie(file->relname, ".iff")
912                                 ||      BLI_testextensie(file->relname, ".lbm")
913                                 ||      BLI_testextensie(file->relname, ".gif")
914                                 ||      BLI_testextensie(file->relname, ".psd")
915                                 ||      BLI_testextensie(file->relname, ".tif")
916                                 ||      BLI_testextensie(file->relname, ".tiff")
917                                 ||      BLI_testextensie(file->relname, ".pct")
918                                 ||      BLI_testextensie(file->relname, ".pict")
919                                 ||      BLI_testextensie(file->relname, ".pntg") //macpaint
920                                 ||      BLI_testextensie(file->relname, ".qtif")
921                                 ||      BLI_testextensie(file->relname, ".sgi")
922                                 ||      BLI_testextensie(file->relname, ".hdr")
923 #ifdef WITH_DDS
924                                 ||      BLI_testextensie(file->relname, ".dds")
925 #endif
926 #ifdef WITH_OPENEXR
927                                 ||      BLI_testextensie(file->relname, ".exr")
928 #endif
929                             ) {
930                                 file->flags |= IMAGEFILE;                       
931                         }
932                         else if(BLI_testextensie(file->relname, ".avi")
933                                 ||      BLI_testextensie(file->relname, ".flc")
934                                 ||      BLI_testextensie(file->relname, ".mov")
935                                 ||      BLI_testextensie(file->relname, ".movie")
936                                 ||      BLI_testextensie(file->relname, ".mp4")
937                                 ||      BLI_testextensie(file->relname, ".m4v")
938                                 ||      BLI_testextensie(file->relname, ".mv")
939                                 ||      BLI_testextensie(file->relname, ".wmv")
940                                 ||      BLI_testextensie(file->relname, ".ogv")
941                                 ||      BLI_testextensie(file->relname, ".mpeg")
942                                 ||      BLI_testextensie(file->relname, ".mpg")
943                                 ||      BLI_testextensie(file->relname, ".mpg2")
944                                 ||      BLI_testextensie(file->relname, ".vob")
945                                 ||      BLI_testextensie(file->relname, ".mkv")
946                                 ||      BLI_testextensie(file->relname, ".flv")
947                                 ||      BLI_testextensie(file->relname, ".divx")
948                                 ||      BLI_testextensie(file->relname, ".xvid")) {
949                                 file->flags |= MOVIEFILE;                       
950                         }
951                         else if(BLI_testextensie(file->relname, ".wav")
952                                 ||      BLI_testextensie(file->relname, ".ogg")
953                                 ||      BLI_testextensie(file->relname, ".oga")
954                                 ||      BLI_testextensie(file->relname, ".mp3")
955                                 ||      BLI_testextensie(file->relname, ".mp2")
956                                 ||      BLI_testextensie(file->relname, ".ac3")
957                                 ||      BLI_testextensie(file->relname, ".aac")
958                                 ||      BLI_testextensie(file->relname, ".flac")
959                                 ||      BLI_testextensie(file->relname, ".wma")
960                                 ||      BLI_testextensie(file->relname, ".eac3")) {
961                                 file->flags |= SOUNDFILE;
962                         }
963                 } else { // no quicktime
964                         if(BLI_testextensie(file->relname, ".int")
965                                 ||      BLI_testextensie(file->relname, ".inta")
966                                 ||      BLI_testextensie(file->relname, ".jpg")
967                                 ||  BLI_testextensie(file->relname, ".jpeg")
968 #ifdef WITH_OPENJPEG
969                                 ||  BLI_testextensie(file->relname, ".jp2")
970 #endif
971                                 ||      BLI_testextensie(file->relname, ".tga")
972                                 ||      BLI_testextensie(file->relname, ".rgb")
973                                 ||      BLI_testextensie(file->relname, ".rgba")
974                                 ||      BLI_testextensie(file->relname, ".bmp")
975                                 ||      BLI_testextensie(file->relname, ".png")
976                                 ||      BLI_testextensie(file->relname, ".iff")
977                                 ||      BLI_testextensie(file->relname, ".tif")
978                                 ||      BLI_testextensie(file->relname, ".tiff")
979                                 ||      BLI_testextensie(file->relname, ".hdr")
980 #ifdef WITH_DDS
981                                 ||      BLI_testextensie(file->relname, ".dds")
982 #endif
983 #ifdef WITH_OPENEXR
984                                 ||      BLI_testextensie(file->relname, ".exr")
985 #endif
986                                 ||      BLI_testextensie(file->relname, ".lbm")
987                                 ||      BLI_testextensie(file->relname, ".sgi")) {
988                                 file->flags |= IMAGEFILE;                       
989                         }
990                         else if(BLI_testextensie(file->relname, ".avi")
991                                 ||      BLI_testextensie(file->relname, ".flc")
992                                 ||      BLI_testextensie(file->relname, ".mov")
993                                 ||      BLI_testextensie(file->relname, ".movie")
994                                 ||      BLI_testextensie(file->relname, ".mp4")
995                                 ||      BLI_testextensie(file->relname, ".m4v")
996                                 ||      BLI_testextensie(file->relname, ".mv")
997                                 ||      BLI_testextensie(file->relname, ".wmv")
998                                 ||      BLI_testextensie(file->relname, ".ogv")
999                                 ||      BLI_testextensie(file->relname, ".mpeg")
1000                                 ||      BLI_testextensie(file->relname, ".mpg")
1001                                 ||      BLI_testextensie(file->relname, ".mpg2")
1002                                 ||      BLI_testextensie(file->relname, ".vob")
1003                                 ||      BLI_testextensie(file->relname, ".mkv")
1004                                 ||      BLI_testextensie(file->relname, ".flv")
1005                                 ||      BLI_testextensie(file->relname, ".divx")
1006                                 ||      BLI_testextensie(file->relname, ".xvid")) {
1007                                 file->flags |= MOVIEFILE;                       
1008                         }
1009                         else if(BLI_testextensie(file->relname, ".wav")
1010                                 ||      BLI_testextensie(file->relname, ".ogg")
1011                                 ||      BLI_testextensie(file->relname, ".oga")
1012                                 ||      BLI_testextensie(file->relname, ".mp3")
1013                                 ||      BLI_testextensie(file->relname, ".mp2")
1014                                 ||      BLI_testextensie(file->relname, ".ac3")
1015                                 ||      BLI_testextensie(file->relname, ".aac")
1016                                 ||      BLI_testextensie(file->relname, ".flac")
1017                                 ||      BLI_testextensie(file->relname, ".wma")
1018                                 ||      BLI_testextensie(file->relname, ".eac3")) {
1019                                 file->flags |= SOUNDFILE;
1020                         }
1021                 }
1022         }
1023 }
1024
1025 void filelist_swapselect(struct FileList* filelist)
1026 {
1027         struct direntry *file;
1028         int num, act= 0;
1029         
1030         file= filelist->filelist;
1031         for(num=0; num<filelist->numfiles; num++, file++) {
1032                 if(file->flags & ACTIVE) {
1033                         act= 1;
1034                         break;
1035                 }
1036         }
1037         file= filelist->filelist+2;
1038         for(num=2; num<filelist->numfiles; num++, file++) {
1039                 if(act) file->flags &= ~ACTIVE;
1040                 else file->flags |= ACTIVE;
1041         }
1042 }
1043
1044 void filelist_sort(struct FileList* filelist, short sort)
1045 {
1046         switch(sort) {
1047         case FILE_SORT_ALPHA:
1048                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_name);   
1049                 break;
1050         case FILE_SORT_TIME:
1051                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_date);   
1052                 break;
1053         case FILE_SORT_SIZE:
1054                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_size);   
1055                 break;
1056         case FILE_SORT_EXTENSION:
1057                 qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_extension);      
1058         }
1059
1060         filelist_filter(filelist);
1061 }
1062
1063
1064 int filelist_islibrary(struct FileList* filelist, char* dir, char* group)
1065 {
1066         return BLO_is_a_library(filelist->dir, dir, group);
1067 }
1068
1069 static int groupname_to_code(char *group)
1070 {
1071         char buf[32];
1072         char *lslash;
1073         
1074         BLI_strncpy(buf, group, 31);
1075         lslash= BLI_last_slash(buf);
1076         if (lslash)
1077                 lslash[0]= '\0';
1078
1079         return BLO_idcode_from_name(buf);
1080 }
1081
1082 void filelist_from_library(struct FileList* filelist)
1083 {
1084         LinkNode *l, *names, *previews;
1085         struct ImBuf* ima;
1086         int ok, i, nnames, idcode;
1087         char filename[FILE_MAXDIR+FILE_MAXFILE];
1088         char dir[FILE_MAX], group[GROUP_MAX];   
1089         
1090         /* name test */
1091         ok= filelist_islibrary(filelist, dir, group);
1092         if (!ok) {
1093                 /* free */
1094                 if(filelist->libfiledata) BLO_blendhandle_close(filelist->libfiledata);
1095                 filelist->libfiledata= 0;
1096                 return;
1097         }
1098         
1099         BLI_strncpy(filename, G.sce, sizeof(filename)); // G.sce = last file loaded, for UI
1100
1101         /* there we go */
1102         /* for the time being only read filedata when libfiledata==0 */
1103         if (filelist->libfiledata==0) {
1104                 filelist->libfiledata= BLO_blendhandle_from_file(dir);
1105                 if(filelist->libfiledata==0) return;
1106         }
1107         
1108         idcode= groupname_to_code(group);
1109
1110                 // memory for strings is passed into filelist[i].relname
1111                 // and free'd in freefilelist
1112         previews = NULL;
1113         if (idcode) {
1114                 previews= BLO_blendhandle_get_previews(filelist->libfiledata, idcode);
1115                 names= BLO_blendhandle_get_datablock_names(filelist->libfiledata, idcode);
1116                 /* ugh, no rewind, need to reopen */
1117                 BLO_blendhandle_close(filelist->libfiledata);
1118                 filelist->libfiledata= BLO_blendhandle_from_file(dir);
1119                 
1120         } else {
1121                 names= BLO_blendhandle_get_linkable_groups(filelist->libfiledata);
1122         }
1123         
1124         nnames= BLI_linklist_length(names);
1125
1126         filelist->numfiles= nnames + 1;
1127         filelist->filelist= malloc(filelist->numfiles * sizeof(*filelist->filelist));
1128         memset(filelist->filelist, 0, filelist->numfiles * sizeof(*filelist->filelist));
1129
1130         filelist->filelist[0].relname= BLI_strdup("..");
1131         filelist->filelist[0].type |= S_IFDIR;
1132                 
1133         for (i=0, l= names; i<nnames; i++, l= l->next) {
1134                 char *blockname= l->link;
1135
1136                 filelist->filelist[i + 1].relname= BLI_strdup(blockname);
1137                 if (!idcode)
1138                         filelist->filelist[i + 1].type |= S_IFDIR;
1139         }
1140         
1141         if(previews) {
1142                 for (i=0, l= previews; i<nnames; i++, l= l->next) {
1143                         PreviewImage *img= l->link;
1144                         
1145                         if (img) {
1146                                 unsigned int w = img->w[PREVIEW_MIPMAP_LARGE];
1147                                 unsigned int h = img->h[PREVIEW_MIPMAP_LARGE];
1148                                 unsigned int *rect = img->rect[PREVIEW_MIPMAP_LARGE];
1149
1150                                 /* first allocate imbuf for copying preview into it */
1151                                 if (w > 0 && h > 0 && rect) {
1152                                         ima = IMB_allocImBuf(w, h, 32, IB_rect, 0);
1153                                         memcpy(ima->rect, rect, w*h*sizeof(unsigned int));
1154                                         filelist->filelist[i + 1].image = ima;
1155                                         filelist->filelist[i + 1].flags = IMAGEFILE;
1156                                 }
1157                         }
1158                 }
1159         }
1160
1161         BLI_linklist_free(names, free);
1162         if (previews) BLI_linklist_free(previews, (void(*)(void*)) MEM_freeN);
1163
1164         filelist_sort(filelist, FILE_SORT_ALPHA);
1165
1166         BLI_strncpy(G.sce, filename, sizeof(filename)); // prevent G.sce to change
1167
1168         filelist->filter = 0;
1169         filelist_filter(filelist);
1170 }
1171
1172 void filelist_hideparent(struct FileList* filelist, short hide)
1173 {
1174         filelist->hide_parent = hide;
1175 }
1176
1177 void filelist_from_main(struct FileList *filelist)
1178 {
1179         ID *id;
1180         struct direntry *files, *firstlib = NULL;
1181         ListBase *lb;
1182         int a, fake, idcode, ok, totlib, totbl;
1183         
1184         // filelist->type = FILE_MAIN; // XXXXX TODO: add modes to filebrowser
1185
1186         if(filelist->dir[0]=='/') filelist->dir[0]= 0;
1187         
1188         if(filelist->dir[0]) {
1189                 idcode= groupname_to_code(filelist->dir);
1190                 if(idcode==0) filelist->dir[0]= 0;
1191         }
1192         
1193         if( filelist->dir[0]==0) {
1194                 
1195                 /* make directories */
1196                 filelist->numfiles= 23;
1197                 filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry));
1198                 
1199                 for(a=0; a<filelist->numfiles; a++) {
1200                         memset( &(filelist->filelist[a]), 0 , sizeof(struct direntry));
1201                         filelist->filelist[a].type |= S_IFDIR;
1202                 }
1203                 
1204                 filelist->filelist[0].relname= BLI_strdup("..");
1205                 filelist->filelist[2].relname= BLI_strdup("Scene");
1206                 filelist->filelist[3].relname= BLI_strdup("Object");
1207                 filelist->filelist[4].relname= BLI_strdup("Mesh");
1208                 filelist->filelist[5].relname= BLI_strdup("Curve");
1209                 filelist->filelist[6].relname= BLI_strdup("Metaball");
1210                 filelist->filelist[7].relname= BLI_strdup("Material");
1211                 filelist->filelist[8].relname= BLI_strdup("Texture");
1212                 filelist->filelist[9].relname= BLI_strdup("Image");
1213                 filelist->filelist[10].relname= BLI_strdup("Ika");
1214                 filelist->filelist[11].relname= BLI_strdup("Wave");
1215                 filelist->filelist[12].relname= BLI_strdup("Lattice");
1216                 filelist->filelist[13].relname= BLI_strdup("Lamp");
1217                 filelist->filelist[14].relname= BLI_strdup("Camera");
1218                 filelist->filelist[15].relname= BLI_strdup("Ipo");
1219                 filelist->filelist[16].relname= BLI_strdup("World");
1220                 filelist->filelist[17].relname= BLI_strdup("Screen");
1221                 filelist->filelist[18].relname= BLI_strdup("VFont");
1222                 filelist->filelist[19].relname= BLI_strdup("Text");
1223                 filelist->filelist[20].relname= BLI_strdup("Armature");
1224                 filelist->filelist[21].relname= BLI_strdup("Action");
1225                 filelist->filelist[22].relname= BLI_strdup("NodeTree");
1226                 filelist_sort(filelist, FILE_SORT_ALPHA);
1227         }
1228         else {
1229
1230                 /* make files */
1231                 idcode= groupname_to_code(filelist->dir);
1232                 
1233                 lb= wich_libbase(G.main, idcode );
1234                 if(lb==0) return;
1235                 
1236                 id= lb->first;
1237                 filelist->numfiles= 0;
1238                 while(id) {
1239                         if (!filelist->hide_dot || id->name[2] != '.') {
1240                                 filelist->numfiles++;
1241                         }
1242                         
1243                         id= id->next;
1244                 }
1245                 
1246                 /* XXXXX TODO: if databrowse F4 or append/link filelist->hide_parent has to be set */
1247                 if (!filelist->hide_parent) filelist->numfiles+= 1;
1248                 filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry));
1249                 
1250                 files = filelist->filelist;
1251                 
1252                 if (!filelist->hide_parent) {
1253                         memset( &(filelist->filelist[0]), 0 , sizeof(struct direntry));
1254                         filelist->filelist[0].relname= BLI_strdup("..");
1255                         filelist->filelist[0].type |= S_IFDIR;
1256                 
1257                         files++;
1258                 }
1259                 
1260                 id= lb->first;
1261                 totlib= totbl= 0;
1262                 
1263                 while(id) {
1264                         ok = 1;
1265                         if(ok) {
1266                                 if (!filelist->hide_dot || id->name[2] != '.') {
1267                                         memset( files, 0 , sizeof(struct direntry));
1268                                         if(id->lib==NULL)
1269                                                 files->relname= BLI_strdup(id->name+2);
1270                                         else {
1271                                                 files->relname= MEM_mallocN(FILE_MAXDIR+FILE_MAXFILE+32, "filename for lib");
1272                                                 sprintf(files->relname, "%s | %s", id->lib->name, id->name+2);
1273                                         }
1274                                         /* files->type |= S_IFDIR; */
1275 #if 0                           // XXXXX TODO show the selection status of the objects
1276                                         if(!filelist->has_func) { /* F4 DATA BROWSE */
1277                                                 if(idcode==ID_OB) {
1278                                                         if( ((Object *)id)->flag & SELECT) files->flags |= ACTIVE;
1279                                                 }
1280                                                 else if(idcode==ID_SCE) {
1281                                                         if( ((Scene *)id)->r.scemode & R_BG_RENDER) files->flags |= ACTIVE;
1282                                                 }                                       
1283                                         }
1284 #endif
1285                                         files->nr= totbl+1;
1286                                         files->poin= id;
1287                                         fake= id->flag & LIB_FAKEUSER;
1288                                         if(idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO || idcode == ID_IM) {
1289                                                 files->flags |= IMAGEFILE;
1290                                         }
1291                                         if(id->lib && fake) sprintf(files->extra, "LF %d", id->us);
1292                                         else if(id->lib) sprintf(files->extra, "L    %d", id->us);
1293                                         else if(fake) sprintf(files->extra, "F    %d", id->us);
1294                                         else sprintf(files->extra, "      %d", id->us);
1295                                         
1296                                         if(id->lib) {
1297                                                 if(totlib==0) firstlib= files;
1298                                                 totlib++;
1299                                         }
1300                                         
1301                                         files++;
1302                                 }
1303                                 totbl++;
1304                         }
1305                         
1306                         id= id->next;
1307                 }
1308                 
1309                 /* only qsort of library blocks */
1310                 if(totlib>1) {
1311                         qsort(firstlib, totlib, sizeof(struct direntry), compare_name);
1312                 }
1313         }
1314         filelist->filter = 0;
1315         filelist_filter(filelist);
1316 }
1317