added mousewheel support
[blender.git] / source / blender / src / filesel.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #ifdef WIN32
42 #include <io.h>
43 #include <direct.h>
44 #include "BLI_winstuff.h"
45 #else
46 #include <unistd.h>
47 #include <sys/times.h>
48 #endif   
49
50 #include <sys/stat.h>
51 #include <sys/types.h>
52 #include "MEM_guardedalloc.h"
53
54 #include "BMF_Api.h"
55
56 #include "BLI_blenlib.h"
57 #include "BLI_arithb.h"
58 #include "BLI_editVert.h"
59 #include "BLI_linklist.h"
60 #include "BLI_storage_types.h"
61 #include "BLI_dynstr.h"
62
63 #include "IMB_imbuf.h"
64
65 #include "DNA_curve_types.h"
66 #include "DNA_image_types.h"
67 #include "DNA_ipo_types.h"
68 #include "DNA_vfont_types.h"
69 #include "DNA_mesh_types.h"
70 #include "DNA_object_types.h"
71 #include "DNA_texture_types.h"
72 #include "DNA_space_types.h"
73 #include "DNA_scene_types.h"
74 #include "DNA_screen_types.h"
75 #include "DNA_view3d_types.h"
76 #include "DNA_userdef_types.h"
77
78 #include "BKE_utildefines.h"
79 #include "BKE_global.h"
80 #include "BKE_main.h"
81 #include "BKE_displist.h"
82 #include "BKE_library.h"
83 #include "BKE_curve.h"
84 #include "BKE_font.h"
85 #include "BKE_material.h"
86
87 #include "BIF_gl.h"
88 #include "BIF_interface.h"
89 #include "BIF_toolbox.h"
90 #include "BIF_mywindow.h"
91 #include "BIF_editview.h"
92 #include "BIF_space.h"
93 #include "BIF_screen.h"
94
95 #include "BLO_readfile.h"
96
97 #include "BDR_editcurve.h"
98 #include "BSE_filesel.h"
99 #include "BSE_view.h"
100
101 #include "mydevice.h"
102 #include "blendef.h"
103 #include "render.h"
104 #include "interface.h"
105 #include "nla.h"
106
107 #if defined WIN32 || defined __BeOS
108         int fnmatch(){return 0;}
109 #else
110         #include <fnmatch.h>
111 #endif
112
113 #ifndef WIN32
114 #include <sys/param.h>
115 #endif
116
117 #define FILESELHEAD             60
118 #define FILESEL_DY              16
119
120 #define NOTACTIVE                       0
121 #define ACTIVATE                        1
122 #define INACTIVATE                      2
123
124 #define STARTSWITH(x, y) (strncmp(x, y, sizeof(x) - 1) == 0)
125
126 static int is_a_library(SpaceFile *sfile, char *dir, char *group);
127 static void do_library_append(SpaceFile *sfile);
128 static void library_to_filelist(SpaceFile *sfile);
129 static void filesel_select_objects(struct SpaceFile *sfile);
130 static void active_file_object(struct SpaceFile *sfile);
131 static int groupname_to_code(char *group);
132
133 /* local globals */
134
135 static rcti scrollrct, textrct, bar;
136 static int filebuty1, filebuty2, page_ofs, collumwidth, selecting=0;
137 static int filetoname= 0;
138 static float pixels_to_ofs;
139 static char otherdir[FILE_MAXDIR];
140 static ScrArea *otherarea;
141
142 /* FSMENU HANDLING */
143
144         /* FSMenuEntry's without paths indicate seperators */
145 typedef struct _FSMenuEntry FSMenuEntry;
146 struct _FSMenuEntry {
147         FSMenuEntry *next;
148
149         char *path;
150 };
151
152 static FSMenuEntry *fsmenu= 0, *lseperator= 0;
153
154 int fsmenu_get_nentries(void)
155 {
156         FSMenuEntry *fsme;
157         int count= 0;
158
159         for (fsme= fsmenu; fsme; fsme= fsme->next) 
160                 count++;
161
162         return count;
163 }
164 int fsmenu_is_entry_a_seperator(int idx)
165 {
166         FSMenuEntry *fsme;
167
168         for (fsme= fsmenu; fsme && idx; fsme= fsme->next)
169                 idx--;
170
171         return (fsme && !fsme->path)?1:0;
172 }
173 char *fsmenu_get_entry(int idx)
174 {
175         FSMenuEntry *fsme;
176
177         for (fsme= fsmenu; fsme && idx; fsme= fsme->next)
178                 idx--;
179
180         return fsme?fsme->path:NULL;
181 }
182 char *fsmenu_build_menu(void)
183 {
184         DynStr *ds= BLI_dynstr_new();
185         FSMenuEntry *fsme;
186         char *menustr;
187
188         for (fsme= fsmenu; fsme; fsme= fsme->next) {
189                 if (!fsme->path) {
190                                 /* ignore consecutive or trailing seperators */
191                         if (fsme->next && fsme->next->path)
192                                 BLI_dynstr_append(ds, "%l|");
193                 } else {
194                         BLI_dynstr_append(ds, fsme->path);
195                         if (fsme->next) BLI_dynstr_append(ds, "|");
196                 }
197         }
198
199         menustr= BLI_dynstr_get_cstring(ds);
200         BLI_dynstr_free(ds);
201         return menustr;
202 }
203 void fsmenu_insert_entry(char *path, int sorted)
204 {
205         FSMenuEntry *fsme, *prev;
206
207         if (lseperator) {
208                 prev= lseperator;
209                 fsme= lseperator->next;
210         } else {
211                 prev= NULL;
212                 fsme= fsmenu;
213         }
214         for (; fsme; prev= fsme, fsme= fsme->next) {
215                 if (fsme->path) {
216                         if (BLI_streq(path, fsme->path)) {
217                                 return;
218                         } else if (sorted && strcmp(path, fsme->path)<0) {
219                                 break;
220                         }
221                 }
222         }
223         
224         fsme= MEM_mallocN(sizeof(*fsme), "fsme");
225         fsme->path= BLI_strdup(path);
226
227         if (prev) {
228                 fsme->next= prev->next;
229                 prev->next= fsme;
230         } else {
231                 fsme->next= fsmenu;
232                 fsmenu= fsme;
233         }
234 }
235 void fsmenu_append_seperator(void)
236 {
237         if (fsmenu) {
238                 FSMenuEntry *fsme= fsmenu;
239
240                 while (fsme->next) fsme= fsme->next;
241
242                 lseperator= MEM_mallocN(sizeof(*fsme), "fsme");
243                 lseperator->next= NULL;
244                 lseperator->path= NULL;
245
246                 fsme->next= lseperator;
247         }
248 }
249 void fsmenu_remove_entry(int idx)
250 {
251         FSMenuEntry *prev= NULL, *fsme= fsmenu;
252
253         for (fsme= fsmenu; fsme && idx; prev= fsme, fsme= fsme->next)
254                 if (fsme->path)
255                         idx--;
256
257         if (fsme) {
258                 if (prev) {
259                         prev->next= fsme->next;
260                 } else {
261                         fsmenu= fsme->next;
262                 }
263
264                 MEM_freeN(fsme->path);
265                 MEM_freeN(fsme);
266         }
267 }
268 void fsmenu_free(void)
269 {
270         FSMenuEntry *fsme= fsmenu;
271
272         while (fsme) {
273                 FSMenuEntry *n= fsme->next;
274
275                 if (fsme->path) MEM_freeN(fsme->path);
276                 MEM_freeN(fsme);
277
278                 fsme= n;
279         }
280 }
281
282 /* ******************* SORT ******************* */
283
284 static int compare_name(const void *a1, const void *a2)
285 {
286         const struct direntry *entry1=a1, *entry2=a2;
287
288         /* type is gelijk aan stat.st_mode */
289
290         if (S_ISDIR(entry1->type)){
291                 if (S_ISDIR(entry2->type)==0) return (-1);
292         } else{
293                 if (S_ISDIR(entry2->type)) return (1);
294         }
295         if (S_ISREG(entry1->type)){
296                 if (S_ISREG(entry2->type)==0) return (-1);
297         } else{
298                 if (S_ISREG(entry2->type)) return (1);
299         }
300         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
301         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
302         return (strcasecmp(entry1->relname,entry2->relname));
303 }
304
305 static int compare_date(const void *a1, const void *a2) 
306 {
307         const struct direntry *entry1=a1, *entry2=a2;
308         
309         /* type is gelijk aan stat.st_mode */
310
311         if (S_ISDIR(entry1->type)){
312                 if (S_ISDIR(entry2->type)==0) return (-1);
313         } else{
314                 if (S_ISDIR(entry2->type)) return (1);
315         }
316         if (S_ISREG(entry1->type)){
317                 if (S_ISREG(entry2->type)==0) return (-1);
318         } else{
319                 if (S_ISREG(entry2->type)) return (1);
320         }
321         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
322         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
323
324 /*
325         if ( entry1->s.st_ctime < entry2->s.st_ctime) return 1;
326         if ( entry1->s.st_ctime > entry2->s.st_ctime) return -1;
327 */
328         if ( entry1->s.st_mtime < entry2->s.st_mtime) return 1;
329         if ( entry1->s.st_mtime > entry2->s.st_mtime) return -1;
330         else return strcasecmp(entry1->relname,entry2->relname);
331 }
332
333 static int compare_size(const void *a1, const void *a2) 
334 {
335         const struct direntry *entry1=a1, *entry2=a2;
336
337         /* type is gelijk aan stat.st_mode */
338
339         if (S_ISDIR(entry1->type)){
340                 if (S_ISDIR(entry2->type)==0) return (-1);
341         } else{
342                 if (S_ISDIR(entry2->type)) return (1);
343         }
344         if (S_ISREG(entry1->type)){
345                 if (S_ISREG(entry2->type)==0) return (-1);
346         } else{
347                 if (S_ISREG(entry2->type)) return (1);
348         }
349         if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
350         if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
351
352         if ( entry1->s.st_size < entry2->s.st_size) return 1;
353         if ( entry1->s.st_size > entry2->s.st_size) return -1;
354         else return strcasecmp(entry1->relname,entry2->relname);
355 }
356
357
358 /* **************************************** */
359
360 void clear_global_filesel_vars()
361 {
362         selecting= 0;
363 }
364
365
366 void filesel_statistics(SpaceFile *sfile, int *totfile, int *selfile, float *totlen, float *sellen)
367 {
368         int a, len;
369         
370         *totfile= *selfile= 0;
371         *totlen= *sellen= 0;
372         
373         if(sfile->filelist==0) return;
374         
375         for(a=0; a<sfile->totfile; a++) {
376                 if( (sfile->filelist[a].type & S_IFDIR)==0 ) {
377                         (*totfile) ++;
378
379                         len = sfile->filelist[a].s.st_size;
380                         (*totlen) += (len/1048576.0);           
381
382                         if(sfile->filelist[a].flags & ACTIVE) {
383                                 (*selfile) ++;
384                                 (*sellen) += (len/1048576.0);
385                         }
386                 }
387         }
388 }
389
390 /* *************** HULPFUNKTIES ******************* */
391
392 /* This is a really ugly function... its purpose is to
393  * take the space file name and clean it up, replacing
394  * excess file entry stuff (like /tmp/../tmp/../)
395  */
396
397 void checkdir(char *dir)
398 {
399         short a;
400         char *start, *eind;
401         char tmp[FILE_MAXDIR+FILE_MAXFILE];
402
403         BLI_make_file_string(G.sce, tmp, dir, "");
404         strcpy(dir, tmp);
405         
406 #ifdef WIN32
407         if(dir[0]=='.') {       /* komt voor, o.a. bij FILE_MAIN */
408                 dir[0]= '\\';
409                 dir[1]= 0;
410                 return;
411         }       
412
413         while (start = strstr(dir, "\\..\\")) {
414                 eind = start + strlen("\\..\\") - 1;
415                 a = start-dir-1;
416                 while (a>0) {
417                         if (dir[a] == '\\') break;
418                         a--;
419                 }
420                 strcpy(dir+a,eind);
421         }
422
423         while (start = strstr(dir,"\\.\\")){
424                 eind = start + strlen("\\.\\") - 1;
425                 strcpy(start,eind);
426         }
427
428         while (start = strstr(dir,"\\\\" )){
429                 eind = start + strlen("\\\\") - 1;
430                 strcpy(start,eind);
431         }
432
433         if(a = strlen(dir)){                            /* eerst alle '\\' weghalen aan het eind */
434                 while(a>0 && dir[a-1] == '\\'){
435                         a--;
436                         dir[a] = 0;
437                 }
438         }
439
440         strcat(dir, "\\");
441 #else   
442         if(dir[0]=='.') {       /* komt voor, o.a. bij FILE_MAIN */
443                 dir[0]= '/';
444                 dir[1]= 0;
445                 return;
446         }       
447         
448         while ( (start = strstr(dir, "/../")) ) {
449                 eind = start + strlen("/../") - 1;
450                 a = start-dir-1;
451                 while (a>0) {
452                         if (dir[a] == '/') break;
453                         a--;
454                 }
455                 strcpy(dir+a,eind);
456         }
457
458         while ( (start = strstr(dir,"/./")) ){
459                 eind = start + strlen("/./") - 1;
460                 strcpy(start,eind);
461         }
462
463         while ( (start = strstr(dir,"//" )) ){
464                 eind = start + strlen("//") - 1;
465                 strcpy(start,eind);
466         }
467
468         if( (a = strlen(dir)) ){                                /* eerst alle '/' weghalen aan het eind */
469                 while(dir[a-1] == '/'){
470                         a--;
471                         dir[a] = 0;
472                         if (a<=0) break;
473                 }
474         }
475
476         strcat(dir, "/");
477 #endif
478 }
479
480 void test_flags_file(SpaceFile *sfile)
481 {
482         struct direntry *file;
483         int num;
484
485         file= sfile->filelist;
486         
487         for(num=0; num<sfile->totfile; num++, file++) {
488                 file->flags= 0;
489                 file->type= file->s.st_mode;    /* restore het geknoei van hieronder */ 
490                 
491                         /* Don't check extensions for directories */ 
492                 if (file->type&S_IFDIR)
493                         continue;
494                         
495                 if(sfile->type==FILE_BLENDER || sfile->type==FILE_LOADLIB) {
496                         if(BLO_has_bfile_extension(file->relname)) {
497                                 file->flags |= BLENDERFILE;
498                                 if(sfile->type==FILE_LOADLIB) {
499                                         file->type &= ~S_IFMT;
500                                         file->type |= S_IFDIR;
501                                 }
502                         }
503                         else if(BLI_testextensie(file->relname, ".psx")) {
504                                 file->flags |= PSXFILE;
505                         }
506                 } else if (sfile->type==FILE_SPECIAL){
507                         if(BLI_testextensie(file->relname, ".jpg") ||
508                                         BLI_testextensie(file->relname, ".tga") ||
509                                         BLI_testextensie(file->relname, ".rgb") ||
510                                         BLI_testextensie(file->relname, ".png") ||
511                                         BLI_testextensie(file->relname, ".sgi")) {
512                                 file->flags |= IMAGEFILE;                       
513                         }
514                         else if(BLI_testextensie(file->relname, ".avi") ||
515                                         BLI_testextensie(file->relname, ".mv")) {
516                                 file->flags |= MOVIEFILE;                       
517                         }
518                 }
519         }       
520 }
521
522
523 void sort_filelist(SpaceFile *sfile)
524 {
525         struct direntry *file;
526         int num;/*  , act= 0; */
527         
528         switch(sfile->sort) {
529         case FILE_SORTALPHA:
530                 qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);  
531                 break;
532         case FILE_SORTDATE:
533                 qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_date);  
534                 break;
535         case FILE_SORTSIZE:
536                 qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_size);  
537                 break;
538         case FILE_SORTEXTENS:
539                 qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);  
540                 break;
541         }
542         
543         sfile->act= -1;
544
545         file= sfile->filelist;
546         for(num=0; num<sfile->totfile; num++, file++) {
547                 file->flags &= ~HILITE;
548         }
549
550 }
551
552 void read_dir(SpaceFile *sfile)
553 {
554         int num, len;
555         char wdir[FILE_MAXDIR];
556
557         /* sfile->act wordt gebruikt o.a. bij databrowse: dubbele namen van library objecten */
558         sfile->act= -1;
559
560         if(sfile->type==FILE_MAIN) {
561                 main_to_filelist(sfile);
562                 return;
563         }
564         else if(sfile->type==FILE_LOADLIB) {
565                 library_to_filelist(sfile);
566                 if(sfile->libfiledata) return;
567         }
568
569         BLI_hide_dot_files(sfile->flag & FILE_HIDE_DOT);
570         
571         BLI_getwdN(wdir);
572         sfile->totfile= BLI_getdir(sfile->dir, &(sfile->filelist));
573         chdir(wdir);
574         
575         if(sfile->sort!=FILE_SORTALPHA) sort_filelist(sfile);
576         
577         sfile->maxnamelen= 0;
578
579         for (num=0; num<sfile->totfile; num++) {
580                 
581                 len = BMF_GetStringWidth(G.font, sfile->filelist[num].relname);
582                 if (len > sfile->maxnamelen) sfile->maxnamelen = len;
583                 
584                 if(filetoname) {
585                         if(strcmp(sfile->file, sfile->filelist[num].relname)==0) {
586                                 
587                                 sfile->ofs= num-( sfile->collums*(curarea->winy-FILESELHEAD-20)/(2*FILESEL_DY));
588                                 filetoname= 0;
589                         }
590                 }
591         }
592         test_flags_file(sfile);
593         
594         filetoname= 0;
595 }
596
597 void freefilelist(SpaceFile *sfile)
598 {
599         int num;
600
601         num= sfile->totfile-1;
602
603         if (sfile->filelist==0) return;
604         
605         for(; num>=0; num--){
606                 free(sfile->filelist[num].relname);
607                 
608                 if (sfile->filelist[num].string) free(sfile->filelist[num].string);
609         }
610         free(sfile->filelist);
611         sfile->filelist= 0;
612 }
613
614 static void split_sfile(SpaceFile *sfile, char *s1)
615 {
616         char string[FILE_MAXDIR+FILE_MAXFILE], dir[FILE_MAXDIR], file[FILE_MAXFILE];
617
618         strcpy(string, s1);
619
620         BLI_split_dirfile(string, dir, file);
621         
622         if(sfile->filelist) {
623                 if(strcmp(dir, sfile->dir)!=0) {
624                         freefilelist(sfile);
625                 }
626                 else test_flags_file(sfile);
627         }
628         strcpy(sfile->file, file);
629         BLI_make_file_string(G.sce, sfile->dir, dir, "");
630 }
631
632
633 void parent(SpaceFile *sfile)
634 {
635         short a;
636         char *dir;
637         
638         /* als databrowse: geen parent */
639         if(sfile->type==FILE_MAIN && sfile->returnfunc) return;
640
641         dir= sfile->dir;
642         
643 #ifdef WIN32
644         if(a = strlen(dir)) {                           /* eerst alle '/' weghalen aan het eind */
645                 while(dir[a-1] == '\\') {
646                         a--;
647                         dir[a] = 0;
648                         if (a<=0) break;
649                 }
650         }
651         if(a = strlen(dir)) {                           /* daarna alles weghalen tot aan '/' */
652                 while(dir[a-1] != '\\') {
653                         a--;
654                         dir[a] = 0;
655                         if (a<=0) break;
656                 }
657         }
658         if (a = strlen(dir)) {
659                 if (dir[a-1] != '\\') strcat(dir,"\\");
660         }
661         else if(sfile->type!=FILE_MAIN) strcpy(dir,"\\");
662 #else
663         if( (a = strlen(dir)) ) {                               /* eerst alle '/' weghalen aan het eind */
664                 while(dir[a-1] == '/') {
665                         a--;
666                         dir[a] = 0;
667                         if (a<=0) break;
668                 }
669         }
670         if( (a = strlen(dir)) ) {                               /* daarna alles weghalen tot aan '/' */
671                 while(dir[a-1] != '/') {
672                         a--;
673                         dir[a] = 0;
674                         if (a<=0) break;
675                 }
676         }
677         if ( (a = strlen(dir)) ) {
678                 if (dir[a-1] != '/') strcat(dir,"/");
679         }
680         else if(sfile->type!=FILE_MAIN) strcpy(dir,"/");
681 #endif
682         
683         /* to be sure */
684         BLI_make_exist(sfile->dir);
685
686         freefilelist(sfile);
687         sfile->ofs= 0;
688         scrarea_queue_winredraw(curarea);
689 }
690
691 void swapselect_file(SpaceFile *sfile)
692 {
693         struct direntry *file;
694         int num, act= 0;
695         
696         file= sfile->filelist;
697         for(num=0; num<sfile->totfile; num++, file++) {
698                 if(file->flags & ACTIVE) {
699                         act= 1;
700                         break;
701                 }
702         }
703         file= sfile->filelist+2;
704         for(num=2; num<sfile->totfile; num++, file++) {
705                 if(act) file->flags &= ~ACTIVE;
706                 else file->flags |= ACTIVE;
707         }
708 }
709
710 static int find_active_file(SpaceFile *sfile, short x, short y)
711 {
712         int ofs;
713         
714         if(y > textrct.ymax) y= textrct.ymax;
715         if(y <= textrct.ymin) y= textrct.ymin+1;
716         
717         ofs= (x-textrct.xmin)/collumwidth;
718         if(ofs<0) ofs= 0;
719         ofs*= (textrct.ymax-textrct.ymin);
720
721         return sfile->ofs+ (ofs+textrct.ymax-y)/FILESEL_DY;
722         
723 }
724
725
726 /* ********************** DRAW ******************************* */
727
728 static void calc_file_rcts(SpaceFile *sfile)
729 {
730         int tot, h, len;
731         float fac, start, totfile;
732         
733         scrollrct.xmin= 15;
734         scrollrct.xmax= 35;
735         scrollrct.ymin= 10;
736         scrollrct.ymax= curarea->winy-10-FILESELHEAD;
737         
738         textrct.xmin= scrollrct.xmax+10;
739         textrct.xmax= curarea->winx-10;
740         textrct.ymin= scrollrct.ymin;
741         textrct.ymax= scrollrct.ymax;
742         
743         if(textrct.xmax-textrct.xmin <60) textrct.xmax= textrct.xmin+60;
744         
745         len= (textrct.ymax-textrct.ymin) % FILESEL_DY;
746         textrct.ymin+= len;
747         scrollrct.ymin+= len;
748         
749         filebuty1= curarea->winy-FILESELHEAD;
750         filebuty2= filebuty1+FILESELHEAD/2 -6;
751         
752         
753         /* aantal kolommen */
754         len= sfile->maxnamelen+25;
755         
756         if(sfile->type==FILE_MAIN) len+= 100;
757         else if(sfile->flag & FILE_SHOWSHORT) len+= 100;
758         else len+= 380;
759         
760         sfile->collums= (textrct.xmax-textrct.xmin)/len;
761         
762         if(sfile->collums<1) sfile->collums= 1;
763         else if(sfile->collums>8) sfile->collums= 8;
764
765         if((U.flag & FSCOLLUM)==0) if(sfile->type!=FILE_MAIN) sfile->collums= 1;
766         
767         collumwidth= (textrct.xmax-textrct.xmin)/sfile->collums;
768         
769
770         totfile= sfile->totfile + 0.5;
771
772         tot= FILESEL_DY*totfile;
773         if(tot) fac= ((float)sfile->collums*(scrollrct.ymax-scrollrct.ymin))/( (float)tot);
774         else fac= 1.0;
775         
776         if(sfile->ofs<0) sfile->ofs= 0;
777         
778         if(tot) start= ( (float)sfile->ofs)/(totfile);
779         else start= 0.0;
780         if(fac>1.0) fac= 1.0;
781
782         if(start+fac>1.0) {
783                 sfile->ofs= ceil((1.0-fac)*totfile);
784                 start= ( (float)sfile->ofs)/(totfile);
785                 fac= 1.0-start;
786         }
787
788         bar.xmin= scrollrct.xmin+2;
789         bar.xmax= scrollrct.xmax-2;
790         h= (scrollrct.ymax-scrollrct.ymin)-4;
791         bar.ymax= scrollrct.ymax-2- start*h;
792         bar.ymin= bar.ymax- fac*h;
793
794         pixels_to_ofs= (totfile)/(float)(h+3);
795         page_ofs= fac*totfile;
796 }
797
798 int filescrollselect= 0;
799
800 static void draw_filescroll(SpaceFile *sfile)
801 {
802
803         if(scrollrct.ymin+10 >= scrollrct.ymax) return;
804         
805         cpack(0x707070);
806         glRecti(scrollrct.xmin,  scrollrct.ymin,  scrollrct.xmax,  scrollrct.ymax);
807
808         uiEmboss(scrollrct.xmin, scrollrct.ymin, scrollrct.xmax, scrollrct.ymax, 1);
809
810         cpack(0x909090);
811         glRecti(bar.xmin+2,  bar.ymin+2,  bar.xmax-2,  bar.ymax-2);
812
813         uiEmboss(bar.xmin+2, bar.ymin+2, bar.xmax-2, bar.ymax-2, filescrollselect);
814         
815 }
816
817 static void regelrect(unsigned int col, int x, int y)
818 {
819         cpack(col);
820         glRects(x-17,  y-3,  x+collumwidth-21,  y+11);
821
822 }
823
824 static void printregel(SpaceFile *sfile, struct direntry *files, int x, int y)
825 {
826         unsigned int boxcol=0;
827         char *s;
828
829         switch(files->flags & (HILITE + ACTIVE)) {
830         case HILITE+ACTIVE:
831                 boxcol= (0xC09090);
832                 break;
833         case HILITE:
834                 boxcol= (0x909090);
835                 break;
836         case ACTIVE:
837                 boxcol= (0xB08080);
838                 break;
839         }
840
841         if(boxcol) {
842                 regelrect(boxcol, x, y);
843         }
844
845         if(files->flags & BLENDERFILE) {
846                 cpack(0xA0A0);
847                 glRects(x-14,  y,  x-8,  y+7);
848         }
849         else if(files->flags & PSXFILE) {
850                 cpack(0xA060B0);
851                 glRects(x-14,  y,  x-8,  y+7);
852         }
853         else if(files->flags & IMAGEFILE) {
854                 cpack(0xF08040);
855                 glRects(x-14,  y,  x-8,  y+7);
856         }
857         else if(files->flags & MOVIEFILE) {
858                 cpack(0x70A070);
859                 glRects(x-14,  y,  x-8,  y+7);
860         }
861         
862         if(S_ISDIR(files->type)) cpack(0xFFFFFF);
863         else cpack(0x0);
864
865         s = files->string;
866         if(s) {
867                 glRasterPos2i(x,  y);
868                 BMF_DrawString(G.font, files->relname);
869                 
870                 x += sfile->maxnamelen + 100;
871
872                 glRasterPos2i(x - BMF_GetStringWidth(G.font, files->size),  y);
873                 BMF_DrawString(G.font, files->size);
874
875                 if(sfile->flag & FILE_SHOWSHORT) return;
876
877 #ifndef WIN32
878                 /* rwx rwx rwx */
879                         x += 20; glRasterPos2i(x, y); 
880                         BMF_DrawString(G.font, files->mode1); 
881                 
882                         x += 30; glRasterPos2i(x, y); 
883                         BMF_DrawString(G.font, files->mode2); 
884                 
885                         x += 30; glRasterPos2i(x, y); 
886                         BMF_DrawString(G.font, files->mode3); 
887                 
888                 /* owner time date */
889                         x += 30; glRasterPos2i(x, y); 
890                         BMF_DrawString(G.font, files->owner); 
891 #endif
892                 
893                         x += 60; glRasterPos2i(x, y); 
894                         BMF_DrawString(G.font, files->time); 
895                 
896                         x += 50; glRasterPos2i(x, y); 
897                         BMF_DrawString(G.font, files->date); 
898         }
899         else {
900                 glRasterPos2i(x,  y);
901                 BMF_DrawString(G.font, files->relname);
902                 
903                 if(files->nr) { /* extra info */
904                         x+= sfile->maxnamelen+20;
905                         glRasterPos2i(x,  y);
906                         BMF_DrawString(G.font, files->extra);
907                 }
908         }
909 }
910
911
912 static int calc_filesel_regel(SpaceFile *sfile, int nr, int *valx, int *valy)
913 {
914         /* sco van de de regel */
915         int val, coll;
916
917         nr-= sfile->ofs;
918
919         /* aantal regels in de hoogte */
920         val= (textrct.ymax-textrct.ymin)/FILESEL_DY;
921         coll= nr/val;
922         nr -= coll*val;
923         
924         *valy= textrct.ymax-FILESEL_DY+3 - nr*FILESEL_DY;
925         *valx= coll*collumwidth + textrct.xmin+20;
926         
927         if(nr<0 || coll > sfile->collums) return 0;
928         return 1;
929 }
930
931 static void set_active_file(SpaceFile *sfile, int act)
932 {
933         struct direntry *file;
934         int num, redraw= 0, newflag;
935         int old=0, newi=0;
936         
937         file= sfile->filelist;
938         if(file==0) return;
939         
940         for(num=0; num<sfile->totfile; num++, file++) {
941                 if(num==act) {
942                         
943                         if(selecting && num>1) {
944                                 newflag= HILITE | (file->flags & ~ACTIVE);
945                                 if(selecting==ACTIVATE) newflag |= ACTIVE;
946                         
947                                 if(file->flags != newflag) redraw|= 1;
948                                 file->flags= newflag;
949                         }
950                         else {
951                                 if(file->flags & HILITE);
952                                 else {
953                                         file->flags |= HILITE;
954                                         redraw|= 2;
955                                         newi= num;
956                                 }
957                         }
958                 }
959                 else {
960                         if(file->flags & HILITE) {
961                                 file->flags &= ~HILITE;
962                                 redraw|= 2;
963                                 old= num;
964                         }
965                 }
966                         
967         }
968         
969         if(redraw==2) {
970                 int x, y;
971                 
972                 glDrawBuffer(GL_FRONT);
973
974                 glScissor(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winx-12, curarea->winy);
975
976                 if( calc_filesel_regel(sfile, old, &x, &y) ) {
977                         regelrect(0x717171, x, y);
978                         printregel(sfile, sfile->filelist+old, x, y);
979                 }
980                 if( calc_filesel_regel(sfile, newi, &x, &y) ) {
981                         printregel(sfile, sfile->filelist+newi, x, y);
982                 }
983                 
984                 glScissor(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winx, curarea->winy);
985
986                 glFinish();             /* for geforce, to show it in the frontbuffer */
987                 glDrawBuffer(GL_BACK);
988         }
989         else if(redraw) {
990                 scrarea_queue_winredraw(curarea);
991         }
992 }
993
994
995 static void draw_filetext(SpaceFile *sfile)
996 {
997         struct direntry *files;
998         int a, x, y;
999         short mval[2];
1000         
1001         if(textrct.ymin+10 >= textrct.ymax) return;
1002
1003
1004         /* kader */
1005         cpack(0x717171);
1006         glRecti(textrct.xmin,  textrct.ymin,  textrct.xmax,  textrct.ymax);
1007
1008         /* kolommen */
1009         x= textrct.xmin+collumwidth;
1010         for(a=1; a<sfile->collums; a++, x+= collumwidth) {
1011                 cpack(0x303030);
1012                 sdrawline(x,  textrct.ymin,  x,  textrct.ymax); 
1013                 cpack(0xB0B0B0);
1014                 sdrawline(x+1,  textrct.ymin,  x+1,  textrct.ymax); 
1015         }
1016
1017         if(sfile->filelist==0) return;
1018         
1019         /* test: als muis niet in area staat: de HILITE wissen */
1020         getmouseco_areawin(mval);
1021
1022         if(mval[0]<0 || mval[0]>curarea->winx) {
1023                 files= sfile->filelist+sfile->ofs;
1024                 for(a= sfile->ofs; a<sfile->totfile; a++, files++) files->flags &= ~HILITE;
1025         }
1026         
1027         files= sfile->filelist+sfile->ofs;
1028         for(a= sfile->ofs; a<sfile->totfile; a++, files++) {
1029         
1030                 if( calc_filesel_regel(sfile, a, &x, &y)==0 ) break;
1031                 
1032                 printregel(sfile, files, x, y);
1033         }
1034
1035         /* wissen tekenfoutjes, tekst teveel aan de rechterkant: */
1036         uiEmboss(textrct.xmin, textrct.ymin, textrct.xmax, textrct.ymax, 1);
1037         
1038         glColor3f(.5625, .5625, .5625);
1039         glRecti(textrct.xmax+2,  textrct.ymin,  textrct.xmax+10,  textrct.ymax);
1040 }
1041
1042 void drawfilespace()
1043 {
1044         SpaceFile *sfile;
1045         uiBlock *block;
1046         int act, loadbutton;
1047         short mval[2];
1048         char name[20];
1049         char *menu;
1050
1051         myortho2(-0.5, curarea->winrct.xmax-curarea->winrct.xmin-0.5, -0.5, curarea->winrct.ymax-curarea->winrct.ymin-0.5);
1052
1053         glClearColor(.56, .56, .56, 0.0); 
1054         glClear(GL_COLOR_BUFFER_BIT);
1055
1056         sfile= curarea->spacedata.first;        
1057         if(sfile->filelist==0) {
1058                 read_dir(sfile);
1059                 
1060                 calc_file_rcts(sfile);
1061                 
1062                 /* act berekenen */ 
1063                 getmouseco_areawin(mval);
1064                 act= find_active_file(sfile, mval[0], mval[1]);
1065                 if(act>=0 && act<sfile->totfile)
1066                         sfile->filelist[act].flags |= HILITE;
1067         }
1068         else calc_file_rcts(sfile);
1069
1070         /* HEADER */
1071         sprintf(name, "win %d", curarea->win);
1072         block= uiNewBlock(&curarea->uiblocks, name, UI_EMBOSSF, UI_HELV, curarea->win);
1073         
1074         uiSetButLock( sfile->type==FILE_MAIN && sfile->returnfunc, NULL);
1075
1076         /* space available for load/save buttons? */
1077         loadbutton= MAX2(80, 20+BMF_GetStringWidth(G.font, sfile->title));
1078         if(textrct.xmax-textrct.xmin > loadbutton+20) {
1079                 if(sfile->title[0]==0) loadbutton= 0;
1080         }
1081         else loadbutton= 0;
1082
1083         uiDefBut(block, TEX,        1,"",       textrct.xmin, filebuty1, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
1084         uiDefBut(block, TEX,        2,"",       textrct.xmin, filebuty2, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
1085         if(loadbutton) {
1086                 uiSetCurFont(block, UI_HELV);
1087                 uiDefBut(block, BUT,        5, sfile->title,    textrct.xmax-loadbutton, filebuty2, loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
1088                 uiDefBut(block, BUT,        6, "Cancel",        textrct.xmax-loadbutton, filebuty1, loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
1089         }
1090
1091         menu= fsmenu_build_menu();
1092         uiDefButS(block, MENU,  3, menu, scrollrct.xmin, filebuty1, scrollrct.xmax-scrollrct.xmin, 21, &sfile->menu, 0, 0, 0, 0, "");
1093         MEM_freeN(menu);
1094
1095         uiDefBut(block, BUT,            4, "P", scrollrct.xmin, filebuty2, scrollrct.xmax-scrollrct.xmin, 21, 0, 0, 0, 0, 0, "Move to the parent directory (PKEY)");
1096
1097         draw_filescroll(sfile);
1098         draw_filetext(sfile);
1099         
1100         /* andere diskfree etc ? */
1101         scrarea_queue_headredraw(curarea);      
1102         
1103         uiDrawBlock(block);
1104         
1105         curarea->win_swap= WIN_BACK_OK;
1106 }
1107
1108 static void do_filescroll(SpaceFile *sfile)
1109 {
1110         short mval[2], oldy, yo;
1111         
1112         calc_file_rcts(sfile);
1113         
1114         filescrollselect= 1;
1115         /* voor mooiigheid */
1116
1117         glDrawBuffer(GL_FRONT);
1118         draw_filescroll(sfile);
1119         glDrawBuffer(GL_BACK);
1120         
1121         getmouseco_areawin(mval);
1122         oldy= yo= mval[1];
1123         
1124         while(get_mbut()&L_MOUSE) {
1125                 getmouseco_areawin(mval);
1126                 
1127                 if(yo!=mval[1]) {
1128                         int dy= floor(0.5+((float)(oldy-mval[1]))*pixels_to_ofs);
1129                         
1130                         if(dy) {
1131                                 sfile->ofs+= dy;
1132                                 if(sfile->ofs<0) {
1133                                         sfile->ofs= 0;
1134                                         oldy= mval[1];
1135                                 }
1136                                 else oldy= floor(0.5+ (float)oldy - (float)dy/pixels_to_ofs);
1137         
1138                                 scrarea_do_windraw(curarea);
1139                                 screen_swapbuffers();
1140         
1141                         }
1142                         
1143                         yo= mval[1];
1144                 }
1145                 else BIF_wait_for_statechange();
1146         }
1147         filescrollselect= 0;
1148
1149         /* voor mooiigheid */
1150         glDrawBuffer(GL_FRONT);
1151         draw_filescroll(sfile);
1152         glDrawBuffer(GL_BACK);
1153         
1154 }
1155
1156 static void do_filescrollwheel(SpaceFile *sfile, int move)
1157 {
1158         // by phase
1159         int lines, rt;
1160
1161         calc_file_rcts(sfile);
1162
1163         lines = (int)(textrct.ymax-textrct.ymin)/FILESEL_DY;
1164         rt = lines * sfile->collums;
1165
1166         if(sfile->totfile > rt) {
1167                 sfile->ofs+= move;
1168                 if( sfile->ofs + rt > sfile->totfile + 1)
1169                         sfile->ofs = sfile->totfile - rt + 1;
1170         }
1171
1172         if(sfile->ofs<0) {
1173                 sfile->ofs= 0;
1174         }
1175 }
1176
1177 void activate_fileselect(int type, char *title, char *file, void (*func)(char *))
1178 {
1179         SpaceFile *sfile;
1180         char group[24], name[FILE_MAXDIR], temp[FILE_MAXDIR];
1181         
1182         if(curarea==0) return;
1183         if(curarea->win==0) return;
1184         
1185         newspace(curarea, SPACE_FILE);
1186         scrarea_queue_winredraw(curarea);
1187         
1188         /* is misschien dubbelop, voor geval area al SPACE_FILE is met andere filename */
1189         addqueue(curarea->headwin, CHANGED, 1);
1190         
1191
1192         name[2]= 0;
1193         strcpy(name, file);
1194         
1195         sfile= curarea->spacedata.first;
1196         /* sfile wants a (*)(short), but get (*)(char*) */
1197         sfile->returnfunc= func;
1198         sfile->type= type;
1199         sfile->ofs= 0;
1200         /* sfile->act wordt gebruikt bij databrowse: dubbele namen van library objecten */
1201         sfile->act= -1;
1202         
1203         if(BLI_convertstringcode(name, G.sce, G.scene->r.cfra)) sfile->flag |= FILE_STRINGCODE;
1204         else sfile->flag &= ~FILE_STRINGCODE;
1205
1206         if(type==FILE_MAIN) {
1207                 char *groupname;
1208                 
1209                 strcpy(sfile->file, name+2);
1210
1211                 groupname = BLO_idcode_to_name( GS(name) );
1212                 if (groupname) {
1213                         strcpy(sfile->dir, groupname);
1214                         strcat(sfile->dir, "/");
1215                 }
1216
1217                 /* alles vrijgeven */
1218                 if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
1219                 sfile->libfiledata= 0;
1220                 
1221                 freefilelist(sfile);
1222         }
1223         else if(type==FILE_LOADLIB) {
1224                 strcpy(sfile->dir, name);
1225                 if( is_a_library(sfile, temp, group) ) {
1226                         /* dit geval is om een reload van library-filelist te veroorzaken */
1227                         if(sfile->libfiledata==0) {
1228                                 freefilelist(sfile);
1229                         }
1230                 }
1231                 else {
1232                         split_sfile(sfile, name);
1233                         if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
1234                         sfile->libfiledata= 0;
1235                 }
1236         }
1237         else {  /* FILE_BLENDER */
1238                 split_sfile(sfile, name);       /* test ook de filelist */
1239                 
1240                 /* vrijgeven: filelist en libfiledata kloppen niet meer */
1241                 if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
1242                 sfile->libfiledata= 0;
1243         }
1244         BLI_strncpy(sfile->title, title, sizeof(sfile->title));
1245         filetoname= 1;
1246 }
1247
1248 void activate_imageselect(int type, char *title, char *file, void (*func)(char *))
1249 {
1250         SpaceImaSel *simasel;
1251         char dir[FILE_MAXDIR], name[FILE_MAXFILE];
1252         
1253         if(curarea==0) return;
1254         if(curarea->win==0) return;
1255         
1256         newspace(curarea, SPACE_IMASEL);
1257         
1258         /* is misschien dubbelop, voor geval area al SPACE_FILE is met andere filename */
1259         addqueue(curarea->headwin, CHANGED, 1);
1260         addqueue(curarea->win, CHANGED, 1);
1261
1262         name[2]= 0;
1263         strcpy(name, file);
1264
1265         simasel= curarea->spacedata.first;
1266         simasel->returnfunc= func;
1267
1268         if(BLI_convertstringcode(name, G.sce, G.scene->r.cfra)) simasel->mode |= IMS_STRINGCODE;
1269         else simasel->mode &= ~IMS_STRINGCODE;
1270         
1271         BLI_split_dirfile(name, dir, simasel->file);
1272         if(strcmp(dir, simasel->dir)!=0) simasel->fase= 0;
1273         strcpy(simasel->dir, dir);
1274         
1275         BLI_strncpy(simasel->title, title, sizeof(simasel->title));
1276
1277         
1278         
1279         /* filetoname= 1; */
1280 }
1281
1282
1283 void activate_databrowse(ID *id, int idcode, int fromcode, int retval, short *menup, void (*func)(unsigned short))
1284 {
1285         ListBase *lb;
1286         SpaceFile *sfile;
1287         char str[32];
1288         
1289         if(id==0) {
1290                 lb= wich_libbase(G.main, idcode);
1291                 id= lb->first;
1292         }
1293         
1294         if(id) strcpy(str, id->name);
1295         else return;
1296         
1297         activate_fileselect(FILE_MAIN, "SELECT DATABLOCK", str, (void (*) (char*))func);
1298         
1299         sfile= curarea->spacedata.first;
1300         sfile->retval= retval;
1301         sfile->ipotype= fromcode;
1302         sfile->menup= menup;
1303 }
1304
1305 void filesel_prevspace()
1306 {
1307         SpaceFile *sfile;
1308         
1309         sfile= curarea->spacedata.first;
1310         if(sfile->next) {
1311         
1312                 BLI_remlink(&curarea->spacedata, sfile);
1313                 BLI_addtail(&curarea->spacedata, sfile);
1314
1315                 sfile= curarea->spacedata.first;
1316                 newspace(curarea, sfile->spacetype);
1317         }
1318         else newspace(curarea, SPACE_INFO);
1319 }
1320
1321 static int countselect(SpaceFile *sfile)
1322 {
1323         int a, count=0;
1324
1325         for(a=0; a<sfile->totfile; a++) {
1326                 if(sfile->filelist[a].flags & ACTIVE) {
1327                         count++;
1328                 }
1329         }
1330         return count;
1331 }
1332
1333 static int getotherdir(void)
1334 {
1335         ScrArea *sa;
1336         SpaceFile *sfile=0;
1337         
1338         sa= G.curscreen->areabase.first;
1339         while(sa) {
1340                 if(sa!=curarea) {
1341                         if(sa->spacetype==SPACE_FILE) {
1342                                 
1343                                 /* al een gevonden */
1344                                 if(sfile) return 0;
1345                 
1346                                 sfile= sa->spacedata.first;
1347
1348                                 if(sfile->type & FILE_UNIX) {
1349                                         otherarea= sa;
1350                                         BLI_make_file_string(G.sce, otherdir, sfile->dir, "");
1351                                 }
1352                                 else sfile= 0;
1353                         }
1354                 }
1355                 sa= sa->next;
1356         }
1357         if(sfile) return 1;
1358         return 0;
1359 }
1360
1361 static void reread_other_fs(void)
1362 {
1363         SpaceFile *sfile;
1364         
1365         /* oppassen: alleen aanroepen als getotherdir goed is afgelopen */
1366         
1367         sfile= otherarea->spacedata.first;
1368         freefilelist(sfile);
1369         scrarea_queue_winredraw(otherarea);
1370 }
1371
1372
1373 void free_filesel_spec(char *dir)
1374 {
1375         /* alle filesels met 'dir' worden vrijgegeven */
1376         bScreen *sc;
1377                 
1378         sc= G.main->screen.first;
1379         while(sc) {
1380                 ScrArea *sa= sc->areabase.first;
1381                 while(sa) {
1382                         SpaceLink  *sl= sa->spacedata.first;
1383                         while(sl) {
1384                                 if(sl->spacetype==SPACE_FILE) {
1385                                         SpaceFile *sfile= (SpaceFile*) sl;
1386                                         if (BLI_streq(sfile->dir, dir)) {
1387                                                 freefilelist(sfile);
1388                                         }
1389                                 }
1390                                 sl= sl->next;
1391                         }
1392                         sa= sa->next;
1393                 }
1394                 sc= sc->id.next;
1395         }
1396 }
1397
1398
1399 static void filesel_execute(SpaceFile *sfile)
1400 {
1401         struct direntry *files;
1402         char name[FILE_MAXDIR];
1403         int a;
1404         
1405         filesel_prevspace();
1406
1407         if(sfile->type==FILE_LOADLIB) {
1408                 do_library_append(sfile);
1409                 
1410                 allqueue(REDRAWALL, 1);
1411         }
1412         else if(sfile->returnfunc) {
1413                 fsmenu_insert_entry(sfile->dir, 1);
1414         
1415                 if(sfile->type==FILE_MAIN) {
1416                         if (sfile->menup) {
1417                                 if(sfile->act>=0) {
1418                                         if(sfile->filelist) {
1419                                                 files= sfile->filelist+sfile->act;
1420                                                 *sfile->menup= files->nr;
1421                                         }       
1422                                         else *sfile->menup= sfile->act+1;
1423                                 }
1424                                 else {
1425                                         *sfile->menup= -1;
1426                                         for(a=0; a<sfile->totfile; a++) {
1427                                                 if( strcmp(sfile->filelist[a].relname, sfile->file)==0) {
1428                                                         *sfile->menup= a+1;
1429                                                         break;
1430                                                 }
1431                                         }
1432                                 }
1433                         }
1434                         sfile->returnfunc((char*) sfile->retval);
1435                 }
1436                 else {
1437                         if(strncmp(sfile->title, "SAVE", 4)==0) free_filesel_spec(sfile->dir);
1438                         
1439                         strcpy(name, sfile->dir);
1440                         strcat(name, sfile->file);
1441                         
1442                         if(sfile->flag & FILE_STRINGCODE) BLI_makestringcode(G.sce, name);
1443
1444                         sfile->returnfunc(name);
1445                 }
1446         }
1447 }
1448
1449 static void do_filesel_buttons(short event, SpaceFile *sfile)
1450 {
1451         char butname[FILE_MAXDIR];
1452         
1453         if (event == 1) {
1454                 if (strchr(sfile->file, '*') || strchr(sfile->file, '?') || strchr(sfile->file, '[')) {
1455                         int i, match = FALSE;
1456                         
1457                         for (i = 2; i < sfile->totfile; i++) {
1458                                 if (fnmatch(sfile->file, sfile->filelist[i].relname, 0) == 0) {
1459                                         sfile->filelist[i].flags |= ACTIVE;
1460                                         match = TRUE;
1461                                 }
1462                         }
1463                         if (match) strcpy(sfile->file, "");
1464                         if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
1465                         scrarea_queue_winredraw(curarea);
1466                 }
1467         }
1468         else if(event== 2) {
1469                 /* reuse the butname variable */
1470                 checkdir(sfile->dir);
1471
1472                 BLI_make_file_string(G.sce, butname, sfile->dir, "");
1473                 /* strip the trailing slash if its a real dir */
1474                 if (strlen(butname)!=1)
1475                         butname[strlen(butname)-1]=0;
1476                 
1477                 if(sfile->type & FILE_UNIX) {
1478                         if (!BLI_exists(butname)) {
1479                                 if (okee("Makedir")) {
1480                                         BLI_recurdir_fileops(butname);
1481                                         if (!BLI_exists(butname)) parent(sfile);
1482                                 } else parent(sfile);
1483                         }
1484                 }
1485                 freefilelist(sfile);
1486                 sfile->ofs= 0;
1487                 scrarea_queue_winredraw(curarea);
1488         }
1489         else if(event== 3) {
1490                 char *selected= fsmenu_get_entry(sfile->menu-1);
1491                 
1492                 /* welke string */
1493                 if (selected) {
1494                         strcpy(sfile->dir, selected);
1495                         BLI_make_exist(sfile->dir);
1496                         checkdir(sfile->dir);
1497                         freefilelist(sfile);
1498                         sfile->ofs= 0;
1499                         scrarea_queue_winredraw(curarea);
1500                 }
1501
1502                 sfile->act= -1;
1503                 
1504         }
1505         else if(event== 4) parent(sfile);
1506         else if(event== 5) {
1507                 if(sfile->type) filesel_execute(sfile);
1508         }
1509         else if(event== 6) filesel_prevspace();
1510         
1511 }
1512
1513 /****/
1514
1515 typedef void (*ReplaceFP)(ID *oldblock, ID *newblock);
1516
1517 static void change_id_link(void *linkpv, void *newlinkv) {
1518         ID **linkp= (ID**) linkpv;
1519         ID *newlink= newlinkv;
1520
1521         if (*linkp) {
1522                 (*linkp)->us--;
1523         }
1524         (*linkp)= newlink;
1525         if (newlink) {
1526                 id_us_plus(newlink);
1527         }
1528 }
1529
1530 static void replace_image(ID *oldblock, ID *newblock) {
1531         Image *oldima= (Image*) oldblock;
1532         Image *newima= (Image*) newblock;
1533         bScreen *sc;
1534         Scene *sce;
1535         Tex *tex;
1536         Mesh *me;
1537
1538         for (tex= G.main->tex.first; tex; tex= tex->id.next) {
1539                 if (tex->env && tex->env->type == ENV_LOAD && tex->env->ima == oldima)
1540                         change_id_link(&tex->env->ima, newima);
1541                 if (tex->ima == oldima)
1542                         change_id_link(&tex->ima, newima);
1543         }
1544
1545         for (sce= G.main->scene.first; sce; sce= sce->id.next) {
1546                 if (sce->ima == oldima)
1547                         change_id_link(&sce->ima, newima);
1548         }
1549
1550         for (sc= G.main->screen.first; sc; sc= sc->id.next) {
1551                 ScrArea *sa;
1552
1553                 for (sa= sc->areabase.first; sa; sa= sa->next) {
1554                         SpaceLink *sl;
1555
1556                         for (sl= sa->spacedata.first; sl; sl= sl->next) {
1557                                 if (sl->spacetype == SPACE_VIEW3D) {
1558                                         View3D *v3d= (View3D*) sl;
1559                                         BGpic *bgp= v3d->bgpic;
1560
1561                                         if (bgp && bgp->ima == oldima) 
1562                                                 change_id_link(&bgp->ima, newima);
1563                                 } else if (sl->spacetype == SPACE_IMAGE) {
1564                                         SpaceImage *sima= (SpaceImage*) sl;
1565                                         
1566                                         if (sima->image == oldima)
1567                                                 change_id_link(&sima->image, newima);
1568                                 }
1569                         }
1570                 }
1571         }
1572
1573         for (me= G.main->mesh.first; me; me= me->id.next) {
1574                 TFace *tfaces= me->tface;
1575
1576                 if (tfaces) {
1577                         int i;
1578
1579                         for (i=0; i<me->totface; i++) {
1580                                 TFace *tf= &tfaces[i];
1581
1582                                 if (tf->tpage == oldima) {
1583                                                 /* not change_id_link, tpage's aren't owners :(
1584                                                  * see hack below.
1585                                                  */
1586                                         tf->tpage= newima;
1587                                 }
1588                         }
1589                 }
1590         }
1591
1592                 /* Nasty hack, necessary because tpages don't act
1593                  * as a user, so there lots of image user count
1594                  * munging occurs... this will ensure the image
1595                  * really dies.
1596                  */
1597         oldima->id.us= 0;
1598 }
1599
1600 static void replace_material(ID *oldblock, ID *newblock)
1601 {
1602         Material *old= (Material*) oldblock;
1603         Material *new= (Material*) newblock;
1604         Material ***matarar;
1605         ID *id;
1606         Object *ob;
1607         int a;
1608         
1609         ob= G.main->object.first;
1610         while(ob) {
1611                 if(ob->totcol && ob->id.lib==0) {
1612                         matarar= give_matarar(ob);
1613                         for(a=1; a<=ob->totcol; a++) {
1614                                 if(ob->mat[a-1] == old) {
1615                                         if(old) old->id.us--;
1616                                         id_us_plus((ID *)new);
1617                                         ob->mat[a-1]= new;
1618                                 }
1619                                 id= ob->data;
1620                                 if( (*matarar)[a-1] == old  && id->lib==0) {
1621                                         if(old) old->id.us--;
1622                                         id_us_plus((ID *)new);
1623                                         (*matarar)[a-1]= new;
1624                                 }
1625                         }
1626                 }
1627                 ob= ob->id.next;
1628         }
1629 }
1630
1631 static ReplaceFP get_id_replace_function(int idcode) {
1632         switch (idcode) {
1633         case ID_MA:
1634                 return &replace_material;
1635         case ID_IM:
1636                 return &replace_image;
1637         default:
1638                 return NULL;
1639         }
1640 }
1641
1642 static void databrowse_replace(SpaceFile *sfile, int idcode)
1643 {
1644         ReplaceFP replace_func= get_id_replace_function(idcode);
1645
1646         if (!replace_func) {
1647                 error("Replacing %s blocks is unsupported", BLO_idcode_to_name(idcode));
1648         } else if (sfile->act==-1) {
1649                 error("Select target with leftmouse");
1650         } else {
1651                 ID *target= (ID*) sfile->filelist[sfile->act].poin;
1652
1653                 if (target) {
1654                         char buf[128];
1655
1656                         sprintf(buf, "Replace with %s: %s", BLO_idcode_to_name(idcode), target->name+2);
1657
1658                         if (okee(buf)) {
1659                                 int i;
1660
1661                                 for (i = 0; i <sfile->totfile; i++)
1662                                         if ((sfile->filelist[i].flags&ACTIVE) && sfile->filelist[i].poin!=target)
1663                                                 replace_func(sfile->filelist[i].poin, target);
1664                         }
1665                 }
1666         }
1667
1668         freefilelist(sfile);
1669         scrarea_queue_winredraw(curarea);
1670 }
1671
1672 static void fs_fake_users(SpaceFile *sfile)
1673 {
1674         ID *id;
1675         int a;
1676         
1677         /* alleen bij F4 DATABROWSE */
1678         if(sfile->returnfunc) return;
1679         
1680         for(a=0; a<sfile->totfile; a++) {
1681                 if(sfile->filelist[a].flags & ACTIVE) {
1682                         id= (ID *)sfile->filelist[a].poin;
1683                         if(id) {
1684                                 if( id->flag & LIB_FAKEUSER) {
1685                                         id->flag -= LIB_FAKEUSER;
1686                                         id->us--;
1687                                 }
1688                                 else {
1689                                         id->flag |= LIB_FAKEUSER;
1690                                         id->us++;
1691                                 }
1692                         }
1693                 }
1694         }
1695         freefilelist(sfile);
1696         scrarea_queue_winredraw(curarea);
1697 }
1698
1699 void winqreadfilespace(unsigned short event, short val, char ascii)
1700 {
1701         static int acto=0;
1702         SpaceFile *sfile;
1703         int act, do_draw= 0, i, test, ret = 0;
1704         short qual, mval[2];
1705         char str[FILE_MAXDIR+FILE_MAXFILE+12];
1706         
1707         sfile= curarea->spacedata.first;
1708         if(sfile==0) return;
1709         if(sfile->filelist==0) {
1710                 /* wel buttons doen */
1711                 if(val && event==LEFTMOUSE) {
1712                         /* FrontbufferButs(TRUE); */
1713                         /* event= DoButtons(); */
1714                         /* FrontbufferButs(FALSE); */
1715                                         /*  NIET de headerbuttons! */
1716                         /* if(event) do_filesel_buttons(event, sfile); */
1717                 }
1718                 return;
1719         }
1720         
1721         if(curarea->win==0) return;
1722         calc_file_rcts(sfile);
1723         getmouseco_areawin(mval);
1724
1725         /* om hangen te voorkomen */
1726         if(selecting && !(get_mbut() & R_MOUSE)) selecting= 0;
1727
1728         if(val) {
1729
1730                 if( event!=RETKEY && event!=PADENTER)
1731                         if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
1732
1733                 switch(event) {
1734                 
1735                 case UI_BUT_EVENT:
1736                         do_filesel_buttons(val, sfile);
1737                         break;          
1738                 
1739                 case WHEELDOWNMOUSE:
1740                         do_filescrollwheel(sfile, 3); //U.wheellinescroll);
1741                         act= find_active_file(sfile, mval[0], mval[1]);
1742                         set_active_file(sfile, act);
1743                         do_draw= 1;
1744                         break;
1745                 case WHEELUPMOUSE:
1746                         do_filescrollwheel(sfile, -3); //U.wheellinescroll);
1747                         act= find_active_file(sfile, mval[0], mval[1]);
1748                         set_active_file(sfile, act);
1749                         do_draw= 1;
1750                         break;
1751
1752                 case LEFTMOUSE:
1753                 case MIDDLEMOUSE:
1754                         if(mval[0]>scrollrct.xmin && mval[0]<scrollrct.xmax && mval[1]>scrollrct.ymin && mval[1]<scrollrct.ymax) {
1755                                 do_filescroll(sfile);
1756                         }
1757                         else if(mval[0]>textrct.xmin && mval[0]<textrct.xmax && mval[1]>textrct.ymin && mval[1]<textrct.ymax) {
1758                                 
1759                                 /* sfile->act wordt gebruikt bij databrowse: dubbelenamen van library objecten */
1760                                 
1761                                 sfile->act= act= find_active_file(sfile, mval[0], mval[1]);
1762                                 
1763                                 if(act>=0 && act<sfile->totfile) {
1764                                         if(S_ISDIR(sfile->filelist[act].type)) {
1765                                                 strcat(sfile->dir, sfile->filelist[act].relname);
1766                                                 strcat(sfile->dir,"/");
1767                                                 checkdir(sfile->dir);
1768                                                 freefilelist(sfile);
1769                                                 sfile->ofs= 0;
1770                                                 do_draw= 1;
1771                                         }
1772                                         else {
1773                                                 if( strcmp(sfile->file, sfile->filelist[act].relname)) {
1774                                                         do_draw= 1;
1775                                                         strcpy(sfile->file, sfile->filelist[act].relname);
1776                                                 }
1777                                                 if(event==MIDDLEMOUSE && sfile->type) filesel_execute(sfile);
1778                                         }
1779                                 }
1780                         }
1781                         else {
1782                                 /* FrontbufferButs(TRUE); */
1783                                 /* event= DoButtons(); */
1784                                 /* FrontbufferButs(FALSE); */
1785                                         /*  NIET de headerbuttons! */
1786                                 /* if(event) do_filesel_buttons(event, sfile);   */
1787                         }
1788                         break;
1789                 case RIGHTMOUSE:
1790                         act= find_active_file(sfile, mval[0], mval[1]);
1791                         acto= act;
1792                         if(act>=0 && act<sfile->totfile) {
1793
1794                                 if (sfile->filelist[act].flags & ACTIVE) {
1795                                         sfile->filelist[act].flags &= ~ACTIVE;
1796                                         selecting = INACTIVATE;
1797                                 }
1798                                 else {
1799                                         test= sfile->filelist[act].relname[0];
1800                                         if (act>=2 || test!='.') sfile->filelist[act].flags |= ACTIVE;
1801                                         
1802                                         selecting = ACTIVATE;
1803                                 }
1804                                 do_draw= 1;
1805                         }
1806                         break;
1807                 case MOUSEY:
1808                         act= find_active_file(sfile, mval[0], mval[1]);
1809                         if (act!=acto) {
1810                                 set_active_file(sfile, act);
1811                         }
1812                         if(selecting && act!=acto) {
1813                                         
1814                                 while(1) {
1815                                         if (acto >= 2 && acto < sfile->totfile) {
1816                                                 if (selecting == ACTIVATE) sfile->filelist[acto].flags |= ACTIVE;
1817                                                 else if (selecting == INACTIVATE) sfile->filelist[acto].flags &= ~ACTIVE;
1818                                         }
1819                                         if (acto < act) acto++;
1820                                         else if (acto > act) acto--;
1821                                         else break;
1822                                         
1823                                 }
1824
1825                         }
1826                         acto= act;
1827                         break;
1828                 
1829                 case PAGEUPKEY:
1830                         sfile->ofs-= page_ofs;
1831                         do_draw= 1;
1832                         break;
1833                 case PAGEDOWNKEY:
1834                         sfile->ofs+= page_ofs;
1835                         do_draw= 1;
1836                         break;
1837                 case HOMEKEY:
1838                         sfile->ofs= 0;
1839                         do_draw= 1;
1840                         break;
1841                 case ENDKEY:
1842                         sfile->ofs= sfile->totfile;
1843                         do_draw= 1;
1844                         break;
1845                 
1846                 case AKEY:
1847                         swapselect_file(sfile);
1848                         if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
1849                         do_draw= 1;
1850                         break;
1851                         
1852                 case BKEY:
1853                 case CKEY:
1854                 case LKEY:
1855                         if(event==LKEY && sfile->type==FILE_MAIN && (G.qual & LR_CTRLKEY)) {
1856                                 databrowse_replace(sfile, groupname_to_code(sfile->dir));
1857                                 break;
1858                         }
1859                         /* doorgeven */
1860                 case MKEY:
1861                         if(sfile->type==FILE_MAIN) break;
1862
1863                         if(!countselect(sfile)) {
1864                                 error("No files selected");
1865                                 break;
1866                         }
1867                         
1868                         if(!getotherdir()) {
1869                                 error("No second fileselect");
1870                                 break;
1871                         }
1872                         
1873                         if (!strcmp(sfile->dir, otherdir)) {
1874                                 error("Same directories");
1875                                 break;
1876                         }
1877
1878                         if(event==BKEY) sprintf(str, "Backup to %s", otherdir);
1879                         else if(event==CKEY) sprintf(str, "Copy to %s", otherdir);
1880                         else if(event==LKEY) sprintf(str, "Linked copy to %s", otherdir);
1881                         else if(event==MKEY) sprintf(str, "Move to %s", otherdir);
1882                                         
1883                         if (!okee(str)) break;
1884
1885                         for (i = 0; i<sfile->totfile; i++){
1886                                 if (sfile->filelist[i].flags & ACTIVE) {                        
1887                                         BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[i].relname);
1888
1889                                         if(event==BKEY) ret= BLI_backup(sfile->filelist[i].relname, sfile->dir, otherdir);
1890                                         else if(event==CKEY) ret= BLI_copy_fileops(str, otherdir);
1891                                         else if(event==LKEY) ret= BLI_link(str, otherdir);
1892                                         else if(event==MKEY) ret= BLI_move(str, otherdir);
1893
1894                                         if (ret) {error("Command failed, see console"); break;}
1895                                         else sfile->filelist[i].flags &= ~ACTIVE;
1896                                 }
1897                         }
1898                         do_draw= 1;
1899                         if(event==BKEY || event==MKEY) 
1900                                 freefilelist(sfile);
1901                                 
1902                         reread_other_fs();
1903                         
1904                         break;
1905                 case RKEY:
1906                         if(sfile->type==FILE_MAIN) {
1907                                 databrowse_replace(sfile, groupname_to_code(sfile->dir));
1908                                 break;
1909                         }
1910                         /* doorgeven aan TKEY! */
1911                         
1912                 case TKEY:
1913                         if(sfile->type==FILE_MAIN) break;
1914                         
1915                         if(!countselect(sfile)) {
1916                                 error("No files selected");
1917                                 break;
1918                         }
1919
1920                         if(event==TKEY) sprintf(str, "Touch");
1921                         else if(event==RKEY) sprintf(str, "Remove from %s", sfile->dir);
1922                         
1923                         qual= G.qual;   /* want na okee() heb je de shift losgelaten */
1924                         if (!okee(str)) break;
1925                         
1926                         for (i = 0; i <sfile->totfile; i++) {
1927                                 if (sfile->filelist[i].flags & ACTIVE) {
1928                                         BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[i].relname);
1929
1930                                         if(event==TKEY) ret= BLI_touch(str);
1931                                         else if(event==RKEY) {
1932                                                 if(qual & LR_SHIFTKEY) ret= BLI_delete(str, 0, 1);
1933                                                 else if(S_ISDIR(sfile->filelist[i].type)) ret= BLI_delete(str, 1, 0);
1934                                                 else ret= BLI_delete(str, 0, 0);
1935                                         }
1936
1937                                         if (ret) {error("Command failed, see console"); break;}
1938                                         else sfile->filelist[i].flags &= ~ACTIVE;
1939                                 }
1940                         }
1941                         do_draw= 1;
1942                         freefilelist(sfile);
1943
1944                         break;
1945                                 
1946                 case PKEY:
1947                         if(G.qual & LR_SHIFTKEY) {
1948                                 extern char bprogname[];        /* usiblender.c */
1949                         
1950                                 sprintf(str, "%s -a \"%s%s\"", bprogname, sfile->dir, sfile->file);
1951                                 system(str);
1952                         }
1953                         else 
1954                                 parent(sfile);
1955                                 
1956                         break;
1957
1958                 case IKEY:
1959                         if(sfile->type==FILE_MAIN) break;
1960                         
1961                         sprintf(str, "$IMAGEEDITOR %s%s", sfile->dir, sfile->file);
1962                         system(str);
1963                         break;
1964                 
1965                 case EKEY:
1966                         if(sfile->type==FILE_MAIN) break;
1967                         
1968                         sprintf(str, "$WINEDITOR %s%s", sfile->dir, sfile->file);
1969                         system(str);
1970                         break;
1971                 
1972                 case FKEY:
1973                         if(sfile->type==FILE_MAIN) {
1974                                 fs_fake_users(sfile);
1975                         }
1976                         break;
1977                                 
1978                 case PADPLUSKEY:
1979                 case EQUALKEY:
1980                         if (G.qual & LR_CTRLKEY) BLI_newname(sfile->file, +100);
1981                         else if (G.qual & LR_SHIFTKEY) BLI_newname(sfile->file, +10);
1982                         else BLI_newname(sfile->file, +1);
1983                         
1984                         do_draw= 1;
1985                         break;
1986                         
1987                 case PADMINUS:
1988                 case MINUSKEY:
1989                         if (G.qual & LR_CTRLKEY) BLI_newname(sfile->file, -100);
1990                         else if (G.qual & LR_SHIFTKEY) BLI_newname(sfile->file, -10);
1991                         else BLI_newname(sfile->file, -1);
1992                         
1993                         do_draw= 1;
1994                         break;
1995                         
1996                 case BACKSLASHKEY:
1997                 case SLASHKEY:
1998                         if(sfile->type==FILE_MAIN) break;
1999
2000 #ifdef WIN32
2001                         strcpy(sfile->dir, "\\");
2002 #else
2003                         strcpy(sfile->dir, "/");
2004 #endif
2005                         freefilelist(sfile);
2006                         sfile->ofs= 0;
2007                         do_draw= 1;
2008                         break;
2009                 case PERIODKEY:
2010                         freefilelist(sfile);
2011                         do_draw= 1;
2012                         break;
2013                 case ESCKEY:
2014                         filesel_prevspace();
2015                         break;
2016                 case PADENTER:
2017                 case RETKEY:
2018                         if(sfile->type) filesel_execute(sfile);
2019                         break;
2020                 }
2021         }
2022         else if(event==RIGHTMOUSE) {
2023                 selecting = NOTACTIVE;
2024                 if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
2025         }
2026         else if(event==LEFTMOUSE) {
2027                 if(sfile->type==FILE_MAIN) active_file_object(sfile);
2028         }
2029
2030                 /* XXX, stupid patch, curarea can become undone
2031                  * because of file loading... fixme zr
2032                  */
2033         if(do_draw && curarea) scrarea_queue_winredraw(curarea);
2034 }
2035
2036
2037
2038
2039 /* ************* LIBRARY FILESEL ******************* */
2040
2041 static int groupname_to_code(char *group)
2042 {
2043         char buf[32];
2044         char *lslash;
2045         
2046         strcpy(buf, group);
2047         lslash= BLI_last_slash(buf);
2048         if (lslash)
2049                 lslash[0]= '\0';
2050
2051         return BLO_idcode_from_name(buf);
2052 }
2053
2054 static int is_a_library(SpaceFile *sfile, char *dir, char *group)
2055 {
2056         /* return ok als een blenderfile, in dir staat de filename,
2057          * in group het type libdata
2058          */
2059         int len;
2060         char *fd;
2061         
2062         strcpy(dir, sfile->dir);
2063         len= strlen(dir);
2064         if(len<7) return 0;
2065         if( dir[len-1] != '/' && dir[len-1] != '\\') return 0;
2066         
2067         group[0]= 0;
2068         dir[len-1]= 0;
2069
2070         /* Find the last slash */
2071         fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
2072
2073         if(fd==0) return 0;
2074         *fd= 0;
2075         if(BLO_has_bfile_extension(fd+1)) {
2076                 *fd= '/';
2077         }
2078         else {
2079                 strcpy(group, fd+1);
2080                         
2081                 /* Find the last slash */
2082                 fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
2083                 if (!fd || !BLO_has_bfile_extension(fd+1)) return 0;
2084         }
2085         return 1;
2086 }
2087
2088 static void do_library_append(SpaceFile *sfile)
2089 {
2090         char dir[FILE_MAXDIR], group[32];
2091         
2092         if ( is_a_library(sfile, dir, group)==0 ) {
2093                 error("Not a library");
2094         } else if (!sfile->libfiledata) {
2095                 error("Library not loaded");
2096         } else if (group[0]==0) {
2097                 error("Nothing indicated");
2098         } else if (BLI_streq(G.main->name, dir)) {
2099                 error("Cannot use current file as library");
2100         } else {
2101                 Object *ob;
2102                 int idcode = groupname_to_code(group);
2103                 
2104                 BLO_library_append(sfile, dir, idcode);
2105
2106                 /* DISPLISTEN */
2107                 ob= G.main->object.first;
2108                 set_displist_onlyzero(1);
2109                 while(ob) {
2110                         if(ob->id.lib) {
2111                                 if(ob->type==OB_FONT) {
2112                                         Curve *cu= ob->data;
2113                                         if(cu->nurb.first==0) text_to_curve(ob, 0);
2114                                 }
2115                                 makeDispList(ob);
2116                         }
2117                         else if(ob->type==OB_MESH && ob->parent && ob->parent->type==OB_LATTICE ) {
2118                                 makeDispList(ob);
2119                         }
2120                         
2121                         ob= ob->id.next;
2122                 }
2123                 set_displist_onlyzero(0);
2124         
2125                 /* in sfile->dir staat de HELE libnaam */
2126                 strcpy(G.lib, sfile->dir);
2127                 
2128                 if((sfile->flag & FILE_LINK)==0) all_local();
2129         }
2130 }
2131
2132 static void library_to_filelist(SpaceFile *sfile)
2133 {
2134         char dir[FILE_MAXDIR], group[24];
2135         int ok, i, nnames, idcode;
2136         LinkNode *l, *names;
2137         
2138         /* name testen */
2139         ok= is_a_library(sfile, dir, group);
2140         if (!ok) {
2141                 /* vrijgeven */
2142                 if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
2143                 sfile->libfiledata= 0;
2144                 return;
2145         }
2146         
2147         /* en daar gaat ie */
2148         /* voorlopig alleen filedata inlezen als libfiledata==0 */
2149         if (sfile->libfiledata==0) {
2150                 sfile->libfiledata= BLO_blendhandle_from_file(dir);
2151                 if(sfile->libfiledata==0) return;
2152         }
2153         
2154         if (idcode= groupname_to_code(group)) {
2155                 names= BLO_blendhandle_get_datablock_names(sfile->libfiledata, idcode);
2156         } else {
2157                 names= BLO_blendhandle_get_linkable_groups(sfile->libfiledata);
2158         }
2159         
2160         nnames= BLI_linklist_length(names);
2161
2162         sfile->totfile= nnames + 2;
2163         sfile->filelist= malloc(sfile->totfile * sizeof(*sfile->filelist));
2164         memset(sfile->filelist, 0, sfile->totfile * sizeof(*sfile->filelist));
2165
2166         sfile->filelist[0].relname= strdup(".");
2167         sfile->filelist[0].type |= S_IFDIR;
2168         sfile->filelist[1].relname= strdup("..");
2169         sfile->filelist[1].type |= S_IFDIR;
2170                 
2171         for (i=0, l= names; i<nnames; i++, l= l->next) {
2172                 char *blockname= l->link;
2173
2174                 sfile->filelist[i + 2].relname= blockname;
2175                 if (!idcode)
2176                         sfile->filelist[i + 2].type |= S_IFDIR;
2177         }
2178                 
2179         BLI_linklist_free(names, NULL);
2180         
2181         qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
2182         
2183         sfile->maxnamelen= 0;
2184         for(i=0; i<sfile->totfile; i++) {
2185                 int len = BMF_GetStringWidth(G.font, sfile->filelist[i].relname);
2186                 if (len > sfile->maxnamelen)
2187                         sfile->maxnamelen = len;
2188         }
2189 }
2190
2191 /* ******************* DATA SELECT ********************* */
2192
2193 static void filesel_select_objects(SpaceFile *sfile)
2194 {
2195         Object *ob;
2196         Base *base;
2197         Scene *sce;
2198         int a;
2199         
2200         /* alleen bij F4 DATABROWSE */
2201         if(sfile->returnfunc) return;
2202         
2203         if( strcmp(sfile->dir, "Object/")==0 ) {
2204                 for(a=0; a<sfile->totfile; a++) {
2205                         
2206                         ob= (Object *)sfile->filelist[a].poin;
2207                         
2208                         if(ob) {
2209                                 if(sfile->filelist[a].flags & ACTIVE) ob->flag |= SELECT;
2210                                 else ob->flag &= ~SELECT;
2211                         }
2212
2213                 }
2214                 base= FIRSTBASE;
2215                 while(base) {
2216                         base->flag= base->object->flag;
2217                         base= base->next;
2218                 }
2219                 allqueue(REDRAWVIEW3D, 0);
2220         }
2221         else if( strcmp(sfile->dir, "Scene/")==0 ) {
2222                 
2223                 for(a=0; a<sfile->totfile; a++) {
2224                         
2225                         sce= (Scene *)sfile->filelist[a].poin;
2226                         if(sce) {
2227                                 if(sfile->filelist[a].flags & ACTIVE) sce->r.scemode |= R_BG_RENDER;
2228                                 else sce->r.scemode &= ~R_BG_RENDER;
2229                         }
2230
2231                 }
2232                 allqueue(REDRAWBUTSRENDER, 0);
2233         }
2234 }
2235
2236 static void active_file_object(SpaceFile *sfile)
2237 {
2238         Object *ob;
2239         
2240         /* alleen bij F4 DATABROWSE */
2241         if(sfile->returnfunc) return;
2242         
2243         if( strcmp(sfile->dir, "Object/")==0 ) {
2244                 if(sfile->act >= 0) {
2245                         
2246                         ob= (Object *)sfile->filelist[sfile->act].poin;
2247                         
2248                         if(ob) {
2249                                 set_active_object(ob);
2250                                 if(BASACT && BASACT->object==ob) {
2251                                         BASACT->flag |= SELECT;
2252                                         sfile->filelist[sfile->act].flags |= ACTIVE;
2253                                         allqueue(REDRAWVIEW3D, 0);
2254                                         scrarea_queue_winredraw(curarea);
2255                                 }
2256                         }
2257                 }
2258         }
2259 }
2260
2261
2262 void main_to_filelist(SpaceFile *sfile)
2263 {
2264         ID *id;
2265         struct direntry *files, *firstlib = NULL;
2266         ListBase *lb;
2267         int a, fake, idcode, len, ok, totlib, totbl;
2268
2269         if(sfile->dir[0]=='/') sfile->dir[0]= 0;
2270         
2271         if(sfile->dir[0]) {
2272                 idcode= groupname_to_code(sfile->dir);
2273                 if(idcode==0) sfile->dir[0]= 0;
2274         }
2275         
2276         if( sfile->dir[0]==0) {
2277                 
2278                 /* directories maken */
2279                 sfile->totfile= 22;
2280                 sfile->filelist= (struct direntry *)malloc(sfile->totfile * sizeof(struct direntry));
2281                 
2282                 for(a=0; a<sfile->totfile; a++) {
2283                         memset( &(sfile->filelist[a]), 0 , sizeof(struct direntry));
2284                         sfile->filelist[a].type |= S_IFDIR;
2285                 }
2286                 
2287                 sfile->filelist[0].relname= strdup("..");
2288                 sfile->filelist[1].relname= strdup(".");
2289                 sfile->filelist[2].relname= strdup("Scene");
2290                 sfile->filelist[3].relname= strdup("Object");
2291                 sfile->filelist[4].relname= strdup("Mesh");
2292                 sfile->filelist[5].relname= strdup("Curve");
2293                 sfile->filelist[6].relname= strdup("Metaball");
2294                 sfile->filelist[7].relname= strdup("Material");
2295                 sfile->filelist[8].relname= strdup("Texture");
2296                 sfile->filelist[9].relname= strdup("Image");
2297                 sfile->filelist[10].relname= strdup("Ika");
2298                 sfile->filelist[11].relname= strdup("Wave");
2299                 sfile->filelist[12].relname= strdup("Lattice");
2300                 sfile->filelist[13].relname= strdup("Lamp");
2301                 sfile->filelist[14].relname= strdup("Camera");
2302                 sfile->filelist[15].relname= strdup("Ipo");
2303                 sfile->filelist[16].relname= strdup("World");
2304                 sfile->filelist[17].relname= strdup("Screen");
2305                 sfile->filelist[18].relname= strdup("VFont");
2306                 sfile->filelist[19].relname= strdup("Text");
2307                 sfile->filelist[20].relname= strdup("Armature");
2308                 sfile->filelist[21].relname= strdup("Action");
2309                 qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
2310         }
2311         else {
2312
2313                 /* files maken */
2314                 idcode= groupname_to_code(sfile->dir);
2315                 
2316                 lb= wich_libbase(G.main, idcode );
2317                 if(lb==0) return;
2318                 
2319                 id= lb->first;
2320                 sfile->totfile= 0;
2321                 while(id) {
2322                         
2323                         if(sfile->returnfunc && idcode==ID_IP) {
2324                                 if(sfile->ipotype== ((Ipo *)id)->blocktype) sfile->totfile++;
2325                         }
2326                         else sfile->totfile++;
2327                         
2328                         id= id->next;
2329                 }
2330                 
2331                 if(sfile->returnfunc==0) sfile->totfile+= 2;
2332                 sfile->filelist= (struct direntry *)malloc(sfile->totfile * sizeof(struct direntry));
2333                 
2334                 files= sfile->filelist;
2335                 
2336                 if(sfile->returnfunc==0) {
2337                         memset( &(sfile->filelist[0]), 0 , sizeof(struct direntry));
2338                         sfile->filelist[0].relname= strdup(".");
2339                         sfile->filelist[0].type |= S_IFDIR;
2340                         memset( &(sfile->filelist[1]), 0 , sizeof(struct direntry));
2341                         sfile->filelist[1].relname= strdup("..");
2342                         sfile->filelist[1].type |= S_IFDIR;
2343                 
2344                         files+= 2;
2345                 }
2346                 
2347                 id= lb->first;
2348                 totlib= totbl= 0;
2349                 
2350                 while(id) {
2351                         
2352                         ok= 0;
2353                         if(sfile->returnfunc && idcode==ID_IP) {
2354                                 if(sfile->ipotype== ((Ipo *)id)->blocktype) ok= 1;
2355                         }
2356                         else ok= 1;
2357                         
2358                         if(ok) {
2359                 
2360                                 memset( files, 0 , sizeof(struct direntry));
2361                                 files->relname= strdup(id->name+2);
2362                                 
2363                                 if(sfile->returnfunc==0) { /* F4 DATA BROWSE */
2364                                         if(idcode==ID_OB) {
2365                                                 if( ((Object *)id)->flag & SELECT) files->flags |= ACTIVE;
2366                                         }
2367                                         else if(idcode==ID_SCE) {
2368                                                 if( ((Scene *)id)->r.scemode & R_BG_RENDER) files->flags |= ACTIVE;
2369                                         }
2370                                 }
2371                                 files->nr= totbl+1;
2372                                 files->poin= id;
2373                                 fake= id->flag & LIB_FAKEUSER;
2374                                 
2375                                 if(id->lib && fake) sprintf(files->extra, "LF %d", id->us);
2376                                 else if(id->lib) sprintf(files->extra, "L    %d", id->us);
2377                                 else if(fake) sprintf(files->extra, "F    %d", id->us);
2378                                 else sprintf(files->extra, "      %d", id->us);
2379                                 
2380                                 if(id->lib) {
2381                                         if(totlib==0) firstlib= files;
2382                                         totlib++;
2383                                 }
2384                                 
2385                                 files++;
2386                                 totbl++;
2387                         }
2388                         
2389                         id= id->next;
2390                 }
2391                 
2392                 /* alleen qsort van libraryblokken */
2393                 if(totlib>1) {
2394                         qsort(firstlib, totlib, sizeof(struct direntry), compare_name);
2395                 }
2396         }
2397
2398         sfile->maxnamelen= 0;
2399         for(a=0; a<sfile->totfile; a++) {
2400                 len = BMF_GetStringWidth(G.font, sfile->filelist[a].relname);
2401                 if (len > sfile->maxnamelen) sfile->maxnamelen = len;
2402                 
2403                 if(filetoname) {
2404                         if( strcmp(sfile->file, sfile->filelist[a].relname)==0) {
2405                                 sfile->ofs= a-( sfile->collums*(curarea->winy-FILESELHEAD-10)/(2*FILESEL_DY));
2406                                 filetoname= 0;
2407                                 if(sfile->returnfunc) sfile->filelist[a].flags |= ACTIVE;
2408                         }
2409                 }
2410         }
2411 }
2412
2413
2414