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