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