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