don't display relative paths button when loading files.
[blender.git] / source / blender / src / editimasel.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 <stdio.h>
36 #include <math.h>
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #ifndef WIN32
43 #include <sys/times.h>
44 #endif
45
46 #include "MEM_guardedalloc.h"
47
48 #include "BKE_global.h"
49 #include "BKE_library.h"
50 #include "BKE_main.h"
51 #include "BKE_depsgraph.h"
52 #include "BKE_utildefines.h"
53
54 #include "BLI_blenlib.h"
55 #include "BLI_arithb.h"
56 #include "BLI_storage_types.h"
57
58 #ifdef WIN32
59 #include "BLI_winstuff.h"
60 #endif
61
62 #include "DNA_armature_types.h"
63 #include "DNA_action_types.h"
64 #include "DNA_curve_types.h"
65 #include "DNA_image_types.h"
66 #include "DNA_ipo_types.h"
67 #include "DNA_material_types.h"
68 #include "DNA_mesh_types.h"
69 #include "DNA_object_types.h"
70 #include "DNA_texture_types.h"
71 #include "DNA_space_types.h"
72 #include "DNA_scene_types.h"
73 #include "DNA_screen_types.h"
74 #include "DNA_userdef_types.h"
75 #include "DNA_vfont_types.h"
76 #include "DNA_view3d_types.h"
77
78
79 #include "BIF_filelist.h"
80 #include "BIF_space.h"
81 #include "BIF_screen.h"
82 #include "BIF_interface.h"
83 #include "BIF_mywindow.h"
84 #include "BIF_imasel.h"
85 #include "BIF_gl.h"
86 #include "BIF_fsmenu.h"
87 #include "BIF_editview.h"
88 #include "BIF_toolbox.h"
89
90 #include "BLO_readfile.h"
91
92 #include "BPI_script.h"
93
94 #include "BSE_drawipo.h"
95 #include "BSE_drawimasel.h"
96 #include "BSE_edit.h"
97
98 #include "IMB_imbuf.h"
99 #include "IMB_imbuf_types.h"
100
101 #include "blendef.h"
102 #include "mydevice.h"
103
104 /* for events */
105 #define NOTACTIVE                       0
106 #define ACTIVATE                        1
107 #define INACTIVATE                      2
108 /* for state of file */
109 #define ACTIVE                          2
110
111 static void imasel_select_objects(SpaceImaSel *simasel);
112
113 static int imasel_has_func(SpaceImaSel *simasel)
114 {
115         if(simasel->returnfunc || simasel->returnfunc_event || simasel->returnfunc_args)
116                 return 1;
117         return 0;
118 }
119
120 #if defined __BeOS
121 static int fnmatch(const char *pattern, const char *string, int flags)
122 {
123         return 0;
124 }
125 #elif defined WIN32 && !defined _LIBC
126         /* use fnmatch included in blenlib */
127         #include "BLI_fnmatch.h"
128 #else
129         #include <fnmatch.h>
130 #endif
131
132 static void imasel_split_file(SpaceImaSel *simasel, char *s1)
133 {
134         char string[FILE_MAX], dir[FILE_MAX], file[FILE_MAX];
135
136         BLI_strncpy(string, s1, sizeof(string));
137
138         BLI_split_dirfile(string, dir, file);
139         
140         if(simasel->files) {
141                 BIF_filelist_free(simasel->files);
142         }
143         BLI_strncpy(simasel->file, file, sizeof(simasel->file));
144         BLI_strncpy(simasel->dir, dir, sizeof(simasel->dir));
145
146         BIF_filelist_setdir(simasel->files, dir);
147
148         BLI_make_file_string(G.sce, simasel->dir, dir, "");
149 }
150
151 /**************** IMAGESELECT ******************************/
152
153 /* the complete call; pulldown menu, and three callback types */
154 static void activate_imageselect_(int type, char *title, char *file, short *menup, char *pupmenu,
155                                                                                  void (*func)(char *),
156                                                                                  void (*func_event)(unsigned short),
157                                                                                  void (*func_args)(char *, void *arg1, void *arg2),
158                                                                                  void *arg1, void *arg2)
159 {
160         SpaceImaSel *simasel;
161         char group[24], name[FILE_MAX], temp[FILE_MAX];
162         
163         if(curarea==0) return;
164         if(curarea->win==0) return;
165         
166         newspace(curarea, SPACE_IMASEL);
167         scrarea_queue_winredraw(curarea);
168         
169         /* sometime double, when area already is SPACE_IMASEL with a different file name */
170         if(curarea->headwin) addqueue(curarea->headwin, CHANGED, 1);
171
172         name[2]= 0;
173         BLI_strncpy(name, file, sizeof(name));
174         
175         simasel= curarea->spacedata.first;
176
177         simasel->returnfunc= func;
178         simasel->returnfunc_event= func_event;
179         simasel->returnfunc_args= func_args;
180         simasel->arg1= arg1;
181         simasel->arg2= arg2;
182         
183         simasel->type= type;
184         simasel->scrollpos = 0.0f;
185
186         if(simasel->pupmenu)
187                 MEM_freeN(simasel->pupmenu);
188         simasel->pupmenu= pupmenu;
189         simasel->menup= menup;
190         
191         /* sfile->act is used for databrowse: double names of library objects */
192         simasel->active_file= -1;
193
194         if(!simasel->files) {
195                 simasel->files = BIF_filelist_new();
196         }
197
198         if(G.relbase_valid && U.flag & USER_RELPATHS && type != FILE_BLENDER)
199                 simasel->flag |= FILE_STRINGCODE;
200         else
201                 simasel->flag &= ~FILE_STRINGCODE;
202
203         if (U.uiflag & USER_HIDE_DOT)
204                 simasel->flag |= FILE_HIDE_DOT;
205
206         if(type==FILE_MAIN) {
207                 char *groupname;
208                 
209                 BLI_strncpy(simasel->file, name+2, sizeof(simasel->file));
210
211                 groupname = BLO_idcode_to_name( GS(name) );
212                 if (groupname) {
213                         BLI_strncpy(simasel->dir, groupname, sizeof(simasel->dir) - 1);
214                         strcat(simasel->dir, "/");
215                 }
216
217                 /* free all */
218                 if (simasel->files) {
219                         BIF_filelist_freelib(simasel->files);                           
220                         BIF_filelist_free(simasel->files);
221                         BIF_filelist_setdir(simasel->files, simasel->dir);
222                         BIF_filelist_settype(simasel->files, type);
223                 }
224         }
225         else if(type==FILE_LOADLIB) {
226                 
227                 if( BIF_filelist_islibrary(simasel->files, temp, group) ) {
228                         /* force a reload of the library-filelist */
229                         BIF_filelist_free(simasel->files);
230                         BIF_filelist_freelib(simasel->files);
231                         BLI_strncpy(simasel->dir, name, sizeof(simasel->dir));
232                         BIF_filelist_setdir(simasel->files, simasel->dir);
233                         BIF_filelist_settype(simasel->files, type);
234                 }
235                 else {
236                         imasel_split_file(simasel, name);
237                         BIF_filelist_freelib(simasel->files);
238                         BIF_filelist_settype(simasel->files, type);                     
239                 }
240         }
241         else {  /* FILE_BLENDER */
242                 imasel_split_file(simasel, name);
243                 BIF_filelist_settype(simasel->files, type);
244
245                 BLI_cleanup_dir(G.sce, simasel->dir);
246
247                 /* free: filelist and libfiledata became incorrect */
248                 BIF_filelist_freelib(simasel->files);
249         }
250         BLI_strncpy(simasel->title, title, sizeof(simasel->title));
251         /* filetoname= 1; */ /* TODO: elubie - check what this means */
252 }
253
254 void activate_imageselect(int type, char *title, char *file, void (*func)(char *))
255 {
256         activate_imageselect_(type, title, file, NULL, NULL, func, NULL, NULL, NULL, NULL);
257 }
258
259 void activate_imageselect_menu(int type, char *title, char *file, char *pupmenu, short *menup, void (*func)(char *))
260 {
261         activate_imageselect_(type, title, file, menup, pupmenu, func, NULL, NULL, NULL, NULL);
262 }
263
264 void activate_imageselect_args(int type, char *title, char *file, void (*func)(char *, void *, void *), void *arg1, void *arg2)
265 {
266         activate_imageselect_(type, title, file, NULL, NULL, NULL, NULL, func, arg1, arg2);
267 }
268
269 void activate_databrowse_imasel(ID *id, int idcode, int fromcode, int retval, short *menup, void (*func)(unsigned short))
270 {
271         ListBase *lb;
272         SpaceImaSel *simasel;
273         char str[32];
274         
275         if(id==NULL) {
276                 lb= wich_libbase(G.main, idcode);
277                 id= lb->first;
278         }
279         
280         if(id) BLI_strncpy(str, id->name, sizeof(str));
281         else return;
282
283         activate_imageselect_(FILE_MAIN, "SELECT DATABLOCK", str, menup, NULL, NULL, func, NULL, NULL, NULL);
284         
285         simasel= curarea->spacedata.first;
286         simasel->retval= retval;
287         simasel->menup= menup;
288
289         BIF_filelist_setipotype(simasel->files, fromcode);
290         BIF_filelist_hasfunc(simasel->files, imasel_has_func(simasel));
291 }
292
293
294 static void set_active_file(SpaceImaSel *simasel, short x, short y)
295 {
296         short tilex, tiley;
297         int active_tile;
298         int active_file;
299         int stridex;
300         struct direntry* file;
301         rcti viewrect = simasel->viewrect;
302         int fileoffset;
303         int rowoffset;
304         int rowleftover;
305         float scrollofs;
306         int numfiles;
307         int tilewidth = simasel->prv_w + TILE_BORDER_X*4;
308         int tileheight = simasel->prv_h + TILE_BORDER_Y*4 + U.fontsize;
309
310         numfiles = BIF_filelist_numfiles(simasel->files);
311         
312         if (simasel->numtilesx > 0) {
313                 fileoffset = numfiles*(simasel->scrollpos / simasel->scrollarea) + 0.5;
314                 rowoffset = (fileoffset / simasel->numtilesx)*simasel->numtilesx;
315                 rowleftover = fileoffset % simasel->numtilesx;
316                 scrollofs = (float)tileheight*(float)rowleftover/(float)simasel->numtilesx;
317         
318                 stridex = (viewrect.xmax - viewrect.xmin) / (tilewidth);
319                 tilex = ( (x-viewrect.xmin)) / (tilewidth);
320                 tiley = (viewrect.ymax - viewrect.ymin + scrollofs - y) / (tileheight);
321                 if (tilex >= simasel->numtilesx) tilex = simasel->numtilesx-1;
322                 if (tiley >= simasel->numtilesy+1) tiley = simasel->numtilesy;
323                 if (tilex < 0) tilex=0;
324                 if (tiley < 0) tiley = 0;
325                 active_tile = tilex + stridex*tiley;
326                 active_file = rowoffset + active_tile;
327
328                 if (active_file >= 0 && active_file < BIF_filelist_numfiles(simasel->files) )
329                 {
330                         simasel->active_file = active_file;
331                         if (simasel->selstate & ACTIVATE) {
332                                 file = BIF_filelist_file(simasel->files, simasel->active_file);
333                                 file->flags |= ACTIVE;
334                         }
335                 } else {
336                         simasel->active_file = -1;
337                 }
338         } else {
339                 simasel->active_file = -1;
340         }
341 }
342
343 static void set_active_bookmark(SpaceImaSel *simasel, short y)
344 {
345         int nentries = fsmenu_get_nentries();
346         short posy = simasel->bookmarkrect.ymax - TILE_BORDER_Y - y;
347         simasel->active_bookmark = ((float)posy / (U.fontsize*3.0f/2.0f));      
348         if (simasel->active_bookmark < 0 || simasel->active_bookmark > nentries) {
349                 simasel->active_bookmark = -1;
350         }
351 }
352
353 static void imasel_prevspace()
354 {
355         SpaceImaSel *simasel;   
356
357         simasel= curarea->spacedata.first;
358
359         /* cleanup */
360         if(simasel->spacetype==SPACE_IMASEL) {
361                 if(simasel->pupmenu) {
362                         MEM_freeN(simasel->pupmenu);
363                         simasel->pupmenu= NULL;
364                 }
365         }
366
367         if(simasel->next) {
368         
369                 BLI_remlink(&curarea->spacedata, simasel);
370                 BLI_addtail(&curarea->spacedata, simasel);
371
372                 simasel= curarea->spacedata.first;
373
374                 if (simasel->spacetype == SPACE_SCRIPT) {
375                         SpaceScript *sc = (SpaceScript *)simasel;
376                         if (sc->script) sc->script->flags &=~SCRIPT_FILESEL;
377                 }
378
379                 newspace(curarea, simasel->spacetype);
380         }
381         else newspace(curarea, SPACE_INFO);
382 }
383
384 static void free_imasel_spec(char *dir)
385 {
386         /* all filesels with 'dir' are freed */
387         bScreen *sc;
388                 
389         sc= G.main->screen.first;
390         while(sc) {
391                 ScrArea *sa= sc->areabase.first;
392                 while(sa) {
393                         SpaceLink  *sl= sa->spacedata.first;
394                         while(sl) {
395                                 if(sl->spacetype==SPACE_FILE) {
396                                         SpaceImaSel *simasel= (SpaceImaSel*) sl;
397                                         if (BLI_streq(simasel->dir, dir)) {
398                                                 BIF_filelist_free(simasel->files);
399                                         }
400                                 }
401                                 sl= sl->next;
402                         }
403                         sa= sa->next;
404                 }
405                 sc= sc->id.next;
406         }
407 }
408
409 static void do_library_append(SpaceImaSel *simasel)
410 {
411         Library *lib;
412         char dir[FILE_MAXDIR], group[32];
413         
414         if ( BIF_filelist_islibrary(simasel->files, dir, group)==0 ) {
415                 error("Not a library");
416         } else if (!BIF_filelist_lib(simasel->files) ) {
417                 error("Library not loaded");
418         } else if (group[0]==0) {
419                 error("Nothing indicated");
420         } else if (BLI_streq(G.main->name, dir)) {
421                 error("Cannot use current file as library");
422         } else {
423                 Object *ob;
424                 int idcode = BIF_groupname_to_code(group);
425                                 
426                 if((simasel->flag & FILE_LINK)==0) {
427                         /* tag everything, all untagged data can be made local */
428                         ID *id;
429                         ListBase *lbarray[MAX_LIBARRAY];
430                         int a;
431                         
432                         a= set_listbasepointers(G.main, lbarray);
433                         while(a--) {
434                                 for(id= lbarray[a]->first; id; id= id->next) id->flag |= LIB_APPEND_TAG;
435                         }
436                 }
437
438                 BIF_filelist_append_library(simasel->files, dir, simasel->file, simasel->flag, idcode);
439
440                 /* DISPLISTS? */
441                 ob= G.main->object.first;
442                 while(ob) {
443                         if(ob->id.lib) {
444                                 ob->recalc |= OB_RECALC;
445                         }
446                         ob= ob->id.next;
447                 }
448         
449                 /* and now find the latest append lib file */
450                 lib= G.main->library.first;
451                 while(lib) {
452                         if (BLI_streq(dir, lib->filename)) break;
453                         lib= lib->id.next;
454                 }
455                 
456                 /* make local */
457                 if(lib) {
458                         if((simasel->flag & FILE_LINK)==0) 
459                                 all_local(lib,1);
460                 }
461                 
462                 DAG_scene_sort(G.scene);
463
464                 /* in sfile->dir is the whole lib name */
465                 BLI_strncpy(G.lib, simasel->dir, sizeof(G.lib) );
466                 
467         }
468 }
469
470 /* NOTE: this is called for file read, after the execfunc no UI memory is valid! */
471 static void imasel_execute(SpaceImaSel *simasel)
472 {
473         struct direntry *file;
474         char name[FILE_MAX];
475         int a;
476         int n;
477         
478         imasel_prevspace();
479
480         if(simasel->type==FILE_LOADLIB) {
481                 if(simasel->flag & FILE_STRINGCODE) {
482                         if (!G.relbase_valid) {
483                                 okee("You have to save the .blend file before using relative paths! Using absolute path instead.");
484                                 simasel->flag &= ~FILE_STRINGCODE;
485                         }
486                 }
487
488                 do_library_append(simasel);
489                 BIF_undo_push("Append from file");
490                 allqueue(REDRAWALL, 1);
491         }
492         else if(imasel_has_func(simasel)) {
493                 fsmenu_insert_entry(simasel->dir, 1, 0);
494         
495                 if(simasel->type==FILE_MAIN) { /* DATABROWSE */
496                         if (simasel->menup) {   /* with value pointing to ID block index */
497                                 int notfound = 1;
498
499                                 /*      Need special handling since hiding .* datablocks means that
500                                         simasel->active_file is no longer the same as files->nr.
501
502                                         Also, toggle HIDE_DOT on and off can make simasel->active_file not longer
503                                         correct (meaning it doesn't point to the correct item in the filelist.
504                                         
505                                         simasel->file is always correct, so first with check if, for the item
506                                         corresponding to simasel->active_file, the name is the same.
507
508                                         If it isn't (or if simasel->active_file is not good), go over filelist and take
509                                         the correct one.
510
511                                         This means that selecting a datablock than hiding it makes it
512                                         unselectable. Not really a problem.
513
514                                         - theeth
515                                  */
516
517                                 *simasel->menup= -1;
518                                 n = BIF_filelist_numfiles(simasel->files);
519                                 if(simasel->files) {
520                                         if( (simasel->active_file>=0) && (simasel->active_file < n) ) {
521                                                 file = BIF_filelist_file(simasel->files, simasel->active_file);                                         
522                                                 if ( strcmp(file->relname, simasel->file)==0) {
523                                                         notfound = 0;
524                                                         *simasel->menup= file->nr;
525                                                 }
526                                         }
527                                         if (notfound) {                                 
528                                                 for(a=0; a<n; a++) {
529                                                         file = BIF_filelist_file(simasel->files, a);    
530                                                         if( strcmp(file->relname, simasel->file)==0) {
531                                                                 *simasel->menup= file->nr;
532                                                                 break;
533                                                         }
534                                                 }
535                                         }
536                                 }
537                         }
538                         if(simasel->returnfunc_event)
539                                 simasel->returnfunc_event(simasel->retval);
540                         else if(simasel->returnfunc_args)
541                                 simasel->returnfunc_args(NULL, simasel->arg1, simasel->arg2);
542                 }
543                 else {
544                         if(strncmp(simasel->title, "Save", 4)==0) free_imasel_spec(simasel->dir);
545                         if(strncmp(simasel->title, "Export", 6)==0) free_imasel_spec(simasel->dir);
546                         
547                         BLI_strncpy(name, simasel->dir, sizeof(name));
548                         strcat(name, simasel->file);
549                         
550                         if(simasel->flag & FILE_STRINGCODE) {
551                                 /* still weak, but we don't want saving files to make relative paths */
552                                 if(G.relbase_valid && strncmp(simasel->title, "Save", 4)) {
553                                         BLI_makestringcode(G.sce, name);
554                                 } else {
555                                         /* if we don't have a valid relative base (.blend file hasn't been saved yet)
556                                            then we don't save the path as relative (for texture images, background image).      
557                                            Warning message not shown when saving files (doesn't make sense there)
558                                         */
559                                         if (strncmp(simasel->title, "Save", 4)) {                                       
560                                                 printf("Relative path setting has been ignored because .blend file hasn't been saved yet.\n");
561                                         }
562                                         simasel->flag &= ~FILE_STRINGCODE;
563                                 }
564                         }
565                         if(simasel->returnfunc)
566                                 simasel->returnfunc(name);
567                         else if(simasel->returnfunc_args)
568                                 simasel->returnfunc_args(name, simasel->arg1, simasel->arg2);
569                 }
570         }
571 }
572
573 static void do_imasel_buttons(short event, SpaceImaSel *simasel)
574 {
575         char butname[FILE_MAX];
576         
577         if (event == B_FS_FILENAME) {
578                 if (strchr(simasel->file, '*') || strchr(simasel->file, '?') || strchr(simasel->file, '[')) {
579                         int i, match = FALSE;
580                         struct direntry *file;
581                         int n = BIF_filelist_numfiles(simasel->files);
582                         for (i = 2; i < n; i++) {
583                                 file = BIF_filelist_file(simasel->files, i);
584                                 if (fnmatch(simasel->file, file->relname, 0) == 0) {
585                                         file->flags |= ACTIVE;
586                                         match = TRUE;
587                                 }
588                         }
589                         if (match) simasel->file[0] = '\0';
590                         if(simasel->type==FILE_MAIN) imasel_select_objects(simasel);
591                         scrarea_queue_winredraw(curarea);
592                 }
593         }
594         else if(event== B_FS_DIRNAME) {
595                 /* reuse the butname variable */
596                 BLI_cleanup_dir(G.sce, simasel->dir);
597
598                 BLI_make_file_string(G.sce, butname, simasel->dir, "");
599                 BLI_strncpy(simasel->dir, butname, sizeof(simasel->dir));               
600
601                 /* strip the trailing slash if its a real dir */
602                 if (strlen(butname)!=1)
603                         butname[strlen(butname)-1]=0;
604                 
605                 /* updating the directory in the filelist */
606                 BIF_filelist_setdir(simasel->files, simasel->dir);
607
608                 if(simasel->type & FILE_UNIX) {
609                         if (!BLI_exists(butname)) {
610                                 if (okee("Makedir")) {
611                                         BLI_recurdir_fileops(butname);
612                                         if (!BLI_exists(butname)) {
613                                                 BIF_filelist_free(simasel->files);
614                                                 BIF_filelist_parent(simasel->files);
615                                                 BLI_strncpy(simasel->dir, BIF_filelist_dir(simasel->files), 80);
616                                         }
617                                 } else {
618                                         BIF_filelist_free(simasel->files);
619                                         BIF_filelist_parent(simasel->files);
620                                         BLI_strncpy(simasel->dir, BIF_filelist_dir(simasel->files), 80);
621                                 }
622                         }
623                 }
624                 BIF_filelist_free(simasel->files);              
625                 simasel->file[0] = '\0';                        
626                 simasel->scrollpos = 0;
627                 simasel->active_file = -1;
628                 scrarea_queue_winredraw(curarea);
629         }
630         else if(event== B_FS_DIR_MENU) {
631                 char *selected= fsmenu_get_entry(simasel->menu-1);
632                 
633                 /* which string */
634                 if (selected) {
635                         BLI_strncpy(simasel->dir, selected, sizeof(simasel->dir));
636                         BLI_make_exist(simasel->dir);
637                         BLI_cleanup_dir(G.sce, simasel->dir);
638                         BIF_filelist_free(simasel->files);      
639                         BIF_filelist_setdir(simasel->files, simasel->dir);
640                         simasel->file[0] = '\0';                        
641                         simasel->scrollpos = 0;
642                         simasel->active_file = -1;
643                         scrarea_queue_redraw(curarea);
644                 }
645
646                 simasel->active_file = -1;
647                 
648         }
649         else if(event== B_FS_PARDIR) {
650                 BIF_filelist_free(simasel->files);
651                 BIF_filelist_parent(simasel->files);
652                 BLI_strncpy(simasel->dir, BIF_filelist_dir(simasel->files), 80);
653                 simasel->file[0] = '\0';
654                 simasel->active_file = -1;
655                 simasel->scrollpos = 0;
656                 scrarea_queue_redraw(curarea);
657         }
658         else if(event== B_FS_LOAD) {
659                 if(simasel->type) 
660                         imasel_execute(simasel);
661         }
662         else if(event== B_FS_CANCEL) 
663                 imasel_prevspace();
664         else if(event== B_FS_LIBNAME) {
665                 Library *lib= BLI_findlink(&G.main->library, simasel->menu);
666                 if(lib) {
667                         BLI_strncpy(simasel->dir, lib->filename, sizeof(simasel->dir));
668                         BLI_make_exist(simasel->dir);
669                         BLI_cleanup_dir(G.sce, simasel->dir);
670                         BIF_filelist_free(simasel->files);
671                         BIF_filelist_setdir(simasel->files, simasel->dir);
672                         simasel->file[0] = '\0';                        
673                         simasel->scrollpos = 0;
674                         simasel->active_file = -1;
675                         scrarea_queue_winredraw(curarea);
676                 }
677         } else if(event== B_FS_BOOKMARK)  {
678                 char name[FILE_MAX];
679                 BLI_make_file_string(G.sce, name, BLI_gethome(), ".Bfs");
680                 fsmenu_insert_entry(simasel->dir, 1, 1);
681                 scrarea_queue_winredraw(curarea);
682                 fsmenu_write_file(name);
683         }
684         
685 }
686
687 static void imasel_home(ScrArea *sa, SpaceImaSel *simasel)
688 {
689         simasel->v2d.cur.xmin= simasel->v2d.cur.ymin= 0.0f;
690         simasel->v2d.cur.xmax= sa->winx;
691         simasel->v2d.cur.ymax= sa->winy;
692         
693         simasel->v2d.tot= simasel->v2d.cur;
694         test_view2d(G.v2d, sa->winx, sa->winy);
695         
696 }
697
698 static struct direntry* get_hilited_entry(SpaceImaSel *simasel)
699 {
700         struct direntry *file;
701         file = BIF_filelist_file(simasel->files, simasel->active_file);
702         return file;
703 }
704
705 static void do_filescroll(SpaceImaSel *simasel)
706 {
707         short mval[2], oldy, yo;
708         float scrollarea, scrollstep;
709
710         /* for beauty */
711         scrarea_do_windraw(curarea);
712         screen_swapbuffers();
713
714         getmouseco_areawin(mval);
715         oldy= yo= mval[1];
716         
717         while(get_mbut()&L_MOUSE) {
718                 getmouseco_areawin(mval);
719                 
720                 if(yo!=mval[1]) {
721                         scrollarea = ((float)simasel->v2d.vert.ymax - (float)simasel->v2d.vert.ymin);
722                         scrollstep = yo - mval[1];      
723                         simasel->scrollpos += scrollstep;
724                         
725                         if (simasel->scrollpos<0) 
726                                 simasel->scrollpos=0;
727                         if (simasel->scrollpos > scrollarea - simasel->scrollheight) 
728                                 simasel->scrollpos = scrollarea - simasel->scrollheight;
729                         scrarea_do_windraw(curarea);
730                         screen_swapbuffers();
731
732                         yo= mval[1];
733                 }
734                 else BIF_wait_for_statechange();
735         }
736
737         /* for beauty */
738         scrarea_do_windraw(curarea);
739         screen_swapbuffers();
740         
741 }
742
743 /* ******************* DATA SELECT ********************* */
744
745 static void imasel_select_objects(SpaceImaSel *simasel)
746 {
747         Object *ob;
748         Base *base;
749         Scene *sce;
750         struct direntry* file;
751         int a;
752         int totfile;
753
754         /* only when F4 DATABROWSE */
755         if(imasel_has_func(simasel)) return;
756         
757         totfile = BIF_filelist_numfiles(simasel->files);
758
759         if( strcmp(simasel->dir, "Object/")==0 ) {
760                 for(a=0; a<totfile; a++) {
761                         file = BIF_filelist_file(simasel->files, a);
762                         ob= (Object *)file->poin;
763                         
764                         if(ob) {
765                                 if(file->flags & ACTIVE) ob->flag |= SELECT;
766                                 else ob->flag &= ~SELECT;
767                         }
768
769                 }
770                 base= FIRSTBASE;
771                 while(base) {
772                         base->flag= base->object->flag;
773                         base= base->next;
774                 }
775                 countall();
776                 allqueue(REDRAWVIEW3D, 0);
777                 allqueue(REDRAWOOPS, 0);
778         }
779         else if( strcmp(simasel->dir, "Scene/")==0 ) {
780                 
781                 for(a=0; a<totfile; a++) {
782                         file = BIF_filelist_file(simasel->files, a);
783                         sce= (Scene *)file->poin;
784                         if(sce) {
785                                 if(file->flags & ACTIVE) sce->r.scemode |= R_BG_RENDER;
786                                 else sce->r.scemode &= ~R_BG_RENDER;
787                         }
788
789                 }
790                 allqueue(REDRAWBUTSSCENE, 0);
791         }
792 }
793
794 static void active_imasel_object(SpaceImaSel *simasel)
795 {
796         Object *ob;
797         struct direntry* file;
798
799         /* only when F4 DATABROWSE */
800         if(imasel_has_func(simasel)) return;
801         
802         if( strcmp(simasel->dir, "Object/")==0 ) {
803                 int n = BIF_filelist_numfiles(simasel->files);
804                 if(simasel->active_file >= 0 && simasel->active_file < n) {
805                         file = BIF_filelist_file(simasel->files, simasel->active_file);
806                         ob= (Object *)file->poin;
807                         
808                         if(ob) {
809                                 set_active_object(ob);
810                                 if(BASACT && BASACT->object==ob) {
811                                         BASACT->flag |= SELECT;
812                                         file->flags |= ACTIVE;
813                                         allqueue(REDRAWVIEW3D, 0);
814                                         allqueue(REDRAWOOPS, 0);
815                                         scrarea_queue_winredraw(curarea);
816                                 }
817                         }
818                 }
819         }
820 }
821
822
823
824 void winqreadimaselspace(ScrArea *, void *, BWinEvent *);
825
826
827 void winqreadimaselspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
828 {
829         unsigned short event= evt->event;
830         short val= evt->val;
831         SpaceImaSel *simasel;
832         
833         char str[FILE_MAXDIR+FILE_MAXFILE+12];
834         short mval[2];
835         short do_draw = 0;
836         short do_headdraw = 0;
837         int numfiles;
838         struct direntry *file;
839         float scrollstep = 0;
840         float scrollarea;
841
842         // if(val==0) return;
843         simasel= curarea->spacedata.first;
844
845         if (!simasel->files)
846                 return;
847
848         if (BIF_filelist_empty(simasel->files))
849                 return;
850
851         numfiles = BIF_filelist_numfiles(simasel->files);
852         
853         /* calc_scrollrcts(sa, &(simasel->v2d), sa->winx, sa->winy); */
854         calc_imasel_rcts(simasel, sa->winx, sa->winy);  
855
856         /* prevent looping */
857         if(simasel->selstate && !(get_mbut() & R_MOUSE)) simasel->selstate= 0;
858
859         if(val) {
860
861                 if( event!=RETKEY && event!=PADENTER)
862                         if( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0;
863
864                 switch(event) {
865                 
866                 case UI_BUT_EVENT:
867                         do_imasel_buttons(val, simasel);
868                         break;          
869                 case RENDERPREVIEW:
870                         do_draw= 1; 
871                         /* draw_imasel_previews(sa, simasel);  */
872                         break;
873                 case REDRAWIMASEL:
874                         do_draw= 1;
875                         break;
876                 case WHEELDOWNMOUSE:
877                         numfiles = BIF_filelist_numfiles(simasel->files);
878                         scrollarea = ((float)simasel->v2d.vert.ymax - (float)simasel->v2d.vert.ymin);
879                         scrollstep = ((scrollarea-simasel->scrollheight)/numfiles)*simasel->numtilesx;  
880                         simasel->scrollpos += scrollstep;
881                         if (simasel->scrollpos > scrollarea - simasel->scrollheight) 
882                                 simasel->scrollpos = scrollarea - simasel->scrollheight;
883                         do_draw= 1;
884                         break;
885                 case WHEELUPMOUSE:
886                         numfiles = BIF_filelist_numfiles(simasel->files);
887                         scrollarea = ((float)simasel->v2d.vert.ymax - (float)simasel->v2d.vert.ymin);
888                         scrollstep = ((scrollarea-simasel->scrollheight)/numfiles)*simasel->numtilesx;                  
889                         simasel->scrollpos -= scrollstep;
890                         if (simasel->scrollpos<0) 
891                                 simasel->scrollpos=0;
892                         do_draw= 1;
893                         break;
894                 case PAGEUPKEY:
895                         numfiles = BIF_filelist_numfiles(simasel->files);
896                         scrollarea = ((float)simasel->v2d.vert.ymax - (float)simasel->v2d.vert.ymin);
897                         scrollstep = ((scrollarea-simasel->scrollheight)/numfiles)
898                                                  *simasel->numtilesx*simasel->numtilesy;
899                         simasel->scrollpos -= scrollstep;
900                         if (simasel->scrollpos<0) 
901                                 simasel->scrollpos=0;
902                         do_draw= 1;
903                         break;
904                 case PAGEDOWNKEY:
905                         numfiles = BIF_filelist_numfiles(simasel->files);
906                         scrollarea = ((float)simasel->v2d.vert.ymax - (float)simasel->v2d.vert.ymin);
907                         scrollstep = ((scrollarea-simasel->scrollheight)/numfiles)
908                                                  * simasel->numtilesx*simasel->numtilesy;
909                         simasel->scrollpos += scrollstep;
910                         if (simasel->scrollpos > scrollarea - simasel->scrollheight) 
911                                 simasel->scrollpos = scrollarea - simasel->scrollheight;
912                         do_draw= 1;                                             
913                         break;
914                 case HOMEKEY:
915                         simasel->scrollpos=0;
916                         imasel_home(sa, simasel);
917                         do_draw= 1;
918                         break;
919                 case ENDKEY:
920                         simasel->scrollpos = simasel->scrollarea;
921                         do_draw= 1;
922                         break;
923
924                 case ESCKEY:
925                         BIF_filelist_free(simasel->files);
926                         imasel_prevspace();
927                         break;
928                 case PERIODKEY:
929                         BIF_filelist_free(simasel->files);
930                         simasel->active_file = -1;
931                         do_draw = 1;
932                         break;
933                 case LEFTMOUSE:
934                 case MIDDLEMOUSE:                       
935                         getmouseco_areawin(mval);
936                         if(mval[0]>simasel->v2d.vert.xmin && mval[0]<simasel->v2d.vert.xmax && mval[1]>simasel->v2d.vert.ymin && mval[1]<simasel->v2d.vert.ymax) {
937                                 do_filescroll(simasel);
938                         }
939                         else if(mval[0]>simasel->viewrect.xmin && mval[0]<simasel->viewrect.xmax 
940                                 && mval[1]>simasel->viewrect.ymin && mval[1]<simasel->viewrect.ymax) {  
941                                 set_active_file(simasel, mval[0], mval[1]);
942                                 if (simasel->active_file >= 0 && simasel->active_file < numfiles) {
943                                         file = BIF_filelist_file(simasel->files, simasel->active_file);
944                                         
945                                         if(file && S_ISDIR(file->type)) {
946                                                 strcat(simasel->dir, file->relname);                                            
947                                                 strcat(simasel->dir,"/");
948                                                 simasel->file[0] = '\0';
949                                                 BLI_cleanup_dir(G.sce, simasel->dir);
950                                                 BIF_filelist_setdir(simasel->files, simasel->dir);
951                                                 BIF_filelist_free(simasel->files);
952                                                 simasel->active_file = -1;
953                                                 simasel->scrollpos = 0;
954                                                 do_draw = 1;
955                                                 do_headdraw = 1;                                                
956                                         }
957                                         else if (file)
958                                         {
959                                                 if (file->relname) {
960                                                         if (simasel->img) {
961                                                                 IMB_freeImBuf(simasel->img);
962                                                                 simasel->img = NULL;
963                                                         }
964                                                         BLI_strncpy(simasel->file, file->relname, FILE_MAXFILE);
965                                                         if(event==MIDDLEMOUSE && BIF_filelist_gettype(simasel->files)) 
966                                                                 imasel_execute(simasel);
967                                                 }
968                                                 
969                                         }       
970                                         if(BIF_filelist_gettype(simasel->files)==FILE_MAIN) {
971                                                 active_imasel_object(simasel);
972                                         }
973                                 
974                                         do_draw = 1;
975                                 }
976                         }
977                         else {
978                                 simasel->active_file = -1;
979                                 if (simasel->flag & FILE_BOOKMARKS) {
980                                         if(mval[0]>simasel->bookmarkrect.xmin && mval[0]<simasel->bookmarkrect.xmax && mval[1]>simasel->bookmarkrect.ymin && mval[1]<simasel->bookmarkrect.ymax) {
981                                                 int nentries = fsmenu_get_nentries();
982                                                 
983                                                 set_active_bookmark(simasel, mval[1]);
984                                                 if (simasel->active_bookmark >= 0 && simasel->active_bookmark < nentries) {
985                                                         char *selected= fsmenu_get_entry(simasel->active_bookmark);                     
986                                                         /* which string */
987                                                         if (selected) {
988                                                                 BLI_strncpy(simasel->dir, selected, sizeof(simasel->dir));
989                                                                 BLI_make_exist(simasel->dir);
990                                                                 BLI_cleanup_dir(G.sce, simasel->dir);
991                                                                 BIF_filelist_free(simasel->files);      
992                                                                 BIF_filelist_setdir(simasel->files, simasel->dir);
993                                                                 simasel->file[0] = '\0';                        
994                                                                 simasel->scrollpos = 0;
995                                                                 simasel->active_file = -1;
996                                                                 do_headdraw = 1;
997                                                         }
998                                                 }
999                                         } else {
1000                                                 simasel->active_bookmark = -1;
1001                                         }
1002                                         do_draw= 1;
1003                                 }                               
1004                         }
1005                         break;
1006                 case RIGHTMOUSE:                        
1007                         getmouseco_areawin(mval);
1008                         if(mval[0]>simasel->viewrect.xmin && mval[0]<simasel->viewrect.xmax 
1009                                 && mval[1]>simasel->viewrect.ymin && mval[1]<simasel->viewrect.ymax) {
1010                                 set_active_file(simasel, mval[0], mval[1]);
1011                                 if(simasel->active_file >=0 && simasel->active_file<numfiles) {
1012                                         simasel->selstate = NOTACTIVE;
1013                                         file = BIF_filelist_file(simasel->files, simasel->active_file);
1014                                         if (file->flags & ACTIVE) {
1015                                                 file->flags &= ~ACTIVE;
1016                                                 simasel->selstate = INACTIVATE;
1017                                         }
1018                                         else {
1019                                                 file->flags |= ACTIVE;
1020                                                 simasel->selstate = ACTIVATE;
1021                                         }
1022                                         do_draw= 1;
1023                                 }
1024                         }
1025                         break;
1026                 case MOUSEY:
1027                 case MOUSEX:
1028                         getmouseco_areawin(mval);
1029                         if(mval[0]>simasel->viewrect.xmin && mval[0]<simasel->viewrect.xmax && mval[1]>simasel->viewrect.ymin && mval[1]<simasel->viewrect.ymax) {
1030                                 set_active_file(simasel, mval[0], mval[1]);
1031                                 simasel->active_bookmark = -1;
1032                                 if(simasel->active_file >=0 && simasel->active_file<numfiles) {
1033                                         file = BIF_filelist_file(simasel->files, simasel->active_file);
1034                                         if (simasel->selstate == INACTIVATE) {
1035                                                 file->flags &= ~ACTIVE;
1036                                         }
1037                                         else if (simasel->selstate == ACTIVATE) {
1038                                                 file->flags |= ACTIVE;
1039                                         }
1040                                         do_draw= 1;
1041                                 }
1042                         } else {
1043                                 simasel->active_file = -1;                      
1044                                 if (simasel->flag & FILE_BOOKMARKS) {
1045                                         if(mval[0]>simasel->bookmarkrect.xmin && mval[0]<simasel->bookmarkrect.xmax && mval[1]>simasel->bookmarkrect.ymin && mval[1]<simasel->bookmarkrect.ymax) {
1046                                                 set_active_bookmark(simasel, mval[1]);                                          
1047                                         } else {
1048                                                 simasel->active_bookmark = -1;
1049                                         }
1050                                         do_draw= 1;
1051                                 }
1052                         }
1053                         break;
1054                 case AKEY:
1055                         BIF_filelist_swapselect(simasel->files);
1056                         if(simasel->type==FILE_MAIN) imasel_select_objects(simasel);
1057                         do_draw= 1;
1058                         break;
1059                 case BKEY:
1060                         toggle_blockhandler(sa, IMASEL_HANDLER_IMAGE, UI_PNL_UNSTOW);
1061                         scrarea_queue_winredraw(sa);
1062                         break;
1063                 case PKEY:
1064                         if(G.qual & LR_SHIFTKEY) {
1065                                 extern char bprogname[];        /* usiblender.c */
1066                         
1067                                 sprintf(str, "%s -a \"%s%s\"", bprogname, simasel->dir, simasel->file);
1068                                 system(str);
1069                         }
1070                         else 
1071                         {
1072                                 BIF_filelist_free(simasel->files);
1073                                 BIF_filelist_parent(simasel->files);
1074                                 BLI_strncpy(simasel->dir, BIF_filelist_dir(simasel->files), 80);
1075                                 simasel->file[0] = '\0';
1076                                 simasel->active_file = -1;
1077                                 simasel->scrollpos = 0;
1078                                 do_headdraw = 1;
1079                         }
1080                         do_draw = 1;    
1081                         break;
1082                 case XKEY:
1083                         getmouseco_areawin(mval);                       
1084                         if (simasel->flag & FILE_BOOKMARKS) {
1085                                 if(mval[0]>simasel->bookmarkrect.xmin && mval[0]<simasel->bookmarkrect.xmax && mval[1]>simasel->bookmarkrect.ymin && mval[1]<simasel->bookmarkrect.ymax) {                      
1086                                         int nentries = fsmenu_get_nentries();
1087                                         set_active_bookmark(simasel, mval[1]);
1088                                         if (simasel->active_bookmark >= 0 && simasel->active_bookmark < nentries) {
1089                                                 char name[FILE_MAX];
1090                                                 BLI_make_file_string(G.sce, name, BLI_gethome(), ".Bfs");
1091                                                 fsmenu_remove_entry(simasel->active_bookmark);
1092                                                 fsmenu_write_file(name);
1093                                                 simasel->active_bookmark = -1;
1094                                                 do_draw = 1;
1095                                         }
1096                                 }
1097                         }                       
1098                         break;
1099                 }               
1100         }
1101         else if(event==RIGHTMOUSE) {
1102                 simasel->selstate = NOTACTIVE;          
1103                 if(simasel->type==FILE_MAIN) imasel_select_objects(simasel);
1104         }
1105         else if(event==LEFTMOUSE) {
1106                 if(simasel->type==FILE_MAIN) {
1107                         getmouseco_areawin(mval);
1108                         set_active_file(simasel, mval[0], mval[1]);
1109                 }
1110         }
1111                 /* XXX, stupid patch, curarea can become undone
1112                  * because of file loading... fixme zr
1113                  */
1114         if(curarea) {
1115                 if(do_draw) scrarea_queue_winredraw(curarea);
1116                 if(do_headdraw) scrarea_queue_headredraw(curarea);
1117         }
1118 }
1119
1120
1121 /* copied from filesel.c */
1122 void clever_numbuts_imasel()
1123 {
1124         SpaceImaSel *simasel;
1125         char orgname[FILE_MAXDIR+FILE_MAXFILE+12];
1126         char filename[FILE_MAXDIR+FILE_MAXFILE+12];
1127         char newname[FILE_MAXDIR+FILE_MAXFILE+12];
1128         struct direntry *file;
1129         int len;
1130         
1131         simasel= curarea->spacedata.first;
1132
1133         if(BIF_filelist_gettype(simasel->files)==FILE_MAIN) return;
1134         
1135         len = 110;
1136         file = get_hilited_entry(simasel);
1137
1138         if (file != NULL && !(S_ISDIR(file->type))){
1139                 
1140                 BLI_make_file_string(G.sce, orgname, simasel->dir, file->relname);
1141                 BLI_strncpy(filename, file->relname, sizeof(filename));
1142
1143                 add_numbut(0, TEX, "", 0, len, filename, "Rename File");
1144
1145                 if( do_clever_numbuts("Rename File", 1, REDRAW) ) {
1146                         BLI_make_file_string(G.sce, newname, simasel->dir, filename);
1147
1148                         if( strcmp(orgname, newname) != 0 ) {
1149                                 BLI_rename(orgname, newname);
1150                                 BIF_filelist_free(simasel->files);
1151                         }
1152                 }
1153
1154                 scrarea_queue_winredraw(curarea);
1155         }
1156 }