added iff, lbm and bmp filetypes to the fileselect. added loading of bmp images,
[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, ".bmp") ||
512                                         BLI_testextensie(file->relname, ".iff") ||
513                                         BLI_testextensie(file->relname, ".lbm") ||
514                                         BLI_testextensie(file->relname, ".sgi")) {
515                                 file->flags |= IMAGEFILE;                       
516                         }
517                         else if(BLI_testextensie(file->relname, ".avi") ||
518                                         BLI_testextensie(file->relname, ".mv")) {
519                                 file->flags |= MOVIEFILE;                       
520                         }
521                 }
522         }       
523 }
524
525
526 void sort_filelist(SpaceFile *sfile)
527 {
528         struct direntry *file;
529         int num;/*  , act= 0; */
530         
531         switch(sfile->sort) {
532         case FILE_SORTALPHA:
533                 qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);  
534                 break;
535         case FILE_SORTDATE:
536                 qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_date);  
537                 break;
538         case FILE_SORTSIZE:
539                 qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_size);  
540                 break;
541         case FILE_SORTEXTENS:
542                 qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);  
543                 break;
544         }
545         
546         sfile->act= -1;
547
548         file= sfile->filelist;
549         for(num=0; num<sfile->totfile; num++, file++) {
550                 file->flags &= ~HILITE;
551         }
552
553 }
554
555 void read_dir(SpaceFile *sfile)
556 {
557         int num, len;
558         char wdir[FILE_MAXDIR];
559
560         /* sfile->act wordt gebruikt o.a. bij databrowse: dubbele namen van library objecten */
561         sfile->act= -1;
562
563         if(sfile->type==FILE_MAIN) {
564                 main_to_filelist(sfile);
565                 return;
566         }
567         else if(sfile->type==FILE_LOADLIB) {
568                 library_to_filelist(sfile);
569                 if(sfile->libfiledata) return;
570         }
571
572         BLI_hide_dot_files(sfile->flag & FILE_HIDE_DOT);
573         
574         BLI_getwdN(wdir);
575         sfile->totfile= BLI_getdir(sfile->dir, &(sfile->filelist));
576         chdir(wdir);
577         
578         if(sfile->sort!=FILE_SORTALPHA) sort_filelist(sfile);
579         
580         sfile->maxnamelen= 0;
581
582         for (num=0; num<sfile->totfile; num++) {
583                 
584                 len = BMF_GetStringWidth(G.font, sfile->filelist[num].relname);
585                 if (len > sfile->maxnamelen) sfile->maxnamelen = len;
586                 
587                 if(filetoname) {
588                         if(strcmp(sfile->file, sfile->filelist[num].relname)==0) {
589                                 
590                                 sfile->ofs= num-( sfile->collums*(curarea->winy-FILESELHEAD-20)/(2*FILESEL_DY));
591                                 filetoname= 0;
592                         }
593                 }
594         }
595         test_flags_file(sfile);
596         
597         filetoname= 0;
598 }
599
600 void freefilelist(SpaceFile *sfile)
601 {
602         int num;
603
604         num= sfile->totfile-1;
605
606         if (sfile->filelist==0) return;
607         
608         for(; num>=0; num--){
609                 free(sfile->filelist[num].relname);
610                 
611                 if (sfile->filelist[num].string) free(sfile->filelist[num].string);
612         }
613         free(sfile->filelist);
614         sfile->filelist= 0;
615 }
616
617 static void split_sfile(SpaceFile *sfile, char *s1)
618 {
619         char string[FILE_MAXDIR+FILE_MAXFILE], dir[FILE_MAXDIR], file[FILE_MAXFILE];
620
621         strcpy(string, s1);
622
623         BLI_split_dirfile(string, dir, file);
624         
625         if(sfile->filelist) {
626                 if(strcmp(dir, sfile->dir)!=0) {
627                         freefilelist(sfile);
628                 }
629                 else test_flags_file(sfile);
630         }
631         strcpy(sfile->file, file);
632         BLI_make_file_string(G.sce, sfile->dir, dir, "");
633 }
634
635
636 void parent(SpaceFile *sfile)
637 {
638         short a;
639         char *dir;
640         
641         /* als databrowse: geen parent */
642         if(sfile->type==FILE_MAIN && sfile->returnfunc) return;
643
644         dir= sfile->dir;
645         
646 #ifdef WIN32
647         if(a = strlen(dir)) {                           /* eerst alle '/' weghalen aan het eind */
648                 while(dir[a-1] == '\\') {
649                         a--;
650                         dir[a] = 0;
651                         if (a<=0) break;
652                 }
653         }
654         if(a = strlen(dir)) {                           /* daarna alles weghalen tot aan '/' */
655                 while(dir[a-1] != '\\') {
656                         a--;
657                         dir[a] = 0;
658                         if (a<=0) break;
659                 }
660         }
661         if (a = strlen(dir)) {
662                 if (dir[a-1] != '\\') strcat(dir,"\\");
663         }
664         else if(sfile->type!=FILE_MAIN) strcpy(dir,"\\");
665 #else
666         if( (a = strlen(dir)) ) {                               /* eerst alle '/' weghalen aan het eind */
667                 while(dir[a-1] == '/') {
668                         a--;
669                         dir[a] = 0;
670                         if (a<=0) break;
671                 }
672         }
673         if( (a = strlen(dir)) ) {                               /* daarna alles weghalen tot aan '/' */
674                 while(dir[a-1] != '/') {
675                         a--;
676                         dir[a] = 0;
677                         if (a<=0) break;
678                 }
679         }
680         if ( (a = strlen(dir)) ) {
681                 if (dir[a-1] != '/') strcat(dir,"/");
682         }
683         else if(sfile->type!=FILE_MAIN) strcpy(dir,"/");
684 #endif
685         
686         /* to be sure */
687         BLI_make_exist(sfile->dir);
688
689         freefilelist(sfile);
690         sfile->ofs= 0;
691         scrarea_queue_winredraw(curarea);
692 }
693
694 void swapselect_file(SpaceFile *sfile)
695 {
696         struct direntry *file;
697         int num, act= 0;
698         
699         file= sfile->filelist;
700         for(num=0; num<sfile->totfile; num++, file++) {
701                 if(file->flags & ACTIVE) {
702                         act= 1;
703                         break;
704                 }
705         }
706         file= sfile->filelist+2;
707         for(num=2; num<sfile->totfile; num++, file++) {
708                 if(act) file->flags &= ~ACTIVE;
709                 else file->flags |= ACTIVE;
710         }
711 }
712
713 static int find_active_file(SpaceFile *sfile, short x, short y)
714 {
715         int ofs;
716         
717         if(y > textrct.ymax) y= textrct.ymax;
718         if(y <= textrct.ymin) y= textrct.ymin+1;
719         
720         ofs= (x-textrct.xmin)/collumwidth;
721         if(ofs<0) ofs= 0;
722         ofs*= (textrct.ymax-textrct.ymin);
723
724         return sfile->ofs+ (ofs+textrct.ymax-y)/FILESEL_DY;
725         
726 }
727
728
729 /* ********************** DRAW ******************************* */
730
731 static void calc_file_rcts(SpaceFile *sfile)
732 {
733         int tot, h, len;
734         float fac, start, totfile;
735         
736         scrollrct.xmin= 15;
737         scrollrct.xmax= 35;
738         scrollrct.ymin= 10;
739         scrollrct.ymax= curarea->winy-10-FILESELHEAD;
740         
741         textrct.xmin= scrollrct.xmax+10;
742         textrct.xmax= curarea->winx-10;
743         textrct.ymin= scrollrct.ymin;
744         textrct.ymax= scrollrct.ymax;
745         
746         if(textrct.xmax-textrct.xmin <60) textrct.xmax= textrct.xmin+60;
747         
748         len= (textrct.ymax-textrct.ymin) % FILESEL_DY;
749         textrct.ymin+= len;
750         scrollrct.ymin+= len;
751         
752         filebuty1= curarea->winy-FILESELHEAD;
753         filebuty2= filebuty1+FILESELHEAD/2 -6;
754         
755         
756         /* aantal kolommen */
757         len= sfile->maxnamelen+25;
758         
759         if(sfile->type==FILE_MAIN) len+= 100;
760         else if(sfile->flag & FILE_SHOWSHORT) len+= 100;
761         else len+= 380;
762         
763         sfile->collums= (textrct.xmax-textrct.xmin)/len;
764         
765         if(sfile->collums<1) sfile->collums= 1;
766         else if(sfile->collums>8) sfile->collums= 8;
767
768         if((U.flag & FSCOLLUM)==0) if(sfile->type!=FILE_MAIN) sfile->collums= 1;
769         
770         collumwidth= (textrct.xmax-textrct.xmin)/sfile->collums;
771         
772
773         totfile= sfile->totfile + 0.5;
774
775         tot= FILESEL_DY*totfile;
776         if(tot) fac= ((float)sfile->collums*(scrollrct.ymax-scrollrct.ymin))/( (float)tot);
777         else fac= 1.0;
778         
779         if(sfile->ofs<0) sfile->ofs= 0;
780         
781         if(tot) start= ( (float)sfile->ofs)/(totfile);
782         else start= 0.0;
783         if(fac>1.0) fac= 1.0;
784
785         if(start+fac>1.0) {
786                 sfile->ofs= ceil((1.0-fac)*totfile);
787                 start= ( (float)sfile->ofs)/(totfile);
788                 fac= 1.0-start;
789         }
790
791         bar.xmin= scrollrct.xmin+2;
792         bar.xmax= scrollrct.xmax-2;
793         h= (scrollrct.ymax-scrollrct.ymin)-4;
794         bar.ymax= scrollrct.ymax-2- start*h;
795         bar.ymin= bar.ymax- fac*h;
796
797         pixels_to_ofs= (totfile)/(float)(h+3);
798         page_ofs= fac*totfile;
799 }
800
801 int filescrollselect= 0;
802
803 static void draw_filescroll(SpaceFile *sfile)
804 {
805
806         if(scrollrct.ymin+10 >= scrollrct.ymax) return;
807         
808         cpack(0x707070);
809         glRecti(scrollrct.xmin,  scrollrct.ymin,  scrollrct.xmax,  scrollrct.ymax);
810
811         uiEmboss(scrollrct.xmin, scrollrct.ymin, scrollrct.xmax, scrollrct.ymax, 1);
812
813         cpack(0x909090);
814         glRecti(bar.xmin+2,  bar.ymin+2,  bar.xmax-2,  bar.ymax-2);
815
816         uiEmboss(bar.xmin+2, bar.ymin+2, bar.xmax-2, bar.ymax-2, filescrollselect);
817         
818 }
819
820 static void regelrect(unsigned int col, int x, int y)
821 {
822         cpack(col);
823         glRects(x-17,  y-3,  x+collumwidth-21,  y+11);
824
825 }
826
827 static void printregel(SpaceFile *sfile, struct direntry *files, int x, int y)
828 {
829         unsigned int boxcol=0;
830         char *s;
831
832         switch(files->flags & (HILITE + ACTIVE)) {
833         case HILITE+ACTIVE:
834                 boxcol= (0xC09090);
835                 break;
836         case HILITE:
837                 boxcol= (0x909090);
838                 break;
839         case ACTIVE:
840                 boxcol= (0xB08080);
841                 break;
842         }
843
844         if(boxcol) {
845                 regelrect(boxcol, x, y);
846         }
847
848         if(files->flags & BLENDERFILE) {
849                 cpack(0xA0A0);
850                 glRects(x-14,  y,  x-8,  y+7);
851         }
852         else if(files->flags & PSXFILE) {
853                 cpack(0xA060B0);
854                 glRects(x-14,  y,  x-8,  y+7);
855         }
856         else if(files->flags & IMAGEFILE) {
857                 cpack(0xF08040);
858                 glRects(x-14,  y,  x-8,  y+7);
859         }
860         else if(files->flags & MOVIEFILE) {
861                 cpack(0x70A070);
862                 glRects(x-14,  y,  x-8,  y+7);
863         }
864         
865         if(S_ISDIR(files->type)) cpack(0xFFFFFF);
866         else cpack(0x0);
867
868         s = files->string;
869         if(s) {
870                 glRasterPos2i(x,  y);
871                 BMF_DrawString(G.font, files->relname);
872                 
873                 x += sfile->maxnamelen + 100;
874
875                 glRasterPos2i(x - BMF_GetStringWidth(G.font, files->size),  y);
876                 BMF_DrawString(G.font, files->size);
877
878                 if(sfile->flag & FILE_SHOWSHORT) return;
879
880 #ifndef WIN32
881                 /* rwx rwx rwx */
882                         x += 20; glRasterPos2i(x, y); 
883                         BMF_DrawString(G.font, files->mode1); 
884                 
885                         x += 30; glRasterPos2i(x, y); 
886                         BMF_DrawString(G.font, files->mode2); 
887                 
888                         x += 30; glRasterPos2i(x, y); 
889                         BMF_DrawString(G.font, files->mode3); 
890                 
891                 /* owner time date */
892                         x += 30; glRasterPos2i(x, y); 
893                         BMF_DrawString(G.font, files->owner); 
894 #endif
895                 
896                         x += 60; glRasterPos2i(x, y); 
897                         BMF_DrawString(G.font, files->time); 
898                 
899                         x += 50; glRasterPos2i(x, y); 
900                         BMF_DrawString(G.font, files->date); 
901         }
902         else {
903                 glRasterPos2i(x,  y);
904                 BMF_DrawString(G.font, files->relname);
905                 
906                 if(files->nr) { /* extra info */
907                         x+= sfile->maxnamelen+20;
908                         glRasterPos2i(x,  y);
909                         BMF_DrawString(G.font, files->extra);
910                 }
911         }
912 }
913
914
915 static int calc_filesel_regel(SpaceFile *sfile, int nr, int *valx, int *valy)
916 {
917         /* sco van de de regel */
918         int val, coll;
919
920         nr-= sfile->ofs;
921
922         /* aantal regels in de hoogte */
923         val= (textrct.ymax-textrct.ymin)/FILESEL_DY;
924         coll= nr/val;
925         nr -= coll*val;
926         
927         *valy= textrct.ymax-FILESEL_DY+3 - nr*FILESEL_DY;
928         *valx= coll*collumwidth + textrct.xmin+20;
929         
930         if(nr<0 || coll > sfile->collums) return 0;
931         return 1;
932 }
933
934 static void set_active_file(SpaceFile *sfile, int act)
935 {
936         struct direntry *file;
937         int num, redraw= 0, newflag;
938         int old=0, newi=0;
939         
940         file= sfile->filelist;
941         if(file==0) return;
942         
943         for(num=0; num<sfile->totfile; num++, file++) {
944                 if(num==act) {
945                         
946                         if(selecting && num>1) {
947                                 newflag= HILITE | (file->flags & ~ACTIVE);
948                                 if(selecting==ACTIVATE) newflag |= ACTIVE;
949                         
950                                 if(file->flags != newflag) redraw|= 1;
951                                 file->flags= newflag;
952                         }
953                         else {
954                                 if(file->flags & HILITE);
955                                 else {
956                                         file->flags |= HILITE;
957                                         redraw|= 2;
958                                         newi= num;
959                                 }
960                         }
961                 }
962                 else {
963                         if(file->flags & HILITE) {
964                                 file->flags &= ~HILITE;
965                                 redraw|= 2;
966                                 old= num;
967                         }
968                 }
969                         
970         }
971         
972         if(redraw==2) {
973                 int x, y;
974                 
975                 glDrawBuffer(GL_FRONT);
976
977                 glScissor(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winx-12, curarea->winy);
978
979                 if( calc_filesel_regel(sfile, old, &x, &y) ) {
980                         regelrect(0x717171, x, y);
981                         printregel(sfile, sfile->filelist+old, x, y);
982                 }
983                 if( calc_filesel_regel(sfile, newi, &x, &y) ) {
984                         printregel(sfile, sfile->filelist+newi, x, y);
985                 }
986                 
987                 glScissor(curarea->winrct.xmin, curarea->winrct.ymin, curarea->winx, curarea->winy);
988
989                 glFinish();             /* for geforce, to show it in the frontbuffer */
990                 glDrawBuffer(GL_BACK);
991         }
992         else if(redraw) {
993                 scrarea_queue_winredraw(curarea);
994         }
995 }
996
997
998 static void draw_filetext(SpaceFile *sfile)
999 {
1000         struct direntry *files;
1001         int a, x, y;
1002         short mval[2];
1003         
1004         if(textrct.ymin+10 >= textrct.ymax) return;
1005
1006
1007         /* kader */
1008         cpack(0x717171);
1009         glRecti(textrct.xmin,  textrct.ymin,  textrct.xmax,  textrct.ymax);
1010
1011         /* kolommen */
1012         x= textrct.xmin+collumwidth;
1013         for(a=1; a<sfile->collums; a++, x+= collumwidth) {
1014                 cpack(0x303030);
1015                 sdrawline(x,  textrct.ymin,  x,  textrct.ymax); 
1016                 cpack(0xB0B0B0);
1017                 sdrawline(x+1,  textrct.ymin,  x+1,  textrct.ymax); 
1018         }
1019
1020         if(sfile->filelist==0) return;
1021         
1022         /* test: als muis niet in area staat: de HILITE wissen */
1023         getmouseco_areawin(mval);
1024
1025         if(mval[0]<0 || mval[0]>curarea->winx) {
1026                 files= sfile->filelist+sfile->ofs;
1027                 for(a= sfile->ofs; a<sfile->totfile; a++, files++) files->flags &= ~HILITE;
1028         }
1029         
1030         files= sfile->filelist+sfile->ofs;
1031         for(a= sfile->ofs; a<sfile->totfile; a++, files++) {
1032         
1033                 if( calc_filesel_regel(sfile, a, &x, &y)==0 ) break;
1034                 
1035                 printregel(sfile, files, x, y);
1036         }
1037
1038         /* wissen tekenfoutjes, tekst teveel aan de rechterkant: */
1039         uiEmboss(textrct.xmin, textrct.ymin, textrct.xmax, textrct.ymax, 1);
1040         
1041         glColor3f(.5625, .5625, .5625);
1042         glRecti(textrct.xmax+2,  textrct.ymin,  textrct.xmax+10,  textrct.ymax);
1043 }
1044
1045 void drawfilespace()
1046 {
1047         SpaceFile *sfile;
1048         uiBlock *block;
1049         int act, loadbutton;
1050         short mval[2];
1051         char name[20];
1052         char *menu;
1053
1054         myortho2(-0.5, curarea->winrct.xmax-curarea->winrct.xmin-0.5, -0.5, curarea->winrct.ymax-curarea->winrct.ymin-0.5);
1055
1056         glClearColor(.56, .56, .56, 0.0); 
1057         glClear(GL_COLOR_BUFFER_BIT);
1058
1059         sfile= curarea->spacedata.first;        
1060         if(sfile->filelist==0) {
1061                 read_dir(sfile);
1062                 
1063                 calc_file_rcts(sfile);
1064                 
1065                 /* act berekenen */ 
1066                 getmouseco_areawin(mval);
1067                 act= find_active_file(sfile, mval[0], mval[1]);
1068                 if(act>=0 && act<sfile->totfile)
1069                         sfile->filelist[act].flags |= HILITE;
1070         }
1071         else calc_file_rcts(sfile);
1072
1073         /* HEADER */
1074         sprintf(name, "win %d", curarea->win);
1075         block= uiNewBlock(&curarea->uiblocks, name, UI_EMBOSSF, UI_HELV, curarea->win);
1076         
1077         uiSetButLock( sfile->type==FILE_MAIN && sfile->returnfunc, NULL);
1078
1079         /* space available for load/save buttons? */
1080         loadbutton= MAX2(80, 20+BMF_GetStringWidth(G.font, sfile->title));
1081         if(textrct.xmax-textrct.xmin > loadbutton+20) {
1082                 if(sfile->title[0]==0) loadbutton= 0;
1083         }
1084         else loadbutton= 0;
1085
1086         uiDefBut(block, TEX,        1,"",       textrct.xmin, filebuty1, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
1087         uiDefBut(block, TEX,        2,"",       textrct.xmin, filebuty2, textrct.xmax-textrct.xmin-loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
1088         if(loadbutton) {
1089                 uiSetCurFont(block, UI_HELV);
1090                 uiDefBut(block, BUT,        5, sfile->title,    textrct.xmax-loadbutton, filebuty2, loadbutton, 21, sfile->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
1091                 uiDefBut(block, BUT,        6, "Cancel",        textrct.xmax-loadbutton, filebuty1, loadbutton, 21, sfile->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
1092         }
1093
1094         menu= fsmenu_build_menu();
1095         uiDefButS(block, MENU,  3, menu, scrollrct.xmin, filebuty1, scrollrct.xmax-scrollrct.xmin, 21, &sfile->menu, 0, 0, 0, 0, "");
1096         MEM_freeN(menu);
1097
1098         uiDefBut(block, BUT,            4, "P", scrollrct.xmin, filebuty2, scrollrct.xmax-scrollrct.xmin, 21, 0, 0, 0, 0, 0, "Move to the parent directory (PKEY)");
1099
1100         draw_filescroll(sfile);
1101         draw_filetext(sfile);
1102         
1103         /* andere diskfree etc ? */
1104         scrarea_queue_headredraw(curarea);      
1105         
1106         uiDrawBlock(block);
1107         
1108         curarea->win_swap= WIN_BACK_OK;
1109 }
1110
1111 static void do_filescroll(SpaceFile *sfile)
1112 {
1113         short mval[2], oldy, yo;
1114         
1115         calc_file_rcts(sfile);
1116         
1117         filescrollselect= 1;
1118         /* voor mooiigheid */
1119
1120         glDrawBuffer(GL_FRONT);
1121         draw_filescroll(sfile);
1122         glDrawBuffer(GL_BACK);
1123         
1124         getmouseco_areawin(mval);
1125         oldy= yo= mval[1];
1126         
1127         while(get_mbut()&L_MOUSE) {
1128                 getmouseco_areawin(mval);
1129                 
1130                 if(yo!=mval[1]) {
1131                         int dy= floor(0.5+((float)(oldy-mval[1]))*pixels_to_ofs);
1132                         
1133                         if(dy) {
1134                                 sfile->ofs+= dy;
1135                                 if(sfile->ofs<0) {
1136                                         sfile->ofs= 0;
1137                                         oldy= mval[1];
1138                                 }
1139                                 else oldy= floor(0.5+ (float)oldy - (float)dy/pixels_to_ofs);
1140         
1141                                 scrarea_do_windraw(curarea);
1142                                 screen_swapbuffers();
1143         
1144                         }
1145                         
1146                         yo= mval[1];
1147                 }
1148                 else BIF_wait_for_statechange();
1149         }
1150         filescrollselect= 0;
1151
1152         /* voor mooiigheid */
1153         glDrawBuffer(GL_FRONT);
1154         draw_filescroll(sfile);
1155         glDrawBuffer(GL_BACK);
1156         
1157 }
1158
1159 static void do_filescrollwheel(SpaceFile *sfile, int move)
1160 {
1161         // by phase
1162         int lines, rt;
1163
1164         calc_file_rcts(sfile);
1165
1166         lines = (int)(textrct.ymax-textrct.ymin)/FILESEL_DY;
1167         rt = lines * sfile->collums;
1168
1169         if(sfile->totfile > rt) {
1170                 sfile->ofs+= move;
1171                 if( sfile->ofs + rt > sfile->totfile + 1)
1172                         sfile->ofs = sfile->totfile - rt + 1;
1173         }
1174
1175         if(sfile->ofs<0) {
1176                 sfile->ofs= 0;
1177         }
1178 }
1179
1180 void activate_fileselect(int type, char *title, char *file, void (*func)(char *))
1181 {
1182         SpaceFile *sfile;
1183         char group[24], name[FILE_MAXDIR], temp[FILE_MAXDIR];
1184         
1185         if(curarea==0) return;
1186         if(curarea->win==0) return;
1187         
1188         newspace(curarea, SPACE_FILE);
1189         scrarea_queue_winredraw(curarea);
1190         
1191         /* is misschien dubbelop, voor geval area al SPACE_FILE is met andere filename */
1192         addqueue(curarea->headwin, CHANGED, 1);
1193         
1194
1195         name[2]= 0;
1196         strcpy(name, file);
1197         
1198         sfile= curarea->spacedata.first;
1199         /* sfile wants a (*)(short), but get (*)(char*) */
1200         sfile->returnfunc= func;
1201         sfile->type= type;
1202         sfile->ofs= 0;
1203         /* sfile->act wordt gebruikt bij databrowse: dubbele namen van library objecten */
1204         sfile->act= -1;
1205         
1206         if(BLI_convertstringcode(name, G.sce, G.scene->r.cfra)) sfile->flag |= FILE_STRINGCODE;
1207         else sfile->flag &= ~FILE_STRINGCODE;
1208
1209         if(type==FILE_MAIN) {
1210                 char *groupname;
1211                 
1212                 strcpy(sfile->file, name+2);
1213
1214                 groupname = BLO_idcode_to_name( GS(name) );
1215                 if (groupname) {
1216                         strcpy(sfile->dir, groupname);
1217                         strcat(sfile->dir, "/");
1218                 }
1219
1220                 /* alles vrijgeven */
1221                 if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
1222                 sfile->libfiledata= 0;
1223                 
1224                 freefilelist(sfile);
1225         }
1226         else if(type==FILE_LOADLIB) {
1227                 strcpy(sfile->dir, name);
1228                 if( is_a_library(sfile, temp, group) ) {
1229                         /* dit geval is om een reload van library-filelist te veroorzaken */
1230                         if(sfile->libfiledata==0) {
1231                                 freefilelist(sfile);
1232                         }
1233                 }
1234                 else {
1235                         split_sfile(sfile, name);
1236                         if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
1237                         sfile->libfiledata= 0;
1238                 }
1239         }
1240         else {  /* FILE_BLENDER */
1241                 split_sfile(sfile, name);       /* test ook de filelist */
1242                 
1243                 /* vrijgeven: filelist en libfiledata kloppen niet meer */
1244                 if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
1245                 sfile->libfiledata= 0;
1246         }
1247         BLI_strncpy(sfile->title, title, sizeof(sfile->title));
1248         filetoname= 1;
1249 }
1250
1251 void activate_imageselect(int type, char *title, char *file, void (*func)(char *))
1252 {
1253         SpaceImaSel *simasel;
1254         char dir[FILE_MAXDIR], name[FILE_MAXFILE];
1255         
1256         if(curarea==0) return;
1257         if(curarea->win==0) return;
1258         
1259         newspace(curarea, SPACE_IMASEL);
1260         
1261         /* is misschien dubbelop, voor geval area al SPACE_FILE is met andere filename */
1262         addqueue(curarea->headwin, CHANGED, 1);
1263         addqueue(curarea->win, CHANGED, 1);
1264
1265         name[2]= 0;
1266         strcpy(name, file);
1267
1268         simasel= curarea->spacedata.first;
1269         simasel->returnfunc= func;
1270
1271         if(BLI_convertstringcode(name, G.sce, G.scene->r.cfra)) simasel->mode |= IMS_STRINGCODE;
1272         else simasel->mode &= ~IMS_STRINGCODE;
1273         
1274         BLI_split_dirfile(name, dir, simasel->file);
1275         if(strcmp(dir, simasel->dir)!=0) simasel->fase= 0;
1276         strcpy(simasel->dir, dir);
1277         
1278         BLI_strncpy(simasel->title, title, sizeof(simasel->title));
1279
1280         
1281         
1282         /* filetoname= 1; */
1283 }
1284
1285
1286 void activate_databrowse(ID *id, int idcode, int fromcode, int retval, short *menup, void (*func)(unsigned short))
1287 {
1288         ListBase *lb;
1289         SpaceFile *sfile;
1290         char str[32];
1291         
1292         if(id==0) {
1293                 lb= wich_libbase(G.main, idcode);
1294                 id= lb->first;
1295         }
1296         
1297         if(id) strcpy(str, id->name);
1298         else return;
1299         
1300         activate_fileselect(FILE_MAIN, "SELECT DATABLOCK", str, (void (*) (char*))func);
1301         
1302         sfile= curarea->spacedata.first;
1303         sfile->retval= retval;
1304         sfile->ipotype= fromcode;
1305         sfile->menup= menup;
1306 }
1307
1308 void filesel_prevspace()
1309 {
1310         SpaceFile *sfile;
1311         
1312         sfile= curarea->spacedata.first;
1313         if(sfile->next) {
1314         
1315                 BLI_remlink(&curarea->spacedata, sfile);
1316                 BLI_addtail(&curarea->spacedata, sfile);
1317
1318                 sfile= curarea->spacedata.first;
1319                 newspace(curarea, sfile->spacetype);
1320         }
1321         else newspace(curarea, SPACE_INFO);
1322 }
1323
1324 static int countselect(SpaceFile *sfile)
1325 {
1326         int a, count=0;
1327
1328         for(a=0; a<sfile->totfile; a++) {
1329                 if(sfile->filelist[a].flags & ACTIVE) {
1330                         count++;
1331                 }
1332         }
1333         return count;
1334 }
1335
1336 static int getotherdir(void)
1337 {
1338         ScrArea *sa;
1339         SpaceFile *sfile=0;
1340         
1341         sa= G.curscreen->areabase.first;
1342         while(sa) {
1343                 if(sa!=curarea) {
1344                         if(sa->spacetype==SPACE_FILE) {
1345                                 
1346                                 /* al een gevonden */
1347                                 if(sfile) return 0;
1348                 
1349                                 sfile= sa->spacedata.first;
1350
1351                                 if(sfile->type & FILE_UNIX) {
1352                                         otherarea= sa;
1353                                         BLI_make_file_string(G.sce, otherdir, sfile->dir, "");
1354                                 }
1355                                 else sfile= 0;
1356                         }
1357                 }
1358                 sa= sa->next;
1359         }
1360         if(sfile) return 1;
1361         return 0;
1362 }
1363
1364 static void reread_other_fs(void)
1365 {
1366         SpaceFile *sfile;
1367         
1368         /* oppassen: alleen aanroepen als getotherdir goed is afgelopen */
1369         
1370         sfile= otherarea->spacedata.first;
1371         freefilelist(sfile);
1372         scrarea_queue_winredraw(otherarea);
1373 }
1374
1375
1376 void free_filesel_spec(char *dir)
1377 {
1378         /* alle filesels met 'dir' worden vrijgegeven */
1379         bScreen *sc;
1380                 
1381         sc= G.main->screen.first;
1382         while(sc) {
1383                 ScrArea *sa= sc->areabase.first;
1384                 while(sa) {
1385                         SpaceLink  *sl= sa->spacedata.first;
1386                         while(sl) {
1387                                 if(sl->spacetype==SPACE_FILE) {
1388                                         SpaceFile *sfile= (SpaceFile*) sl;
1389                                         if (BLI_streq(sfile->dir, dir)) {
1390                                                 freefilelist(sfile);
1391                                         }
1392                                 }
1393                                 sl= sl->next;
1394                         }
1395                         sa= sa->next;
1396                 }
1397                 sc= sc->id.next;
1398         }
1399 }
1400
1401
1402 static void filesel_execute(SpaceFile *sfile)
1403 {
1404         struct direntry *files;
1405         char name[FILE_MAXDIR];
1406         int a;
1407         
1408         filesel_prevspace();
1409
1410         if(sfile->type==FILE_LOADLIB) {
1411                 do_library_append(sfile);
1412                 
1413                 allqueue(REDRAWALL, 1);
1414         }
1415         else if(sfile->returnfunc) {
1416                 fsmenu_insert_entry(sfile->dir, 1);
1417         
1418                 if(sfile->type==FILE_MAIN) {
1419                         if (sfile->menup) {
1420                                 if(sfile->act>=0) {
1421                                         if(sfile->filelist) {
1422                                                 files= sfile->filelist+sfile->act;
1423                                                 *sfile->menup= files->nr;
1424                                         }       
1425                                         else *sfile->menup= sfile->act+1;
1426                                 }
1427                                 else {
1428                                         *sfile->menup= -1;
1429                                         for(a=0; a<sfile->totfile; a++) {
1430                                                 if( strcmp(sfile->filelist[a].relname, sfile->file)==0) {
1431                                                         *sfile->menup= a+1;
1432                                                         break;
1433                                                 }
1434                                         }
1435                                 }
1436                         }
1437                         sfile->returnfunc((char*) sfile->retval);
1438                 }
1439                 else {
1440                         if(strncmp(sfile->title, "SAVE", 4)==0) free_filesel_spec(sfile->dir);
1441                         
1442                         strcpy(name, sfile->dir);
1443                         strcat(name, sfile->file);
1444                         
1445                         if(sfile->flag & FILE_STRINGCODE) BLI_makestringcode(G.sce, name);
1446
1447                         sfile->returnfunc(name);
1448                 }
1449         }
1450 }
1451
1452 static void do_filesel_buttons(short event, SpaceFile *sfile)
1453 {
1454         char butname[FILE_MAXDIR];
1455         
1456         if (event == 1) {
1457                 if (strchr(sfile->file, '*') || strchr(sfile->file, '?') || strchr(sfile->file, '[')) {
1458                         int i, match = FALSE;
1459                         
1460                         for (i = 2; i < sfile->totfile; i++) {
1461                                 if (fnmatch(sfile->file, sfile->filelist[i].relname, 0) == 0) {
1462                                         sfile->filelist[i].flags |= ACTIVE;
1463                                         match = TRUE;
1464                                 }
1465                         }
1466                         if (match) strcpy(sfile->file, "");
1467                         if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
1468                         scrarea_queue_winredraw(curarea);
1469                 }
1470         }
1471         else if(event== 2) {
1472                 /* reuse the butname variable */
1473                 checkdir(sfile->dir);
1474
1475                 BLI_make_file_string(G.sce, butname, sfile->dir, "");
1476                 /* strip the trailing slash if its a real dir */
1477                 if (strlen(butname)!=1)
1478                         butname[strlen(butname)-1]=0;
1479                 
1480                 if(sfile->type & FILE_UNIX) {
1481                         if (!BLI_exists(butname)) {
1482                                 if (okee("Makedir")) {
1483                                         BLI_recurdir_fileops(butname);
1484                                         if (!BLI_exists(butname)) parent(sfile);
1485                                 } else parent(sfile);
1486                         }
1487                 }
1488                 freefilelist(sfile);
1489                 sfile->ofs= 0;
1490                 scrarea_queue_winredraw(curarea);
1491         }
1492         else if(event== 3) {
1493                 char *selected= fsmenu_get_entry(sfile->menu-1);
1494                 
1495                 /* welke string */
1496                 if (selected) {
1497                         strcpy(sfile->dir, selected);
1498                         BLI_make_exist(sfile->dir);
1499                         checkdir(sfile->dir);
1500                         freefilelist(sfile);
1501                         sfile->ofs= 0;
1502                         scrarea_queue_winredraw(curarea);
1503                 }
1504
1505                 sfile->act= -1;
1506                 
1507         }
1508         else if(event== 4) parent(sfile);
1509         else if(event== 5) {
1510                 if(sfile->type) filesel_execute(sfile);
1511         }
1512         else if(event== 6) filesel_prevspace();
1513         
1514 }
1515
1516 /****/
1517
1518 typedef void (*ReplaceFP)(ID *oldblock, ID *newblock);
1519
1520 static void change_id_link(void *linkpv, void *newlinkv) {
1521         ID **linkp= (ID**) linkpv;
1522         ID *newlink= newlinkv;
1523
1524         if (*linkp) {
1525                 (*linkp)->us--;
1526         }
1527         (*linkp)= newlink;
1528         if (newlink) {
1529                 id_us_plus(newlink);
1530         }
1531 }
1532
1533 static void replace_image(ID *oldblock, ID *newblock) {
1534         Image *oldima= (Image*) oldblock;
1535         Image *newima= (Image*) newblock;
1536         bScreen *sc;
1537         Scene *sce;
1538         Tex *tex;
1539         Mesh *me;
1540
1541         for (tex= G.main->tex.first; tex; tex= tex->id.next) {
1542                 if (tex->env && tex->env->type == ENV_LOAD && tex->env->ima == oldima)
1543                         change_id_link(&tex->env->ima, newima);
1544                 if (tex->ima == oldima)
1545                         change_id_link(&tex->ima, newima);
1546         }
1547
1548         for (sce= G.main->scene.first; sce; sce= sce->id.next) {
1549                 if (sce->ima == oldima)
1550                         change_id_link(&sce->ima, newima);
1551         }
1552
1553         for (sc= G.main->screen.first; sc; sc= sc->id.next) {
1554                 ScrArea *sa;
1555
1556                 for (sa= sc->areabase.first; sa; sa= sa->next) {
1557                         SpaceLink *sl;
1558
1559                         for (sl= sa->spacedata.first; sl; sl= sl->next) {
1560                                 if (sl->spacetype == SPACE_VIEW3D) {
1561                                         View3D *v3d= (View3D*) sl;
1562                                         BGpic *bgp= v3d->bgpic;
1563
1564                                         if (bgp && bgp->ima == oldima) 
1565                                                 change_id_link(&bgp->ima, newima);
1566                                 } else if (sl->spacetype == SPACE_IMAGE) {
1567                                         SpaceImage *sima= (SpaceImage*) sl;
1568                                         
1569                                         if (sima->image == oldima)
1570                                                 change_id_link(&sima->image, newima);
1571                                 }
1572                         }
1573                 }
1574         }
1575
1576         for (me= G.main->mesh.first; me; me= me->id.next) {
1577                 TFace *tfaces= me->tface;
1578
1579                 if (tfaces) {
1580                         int i;
1581
1582                         for (i=0; i<me->totface; i++) {
1583                                 TFace *tf= &tfaces[i];
1584
1585                                 if (tf->tpage == oldima) {
1586                                                 /* not change_id_link, tpage's aren't owners :(
1587                                                  * see hack below.
1588                                                  */
1589                                         tf->tpage= newima;
1590                                 }
1591                         }
1592                 }
1593         }
1594
1595                 /* Nasty hack, necessary because tpages don't act
1596                  * as a user, so there lots of image user count
1597                  * munging occurs... this will ensure the image
1598                  * really dies.
1599                  */
1600         oldima->id.us= 0;
1601 }
1602
1603 static void replace_material(ID *oldblock, ID *newblock)
1604 {
1605         Material *old= (Material*) oldblock;
1606         Material *new= (Material*) newblock;
1607         Material ***matarar;
1608         ID *id;
1609         Object *ob;
1610         int a;
1611         
1612         ob= G.main->object.first;
1613         while(ob) {
1614                 if(ob->totcol && ob->id.lib==0) {
1615                         matarar= give_matarar(ob);
1616                         for(a=1; a<=ob->totcol; a++) {
1617                                 if(ob->mat[a-1] == old) {
1618                                         if(old) old->id.us--;
1619                                         id_us_plus((ID *)new);
1620                                         ob->mat[a-1]= new;
1621                                 }
1622                                 id= ob->data;
1623                                 if( (*matarar)[a-1] == old  && id->lib==0) {
1624                                         if(old) old->id.us--;
1625                                         id_us_plus((ID *)new);
1626                                         (*matarar)[a-1]= new;
1627                                 }
1628                         }
1629                 }
1630                 ob= ob->id.next;
1631         }
1632 }
1633
1634 static ReplaceFP get_id_replace_function(int idcode) {
1635         switch (idcode) {
1636         case ID_MA:
1637                 return &replace_material;
1638         case ID_IM:
1639                 return &replace_image;
1640         default:
1641                 return NULL;
1642         }
1643 }
1644
1645 static void databrowse_replace(SpaceFile *sfile, int idcode)
1646 {
1647         ReplaceFP replace_func= get_id_replace_function(idcode);
1648
1649         if (!replace_func) {
1650                 error("Replacing %s blocks is unsupported", BLO_idcode_to_name(idcode));
1651         } else if (sfile->act==-1) {
1652                 error("Select target with leftmouse");
1653         } else {
1654                 ID *target= (ID*) sfile->filelist[sfile->act].poin;
1655
1656                 if (target) {
1657                         char buf[128];
1658
1659                         sprintf(buf, "Replace with %s: %s", BLO_idcode_to_name(idcode), target->name+2);
1660
1661                         if (okee(buf)) {
1662                                 int i;
1663
1664                                 for (i = 0; i <sfile->totfile; i++)
1665                                         if ((sfile->filelist[i].flags&ACTIVE) && sfile->filelist[i].poin!=target)
1666                                                 replace_func(sfile->filelist[i].poin, target);
1667                         }
1668                 }
1669         }
1670
1671         freefilelist(sfile);
1672         scrarea_queue_winredraw(curarea);
1673 }
1674
1675 static void fs_fake_users(SpaceFile *sfile)
1676 {
1677         ID *id;
1678         int a;
1679         
1680         /* alleen bij F4 DATABROWSE */
1681         if(sfile->returnfunc) return;
1682         
1683         for(a=0; a<sfile->totfile; a++) {
1684                 if(sfile->filelist[a].flags & ACTIVE) {
1685                         id= (ID *)sfile->filelist[a].poin;
1686                         if(id) {
1687                                 if( id->flag & LIB_FAKEUSER) {
1688                                         id->flag -= LIB_FAKEUSER;
1689                                         id->us--;
1690                                 }
1691                                 else {
1692                                         id->flag |= LIB_FAKEUSER;
1693                                         id->us++;
1694                                 }
1695                         }
1696                 }
1697         }
1698         freefilelist(sfile);
1699         scrarea_queue_winredraw(curarea);
1700 }
1701
1702 void winqreadfilespace(unsigned short event, short val, char ascii)
1703 {
1704         static int acto=0;
1705         SpaceFile *sfile;
1706         int act, do_draw= 0, i, test, ret = 0;
1707         short qual, mval[2];
1708         char str[FILE_MAXDIR+FILE_MAXFILE+12];
1709         
1710         sfile= curarea->spacedata.first;
1711         if(sfile==0) return;
1712         if(sfile->filelist==0) {
1713                 /* wel buttons doen */
1714                 if(val && event==LEFTMOUSE) {
1715                         /* FrontbufferButs(TRUE); */
1716                         /* event= DoButtons(); */
1717                         /* FrontbufferButs(FALSE); */
1718                                         /*  NIET de headerbuttons! */
1719                         /* if(event) do_filesel_buttons(event, sfile); */
1720                 }
1721                 return;
1722         }
1723         
1724         if(curarea->win==0) return;
1725         calc_file_rcts(sfile);
1726         getmouseco_areawin(mval);
1727
1728         /* om hangen te voorkomen */
1729         if(selecting && !(get_mbut() & R_MOUSE)) selecting= 0;
1730
1731         if(val) {
1732
1733                 if( event!=RETKEY && event!=PADENTER)
1734                         if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
1735
1736                 switch(event) {
1737                 
1738                 case UI_BUT_EVENT:
1739                         do_filesel_buttons(val, sfile);
1740                         break;          
1741                 
1742                 case WHEELDOWNMOUSE:
1743                         do_filescrollwheel(sfile, U.wheellinescroll);
1744                         act= find_active_file(sfile, mval[0], mval[1]);
1745                         set_active_file(sfile, act);
1746                         do_draw= 1;
1747                         break;
1748                 case WHEELUPMOUSE:
1749                         do_filescrollwheel(sfile, -U.wheellinescroll);
1750                         act= find_active_file(sfile, mval[0], mval[1]);
1751                         set_active_file(sfile, act);
1752                         do_draw= 1;
1753                         break;
1754
1755                 case LEFTMOUSE:
1756                 case MIDDLEMOUSE:
1757                         if(mval[0]>scrollrct.xmin && mval[0]<scrollrct.xmax && mval[1]>scrollrct.ymin && mval[1]<scrollrct.ymax) {
1758                                 do_filescroll(sfile);
1759                         }
1760                         else if(mval[0]>textrct.xmin && mval[0]<textrct.xmax && mval[1]>textrct.ymin && mval[1]<textrct.ymax) {
1761                                 
1762                                 /* sfile->act wordt gebruikt bij databrowse: dubbelenamen van library objecten */
1763                                 
1764                                 sfile->act= act= find_active_file(sfile, mval[0], mval[1]);
1765                                 
1766                                 if(act>=0 && act<sfile->totfile) {
1767                                         if(S_ISDIR(sfile->filelist[act].type)) {
1768                                                 strcat(sfile->dir, sfile->filelist[act].relname);
1769                                                 strcat(sfile->dir,"/");
1770                                                 checkdir(sfile->dir);
1771                                                 freefilelist(sfile);
1772                                                 sfile->ofs= 0;
1773                                                 do_draw= 1;
1774                                         }
1775                                         else {
1776                                                 if( strcmp(sfile->file, sfile->filelist[act].relname)) {
1777                                                         do_draw= 1;
1778                                                         strcpy(sfile->file, sfile->filelist[act].relname);
1779                                                 }
1780                                                 if(event==MIDDLEMOUSE && sfile->type) filesel_execute(sfile);
1781                                         }
1782                                 }
1783                         }
1784                         else {
1785                                 /* FrontbufferButs(TRUE); */
1786                                 /* event= DoButtons(); */
1787                                 /* FrontbufferButs(FALSE); */
1788                                         /*  NIET de headerbuttons! */
1789                                 /* if(event) do_filesel_buttons(event, sfile);   */
1790                         }
1791                         break;
1792                 case RIGHTMOUSE:
1793                         act= find_active_file(sfile, mval[0], mval[1]);
1794                         acto= act;
1795                         if(act>=0 && act<sfile->totfile) {
1796
1797                                 if (sfile->filelist[act].flags & ACTIVE) {
1798                                         sfile->filelist[act].flags &= ~ACTIVE;
1799                                         selecting = INACTIVATE;
1800                                 }
1801                                 else {
1802                                         test= sfile->filelist[act].relname[0];
1803                                         if (act>=2 || test!='.') sfile->filelist[act].flags |= ACTIVE;
1804                                         
1805                                         selecting = ACTIVATE;
1806                                 }
1807                                 do_draw= 1;
1808                         }
1809                         break;
1810                 case MOUSEY:
1811                         act= find_active_file(sfile, mval[0], mval[1]);
1812                         if (act!=acto) {
1813                                 set_active_file(sfile, act);
1814                         }
1815                         if(selecting && act!=acto) {
1816                                         
1817                                 while(1) {
1818                                         if (acto >= 2 && acto < sfile->totfile) {
1819                                                 if (selecting == ACTIVATE) sfile->filelist[acto].flags |= ACTIVE;
1820                                                 else if (selecting == INACTIVATE) sfile->filelist[acto].flags &= ~ACTIVE;
1821                                         }
1822                                         if (acto < act) acto++;
1823                                         else if (acto > act) acto--;
1824                                         else break;
1825                                         
1826                                 }
1827
1828                         }
1829                         acto= act;
1830                         break;
1831                 
1832                 case PAGEUPKEY:
1833                         sfile->ofs-= page_ofs;
1834                         do_draw= 1;
1835                         break;
1836                 case PAGEDOWNKEY:
1837                         sfile->ofs+= page_ofs;
1838                         do_draw= 1;
1839                         break;
1840                 case HOMEKEY:
1841                         sfile->ofs= 0;
1842                         do_draw= 1;
1843                         break;
1844                 case ENDKEY:
1845                         sfile->ofs= sfile->totfile;
1846                         do_draw= 1;
1847                         break;
1848                 
1849                 case AKEY:
1850                         swapselect_file(sfile);
1851                         if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
1852                         do_draw= 1;
1853                         break;
1854                         
1855                 case BKEY:
1856                 case CKEY:
1857                 case LKEY:
1858                         if(event==LKEY && sfile->type==FILE_MAIN && (G.qual & LR_CTRLKEY)) {
1859                                 databrowse_replace(sfile, groupname_to_code(sfile->dir));
1860                                 break;
1861                         }
1862                         /* doorgeven */
1863                 case MKEY:
1864                         if(sfile->type==FILE_MAIN) break;
1865
1866                         if(!countselect(sfile)) {
1867                                 error("No files selected");
1868                                 break;
1869                         }
1870                         
1871                         if(!getotherdir()) {
1872                                 error("No second fileselect");
1873                                 break;
1874                         }
1875                         
1876                         if (!strcmp(sfile->dir, otherdir)) {
1877                                 error("Same directories");
1878                                 break;
1879                         }
1880
1881                         if(event==BKEY) sprintf(str, "Backup to %s", otherdir);
1882                         else if(event==CKEY) sprintf(str, "Copy to %s", otherdir);
1883                         else if(event==LKEY) sprintf(str, "Linked copy to %s", otherdir);
1884                         else if(event==MKEY) sprintf(str, "Move to %s", otherdir);
1885                                         
1886                         if (!okee(str)) break;
1887
1888                         for (i = 0; i<sfile->totfile; i++){
1889                                 if (sfile->filelist[i].flags & ACTIVE) {                        
1890                                         BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[i].relname);
1891
1892                                         if(event==BKEY) ret= BLI_backup(sfile->filelist[i].relname, sfile->dir, otherdir);
1893                                         else if(event==CKEY) ret= BLI_copy_fileops(str, otherdir);
1894                                         else if(event==LKEY) ret= BLI_link(str, otherdir);
1895                                         else if(event==MKEY) ret= BLI_move(str, otherdir);
1896
1897                                         if (ret) {error("Command failed, see console"); break;}
1898                                         else sfile->filelist[i].flags &= ~ACTIVE;
1899                                 }
1900                         }
1901                         do_draw= 1;
1902                         if(event==BKEY || event==MKEY) 
1903                                 freefilelist(sfile);
1904                                 
1905                         reread_other_fs();
1906                         
1907                         break;
1908                 case RKEY:
1909                         if(sfile->type==FILE_MAIN) {
1910                                 databrowse_replace(sfile, groupname_to_code(sfile->dir));
1911                                 break;
1912                         }
1913                         /* doorgeven aan TKEY! */
1914                         
1915                 case TKEY:
1916                         if(sfile->type==FILE_MAIN) break;
1917                         
1918                         if(!countselect(sfile)) {
1919                                 error("No files selected");
1920                                 break;
1921                         }
1922
1923                         if(event==TKEY) sprintf(str, "Touch");
1924                         else if(event==RKEY) sprintf(str, "Remove from %s", sfile->dir);
1925                         
1926                         qual= G.qual;   /* want na okee() heb je de shift losgelaten */
1927                         if (!okee(str)) break;
1928                         
1929                         for (i = 0; i <sfile->totfile; i++) {
1930                                 if (sfile->filelist[i].flags & ACTIVE) {
1931                                         BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[i].relname);
1932
1933                                         if(event==TKEY) ret= BLI_touch(str);
1934                                         else if(event==RKEY) {
1935                                                 if(qual & LR_SHIFTKEY) ret= BLI_delete(str, 0, 1);
1936                                                 else if(S_ISDIR(sfile->filelist[i].type)) ret= BLI_delete(str, 1, 0);
1937                                                 else ret= BLI_delete(str, 0, 0);
1938                                         }
1939
1940                                         if (ret) {error("Command failed, see console"); break;}
1941                                         else sfile->filelist[i].flags &= ~ACTIVE;
1942                                 }
1943                         }
1944                         do_draw= 1;
1945                         freefilelist(sfile);
1946
1947                         break;
1948                                 
1949                 case PKEY:
1950                         if(G.qual & LR_SHIFTKEY) {
1951                                 extern char bprogname[];        /* usiblender.c */
1952                         
1953                                 sprintf(str, "%s -a \"%s%s\"", bprogname, sfile->dir, sfile->file);
1954                                 system(str);
1955                         }
1956                         else 
1957                                 parent(sfile);
1958                                 
1959                         break;
1960
1961                 case IKEY:
1962                         if(sfile->type==FILE_MAIN) break;
1963                         
1964                         sprintf(str, "$IMAGEEDITOR %s%s", sfile->dir, sfile->file);
1965                         system(str);
1966                         break;
1967                 
1968                 case EKEY:
1969                         if(sfile->type==FILE_MAIN) break;
1970                         
1971                         sprintf(str, "$WINEDITOR %s%s", sfile->dir, sfile->file);
1972                         system(str);
1973                         break;
1974                 
1975                 case FKEY:
1976                         if(sfile->type==FILE_MAIN) {
1977                                 fs_fake_users(sfile);
1978                         }
1979                         break;
1980                                 
1981                 case PADPLUSKEY:
1982                 case EQUALKEY:
1983                         if (G.qual & LR_CTRLKEY) BLI_newname(sfile->file, +100);
1984                         else if (G.qual & LR_SHIFTKEY) BLI_newname(sfile->file, +10);
1985                         else BLI_newname(sfile->file, +1);
1986                         
1987                         do_draw= 1;
1988                         break;
1989                         
1990                 case PADMINUS:
1991                 case MINUSKEY:
1992                         if (G.qual & LR_CTRLKEY) BLI_newname(sfile->file, -100);
1993                         else if (G.qual & LR_SHIFTKEY) BLI_newname(sfile->file, -10);
1994                         else BLI_newname(sfile->file, -1);
1995                         
1996                         do_draw= 1;
1997                         break;
1998                         
1999                 case BACKSLASHKEY:
2000                 case SLASHKEY:
2001                         if(sfile->type==FILE_MAIN) break;
2002
2003 #ifdef WIN32
2004                         strcpy(sfile->dir, "\\");
2005 #else
2006                         strcpy(sfile->dir, "/");
2007 #endif
2008                         freefilelist(sfile);
2009                         sfile->ofs= 0;
2010                         do_draw= 1;
2011                         break;
2012                 case PERIODKEY:
2013                         freefilelist(sfile);
2014                         do_draw= 1;
2015                         break;
2016                 case ESCKEY:
2017                         filesel_prevspace();
2018                         break;
2019                 case PADENTER:
2020                 case RETKEY:
2021                         if(sfile->type) filesel_execute(sfile);
2022                         break;
2023                 }
2024         }
2025         else if(event==RIGHTMOUSE) {
2026                 selecting = NOTACTIVE;
2027                 if(sfile->type==FILE_MAIN) filesel_select_objects(sfile);
2028         }
2029         else if(event==LEFTMOUSE) {
2030                 if(sfile->type==FILE_MAIN) active_file_object(sfile);
2031         }
2032
2033                 /* XXX, stupid patch, curarea can become undone
2034                  * because of file loading... fixme zr
2035                  */
2036         if(do_draw && curarea) scrarea_queue_winredraw(curarea);
2037 }
2038
2039
2040
2041
2042 /* ************* LIBRARY FILESEL ******************* */
2043
2044 static int groupname_to_code(char *group)
2045 {
2046         char buf[32];
2047         char *lslash;
2048         
2049         strcpy(buf, group);
2050         lslash= BLI_last_slash(buf);
2051         if (lslash)
2052                 lslash[0]= '\0';
2053
2054         return BLO_idcode_from_name(buf);
2055 }
2056
2057 static int is_a_library(SpaceFile *sfile, char *dir, char *group)
2058 {
2059         /* return ok als een blenderfile, in dir staat de filename,
2060          * in group het type libdata
2061          */
2062         int len;
2063         char *fd;
2064         
2065         strcpy(dir, sfile->dir);
2066         len= strlen(dir);
2067         if(len<7) return 0;
2068         if( dir[len-1] != '/' && dir[len-1] != '\\') return 0;
2069         
2070         group[0]= 0;
2071         dir[len-1]= 0;
2072
2073         /* Find the last slash */
2074         fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
2075
2076         if(fd==0) return 0;
2077         *fd= 0;
2078         if(BLO_has_bfile_extension(fd+1)) {
2079                 *fd= '/';
2080         }
2081         else {
2082                 strcpy(group, fd+1);
2083                         
2084                 /* Find the last slash */
2085                 fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
2086                 if (!fd || !BLO_has_bfile_extension(fd+1)) return 0;
2087         }
2088         return 1;
2089 }
2090
2091 static void do_library_append(SpaceFile *sfile)
2092 {
2093         char dir[FILE_MAXDIR], group[32];
2094         
2095         if ( is_a_library(sfile, dir, group)==0 ) {
2096                 error("Not a library");
2097         } else if (!sfile->libfiledata) {
2098                 error("Library not loaded");
2099         } else if (group[0]==0) {
2100                 error("Nothing indicated");
2101         } else if (BLI_streq(G.main->name, dir)) {
2102                 error("Cannot use current file as library");
2103         } else {
2104                 Object *ob;
2105                 int idcode = groupname_to_code(group);
2106                 
2107                 BLO_library_append(sfile, dir, idcode);
2108
2109                 /* DISPLISTEN */
2110                 ob= G.main->object.first;
2111                 set_displist_onlyzero(1);
2112                 while(ob) {
2113                         if(ob->id.lib) {
2114                                 if(ob->type==OB_FONT) {
2115                                         Curve *cu= ob->data;
2116                                         if(cu->nurb.first==0) text_to_curve(ob, 0);
2117                                 }
2118                                 makeDispList(ob);
2119                         }
2120                         else if(ob->type==OB_MESH && ob->parent && ob->parent->type==OB_LATTICE ) {
2121                                 makeDispList(ob);
2122                         }
2123                         
2124                         ob= ob->id.next;
2125                 }
2126                 set_displist_onlyzero(0);
2127         
2128                 /* in sfile->dir staat de HELE libnaam */
2129                 strcpy(G.lib, sfile->dir);
2130                 
2131                 if((sfile->flag & FILE_LINK)==0) all_local();
2132         }
2133 }
2134
2135 static void library_to_filelist(SpaceFile *sfile)
2136 {
2137         char dir[FILE_MAXDIR], group[24];
2138         int ok, i, nnames, idcode;
2139         LinkNode *l, *names;
2140         
2141         /* name testen */
2142         ok= is_a_library(sfile, dir, group);
2143         if (!ok) {
2144                 /* vrijgeven */
2145                 if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata);
2146                 sfile->libfiledata= 0;
2147                 return;
2148         }
2149         
2150         /* en daar gaat ie */
2151         /* voorlopig alleen filedata inlezen als libfiledata==0 */
2152         if (sfile->libfiledata==0) {
2153                 sfile->libfiledata= BLO_blendhandle_from_file(dir);
2154                 if(sfile->libfiledata==0) return;
2155         }
2156         
2157         if (idcode= groupname_to_code(group)) {
2158                 names= BLO_blendhandle_get_datablock_names(sfile->libfiledata, idcode);
2159         } else {
2160                 names= BLO_blendhandle_get_linkable_groups(sfile->libfiledata);
2161         }
2162         
2163         nnames= BLI_linklist_length(names);
2164
2165         sfile->totfile= nnames + 2;
2166         sfile->filelist= malloc(sfile->totfile * sizeof(*sfile->filelist));
2167         memset(sfile->filelist, 0, sfile->totfile * sizeof(*sfile->filelist));
2168
2169         sfile->filelist[0].relname= strdup(".");
2170         sfile->filelist[0].type |= S_IFDIR;
2171         sfile->filelist[1].relname= strdup("..");
2172         sfile->filelist[1].type |= S_IFDIR;
2173                 
2174         for (i=0, l= names; i<nnames; i++, l= l->next) {
2175                 char *blockname= l->link;
2176
2177                 sfile->filelist[i + 2].relname= blockname;
2178                 if (!idcode)
2179                         sfile->filelist[i + 2].type |= S_IFDIR;
2180         }
2181                 
2182         BLI_linklist_free(names, NULL);
2183         
2184         qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
2185         
2186         sfile->maxnamelen= 0;
2187         for(i=0; i<sfile->totfile; i++) {
2188                 int len = BMF_GetStringWidth(G.font, sfile->filelist[i].relname);
2189                 if (len > sfile->maxnamelen)
2190                         sfile->maxnamelen = len;
2191         }
2192 }
2193
2194 /* ******************* DATA SELECT ********************* */
2195
2196 static void filesel_select_objects(SpaceFile *sfile)
2197 {
2198         Object *ob;
2199         Base *base;
2200         Scene *sce;
2201         int a;
2202         
2203         /* alleen bij F4 DATABROWSE */
2204         if(sfile->returnfunc) return;
2205         
2206         if( strcmp(sfile->dir, "Object/")==0 ) {
2207                 for(a=0; a<sfile->totfile; a++) {
2208                         
2209                         ob= (Object *)sfile->filelist[a].poin;
2210                         
2211                         if(ob) {
2212                                 if(sfile->filelist[a].flags & ACTIVE) ob->flag |= SELECT;
2213                                 else ob->flag &= ~SELECT;
2214                         }
2215
2216                 }
2217                 base= FIRSTBASE;
2218                 while(base) {
2219                         base->flag= base->object->flag;
2220                         base= base->next;
2221                 }
2222                 allqueue(REDRAWVIEW3D, 0);
2223         }
2224         else if( strcmp(sfile->dir, "Scene/")==0 ) {
2225                 
2226                 for(a=0; a<sfile->totfile; a++) {
2227                         
2228                         sce= (Scene *)sfile->filelist[a].poin;
2229                         if(sce) {
2230                                 if(sfile->filelist[a].flags & ACTIVE) sce->r.scemode |= R_BG_RENDER;
2231                                 else sce->r.scemode &= ~R_BG_RENDER;
2232                         }
2233
2234                 }
2235                 allqueue(REDRAWBUTSRENDER, 0);
2236         }
2237 }
2238
2239 static void active_file_object(SpaceFile *sfile)
2240 {
2241         Object *ob;
2242         
2243         /* alleen bij F4 DATABROWSE */
2244         if(sfile->returnfunc) return;
2245         
2246         if( strcmp(sfile->dir, "Object/")==0 ) {
2247                 if(sfile->act >= 0) {
2248                         
2249                         ob= (Object *)sfile->filelist[sfile->act].poin;
2250                         
2251                         if(ob) {
2252                                 set_active_object(ob);
2253                                 if(BASACT && BASACT->object==ob) {
2254                                         BASACT->flag |= SELECT;
2255                                         sfile->filelist[sfile->act].flags |= ACTIVE;
2256                                         allqueue(REDRAWVIEW3D, 0);
2257                                         scrarea_queue_winredraw(curarea);
2258                                 }
2259                         }
2260                 }
2261         }
2262 }
2263
2264
2265 void main_to_filelist(SpaceFile *sfile)
2266 {
2267         ID *id;
2268         struct direntry *files, *firstlib = NULL;
2269         ListBase *lb;
2270         int a, fake, idcode, len, ok, totlib, totbl;
2271
2272         if(sfile->dir[0]=='/') sfile->dir[0]= 0;
2273         
2274         if(sfile->dir[0]) {
2275                 idcode= groupname_to_code(sfile->dir);
2276                 if(idcode==0) sfile->dir[0]= 0;
2277         }
2278         
2279         if( sfile->dir[0]==0) {
2280                 
2281                 /* directories maken */
2282                 sfile->totfile= 22;
2283                 sfile->filelist= (struct direntry *)malloc(sfile->totfile * sizeof(struct direntry));
2284                 
2285                 for(a=0; a<sfile->totfile; a++) {
2286                         memset( &(sfile->filelist[a]), 0 , sizeof(struct direntry));
2287                         sfile->filelist[a].type |= S_IFDIR;
2288                 }
2289                 
2290                 sfile->filelist[0].relname= strdup("..");
2291                 sfile->filelist[1].relname= strdup(".");
2292                 sfile->filelist[2].relname= strdup("Scene");
2293                 sfile->filelist[3].relname= strdup("Object");
2294                 sfile->filelist[4].relname= strdup("Mesh");
2295                 sfile->filelist[5].relname= strdup("Curve");
2296                 sfile->filelist[6].relname= strdup("Metaball");
2297                 sfile->filelist[7].relname= strdup("Material");
2298                 sfile->filelist[8].relname= strdup("Texture");
2299                 sfile->filelist[9].relname= strdup("Image");
2300                 sfile->filelist[10].relname= strdup("Ika");
2301                 sfile->filelist[11].relname= strdup("Wave");
2302                 sfile->filelist[12].relname= strdup("Lattice");
2303                 sfile->filelist[13].relname= strdup("Lamp");
2304                 sfile->filelist[14].relname= strdup("Camera");
2305                 sfile->filelist[15].relname= strdup("Ipo");
2306                 sfile->filelist[16].relname= strdup("World");
2307                 sfile->filelist[17].relname= strdup("Screen");
2308                 sfile->filelist[18].relname= strdup("VFont");
2309                 sfile->filelist[19].relname= strdup("Text");
2310                 sfile->filelist[20].relname= strdup("Armature");
2311                 sfile->filelist[21].relname= strdup("Action");
2312                 qsort(sfile->filelist, sfile->totfile, sizeof(struct direntry), compare_name);
2313         }
2314         else {
2315
2316                 /* files maken */
2317                 idcode= groupname_to_code(sfile->dir);
2318                 
2319                 lb= wich_libbase(G.main, idcode );
2320                 if(lb==0) return;
2321                 
2322                 id= lb->first;
2323                 sfile->totfile= 0;
2324                 while(id) {
2325                         
2326                         if(sfile->returnfunc && idcode==ID_IP) {
2327                                 if(sfile->ipotype== ((Ipo *)id)->blocktype) sfile->totfile++;
2328                         }
2329                         else sfile->totfile++;
2330                         
2331                         id= id->next;
2332                 }
2333                 
2334                 if(sfile->returnfunc==0) sfile->totfile+= 2;
2335                 sfile->filelist= (struct direntry *)malloc(sfile->totfile * sizeof(struct direntry));
2336                 
2337                 files= sfile->filelist;
2338                 
2339                 if(sfile->returnfunc==0) {
2340                         memset( &(sfile->filelist[0]), 0 , sizeof(struct direntry));
2341                         sfile->filelist[0].relname= strdup(".");
2342                         sfile->filelist[0].type |= S_IFDIR;
2343                         memset( &(sfile->filelist[1]), 0 , sizeof(struct direntry));
2344                         sfile->filelist[1].relname= strdup("..");
2345                         sfile->filelist[1].type |= S_IFDIR;
2346                 
2347                         files+= 2;
2348                 }
2349                 
2350                 id= lb->first;
2351                 totlib= totbl= 0;
2352                 
2353                 while(id) {
2354                         
2355                         ok= 0;
2356                         if(sfile->returnfunc && idcode==ID_IP) {
2357                                 if(sfile->ipotype== ((Ipo *)id)->blocktype) ok= 1;
2358                         }
2359                         else ok= 1;
2360                         
2361                         if(ok) {
2362                 
2363                                 memset( files, 0 , sizeof(struct direntry));
2364                                 files->relname= strdup(id->name+2);
2365                                 
2366                                 if(sfile->returnfunc==0) { /* F4 DATA BROWSE */
2367                                         if(idcode==ID_OB) {
2368                                                 if( ((Object *)id)->flag & SELECT) files->flags |= ACTIVE;
2369                                         }
2370                                         else if(idcode==ID_SCE) {
2371                                                 if( ((Scene *)id)->r.scemode & R_BG_RENDER) files->flags |= ACTIVE;
2372                                         }
2373                                 }
2374                                 files->nr= totbl+1;
2375                                 files->poin= id;
2376                                 fake= id->flag & LIB_FAKEUSER;
2377                                 
2378                                 if(id->lib && fake) sprintf(files->extra, "LF %d", id->us);
2379                                 else if(id->lib) sprintf(files->extra, "L    %d", id->us);
2380                                 else if(fake) sprintf(files->extra, "F    %d", id->us);
2381                                 else sprintf(files->extra, "      %d", id->us);
2382                                 
2383                                 if(id->lib) {
2384                                         if(totlib==0) firstlib= files;
2385                                         totlib++;
2386                                 }
2387                                 
2388                                 files++;
2389                                 totbl++;
2390                         }
2391                         
2392                         id= id->next;
2393                 }
2394                 
2395                 /* alleen qsort van libraryblokken */
2396                 if(totlib>1) {
2397                         qsort(firstlib, totlib, sizeof(struct direntry), compare_name);
2398                 }
2399         }
2400
2401         sfile->maxnamelen= 0;
2402         for(a=0; a<sfile->totfile; a++) {
2403                 len = BMF_GetStringWidth(G.font, sfile->filelist[a].relname);
2404                 if (len > sfile->maxnamelen) sfile->maxnamelen = len;
2405                 
2406                 if(filetoname) {
2407                         if( strcmp(sfile->file, sfile->filelist[a].relname)==0) {
2408                                 sfile->ofs= a-( sfile->collums*(curarea->winy-FILESELHEAD-10)/(2*FILESEL_DY));
2409                                 filetoname= 0;
2410                                 if(sfile->returnfunc) sfile->filelist[a].flags |= ACTIVE;
2411                         }
2412                 }
2413         }
2414 }
2415
2416
2417