Merge with 2.5 -r 21515:21619.
[blender.git] / source / blender / editors / space_file / file_ops.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL 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. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Andrea Weikert (c) 2008 Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include "BKE_context.h"
30 #include "BKE_screen.h"
31 #include "BKE_global.h"
32
33 #include "BLI_blenlib.h"
34 #include "BLI_storage_types.h"
35 #ifdef WIN32
36 #include "BLI_winstuff.h"
37 #endif
38 #include "DNA_space_types.h"
39 #include "DNA_userdef_types.h"
40
41 #include "ED_space_api.h"
42 #include "ED_screen.h"
43 #include "ED_fileselect.h"
44
45 #include "MEM_guardedalloc.h"
46
47 #include "RNA_access.h"
48 #include "RNA_define.h"
49
50 #include "UI_interface.h"
51 #include "UI_view2d.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 #include "file_intern.h"
57 #include "filelist.h"
58 #include "fsmenu.h"
59
60 #include <stdlib.h>
61 #include <string.h>
62 #include <stdio.h>
63
64 /* for events */
65 #define NOTACTIVE                       0
66 #define ACTIVATE                        1
67 #define INACTIVATE                      2
68
69 /* ---------- FILE SELECTION ------------ */
70
71 static int find_file_mouse(SpaceFile *sfile, struct ARegion* ar, short x, short y, short clamp)
72 {
73         float fx,fy;
74         int active_file = -1;
75         int numfiles = filelist_numfiles(sfile->files);
76         View2D* v2d = &ar->v2d;
77
78         UI_view2d_region_to_view(v2d, x, y, &fx, &fy);
79
80         active_file = ED_fileselect_layout_offset(sfile->layout, v2d->tot.xmin + fx, v2d->tot.ymax - fy);
81
82         if(active_file < 0) {
83                 if(clamp)       active_file=  0;
84                 else            active_file= -1;
85         }
86         else if(active_file >= numfiles) {
87                 if(clamp)       active_file=  numfiles-1;
88                 else            active_file= -1;
89         }
90         
91         return active_file;
92 }
93
94
95 static void file_deselect_all(SpaceFile* sfile)
96 {
97         int numfiles = filelist_numfiles(sfile->files);
98         int i;
99
100         for ( i=0; i < numfiles; ++i) {
101                 struct direntry* file = filelist_file(sfile->files, i);
102                 if (file && (file->flags & ACTIVE)) {
103                         file->flags &= ~ACTIVE;
104                 }
105         }
106 }
107
108 static void file_select(SpaceFile* sfile, ARegion* ar, const rcti* rect, short val)
109 {
110         int first_file = -1;
111         int last_file = -1;
112         int act_file;
113         short selecting = (val == LEFTMOUSE);
114         FileSelectParams *params = ED_fileselect_get_params(sfile);
115         // FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
116
117         int numfiles = filelist_numfiles(sfile->files);
118
119         params->selstate = NOTACTIVE;
120         first_file = find_file_mouse(sfile, ar, rect->xmin, rect->ymax, 1);
121         last_file = find_file_mouse(sfile, ar, rect->xmax, rect->ymin, 1);
122         
123         /* select all valid files between first and last indicated */
124         if ( (first_file >= 0) && (first_file < numfiles) && (last_file >= 0) && (last_file < numfiles) ) {
125                 for (act_file = first_file; act_file <= last_file; act_file++) {
126                         struct direntry* file = filelist_file(sfile->files, act_file);
127                         if (selecting) 
128                                 file->flags |= ACTIVE;
129                         else
130                                 file->flags &= ~ACTIVE;
131                 }
132         }
133
134         /* make the last file active */
135         if (selecting && (last_file >= 0 && last_file < numfiles)) {
136                 struct direntry* file = filelist_file(sfile->files, last_file);
137                 params->active_file = last_file;
138
139                 if(file && S_ISDIR(file->type)) {
140                         /* the path is too long! */
141                         if (strlen(params->dir) + strlen(file->relname) >= FILE_MAX ) 
142                         {
143                                 // XXX error("Path too long, cannot enter this directory");
144                         } else {
145                                 BLI_cleanup_dir(G.sce, params->dir);
146                                 strcat(params->dir, file->relname);
147                                 BLI_add_slash(params->dir);
148                                 params->file[0] = '\0';
149                                 file_change_dir(sfile);
150                         }
151                 }
152                 else if (file)
153                 {
154                         if (file->relname) {
155                                 BLI_strncpy(params->file, file->relname, FILE_MAXFILE);
156                                 /* XXX
157                                 if(event==MIDDLEMOUSE && filelist_gettype(sfile->files)) 
158                                         imasel_execute(sfile);
159                                 */
160                         }
161                         
162                 }       
163                 /* XXX
164                 if(BIF_filelist_gettype(sfile->files)==FILE_MAIN) {
165                         active_imasel_object(sfile);
166                 }
167                 */
168         }
169 }
170
171
172
173 static int file_border_select_exec(bContext *C, wmOperator *op)
174 {
175         ARegion *ar= CTX_wm_region(C);
176         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
177         short val;
178         rcti rect;
179
180         val= RNA_int_get(op->ptr, "event_type");
181         rect.xmin= RNA_int_get(op->ptr, "xmin");
182         rect.ymin= RNA_int_get(op->ptr, "ymin");
183         rect.xmax= RNA_int_get(op->ptr, "xmax");
184         rect.ymax= RNA_int_get(op->ptr, "ymax");
185
186         BLI_isect_rcti(&(ar->v2d.mask), &rect, &rect);
187         
188         file_select(sfile, ar, &rect, val );
189         WM_event_add_notifier(C, NC_WINDOW, NULL);
190         return OPERATOR_FINISHED;
191 }
192
193 void FILE_OT_select_border(wmOperatorType *ot)
194 {
195         /* identifiers */
196         ot->name= "Activate/Select File";
197         ot->idname= "FILE_OT_select_border";
198         
199         /* api callbacks */
200         ot->invoke= WM_border_select_invoke;
201         ot->exec= file_border_select_exec;
202         ot->modal= WM_border_select_modal;
203
204         /* rna */
205         RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
206         RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
207         RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
208         RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
209         RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
210
211         ot->poll= ED_operator_file_active;
212 }
213
214 static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
215 {
216         ARegion *ar= CTX_wm_region(C);
217         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
218         short val;
219         rcti rect;
220
221         rect.xmin = rect.xmax = event->x - ar->winrct.xmin;
222         rect.ymin = rect.ymax = event->y - ar->winrct.ymin;
223         val = event->val;
224
225         if (BLI_in_rcti(&ar->v2d.mask, rect.xmin, rect.ymin)) { 
226
227                 /* single select, deselect all selected first */
228                 file_deselect_all(sfile);
229                 file_select(sfile, ar, &rect, val );
230                 WM_event_add_notifier(C, NC_FILE|ND_PARAMS, NULL);
231         }
232         return OPERATOR_FINISHED;
233 }
234
235 void FILE_OT_select(wmOperatorType *ot)
236 {
237         /* identifiers */
238         ot->name= "Activate/Select File";
239         ot->idname= "FILE_OT_select";
240         
241         /* api callbacks */
242         ot->invoke= file_select_invoke;
243
244         /* rna */
245
246         ot->poll= ED_operator_file_active;
247 }
248
249 static int file_select_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
250 {
251         ScrArea *sa= CTX_wm_area(C);
252         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
253         int numfiles = filelist_numfiles(sfile->files);
254         int i;
255         int select = 1;
256
257         /* if any file is selected, deselect all first */
258         for ( i=0; i < numfiles; ++i) {
259                 struct direntry* file = filelist_file(sfile->files, i);
260                 if (file && (file->flags & ACTIVE)) {
261                         file->flags &= ~ACTIVE;
262                         select = 0;
263                         ED_area_tag_redraw(sa);
264                 }
265         }
266         /* select all only if previously no file was selected */
267         if (select) {
268                 for ( i=0; i < numfiles; ++i) {
269                         struct direntry* file = filelist_file(sfile->files, i);
270                         if(file && !S_ISDIR(file->type)) {
271                                 file->flags |= ACTIVE;
272                                 ED_area_tag_redraw(sa);
273                         }
274                 }
275         }
276         return OPERATOR_FINISHED;
277 }
278
279 void FILE_OT_select_all_toggle(wmOperatorType *ot)
280 {
281         /* identifiers */
282         ot->name= "Select/Deselect all files";
283         ot->idname= "FILE_OT_select_all_toggle";
284         
285         /* api callbacks */
286         ot->invoke= file_select_all_invoke;
287
288         /* rna */
289
290         ot->poll= ED_operator_file_active;
291 }
292
293 /* ---------- BOOKMARKS ----------- */
294
295 static int bookmark_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
296 {
297         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
298
299         if(RNA_struct_find_property(op->ptr, "dir")) {
300                 char entry[256];
301                 FileSelectParams* params = sfile->params;
302
303                 RNA_string_get(op->ptr, "dir", entry);
304                 BLI_strncpy(params->dir, entry, sizeof(params->dir));
305                 BLI_cleanup_dir(G.sce, params->dir);
306                 file_change_dir(sfile);                         
307                 params->file[0] = '\0';
308
309                 WM_event_add_notifier(C, NC_FILE|ND_PARAMS, NULL);
310         }
311         
312         return OPERATOR_FINISHED;
313 }
314
315 void FILE_OT_select_bookmark(wmOperatorType *ot)
316 {
317         /* identifiers */
318         ot->name= "Select Directory";
319         ot->idname= "FILE_OT_select_bookmark";
320         
321         /* api callbacks */
322         ot->invoke= bookmark_select_invoke;
323         ot->poll= ED_operator_file_active;
324
325         RNA_def_string(ot->srna, "dir", "", 256, "Dir", "");
326 }
327
328 static int bookmark_add_invoke(bContext *C, wmOperator *op, wmEvent *event)
329 {
330         ScrArea *sa= CTX_wm_area(C);
331         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
332         struct FSMenu* fsmenu = fsmenu_get();
333         struct FileSelectParams* params= ED_fileselect_get_params(sfile);
334
335         if (params->dir[0] != '\0') {
336                 char name[FILE_MAX];
337         
338                 fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, 0, 1);
339                 BLI_make_file_string("/", name, BLI_gethome(), ".Bfs");
340                 fsmenu_write_file(fsmenu, name);
341         }
342
343         ED_area_tag_redraw(sa);
344         return OPERATOR_FINISHED;
345 }
346
347 void FILE_OT_add_bookmark(wmOperatorType *ot)
348 {
349         /* identifiers */
350         ot->name= "Add Bookmark";
351         ot->idname= "FILE_OT_add_bookmark";
352         
353         /* api callbacks */
354         ot->invoke= bookmark_add_invoke;
355         ot->poll= ED_operator_file_active;
356 }
357
358 static int bookmark_delete_invoke(bContext *C, wmOperator *op, wmEvent *event)
359 {
360         ScrArea *sa= CTX_wm_area(C);
361         struct FSMenu* fsmenu = fsmenu_get();
362         int nentries = fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS);
363         
364         if(RNA_struct_find_property(op->ptr, "index")) {
365                 int index = RNA_int_get(op->ptr, "index");
366                 if ( (index >-1) && (index < nentries)) {
367                         char name[FILE_MAX];
368                         
369                         fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index);
370                         BLI_make_file_string("/", name, BLI_gethome(), ".Bfs");
371                         fsmenu_write_file(fsmenu, name);
372                         ED_area_tag_redraw(sa);
373                 }
374         }
375
376         return OPERATOR_FINISHED;
377 }
378
379 void FILE_OT_delete_bookmark(wmOperatorType *ot)
380 {
381         /* identifiers */
382         ot->name= "Delete Bookmark";
383         ot->idname= "FILE_OT_delete_bookmark";
384         
385         /* api callbacks */
386         ot->invoke= bookmark_delete_invoke;
387         ot->poll= ED_operator_file_active;
388
389         RNA_def_int(ot->srna, "index", -1, -1, 20000, "Index", "", -1, 20000);
390 }
391
392
393 static int loadimages_invoke(bContext *C, wmOperator *op, wmEvent *event)
394 {
395         ScrArea *sa= CTX_wm_area(C);
396         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
397         if (sfile->files) {
398                 filelist_loadimage_timer(sfile->files);
399                 if (filelist_changed(sfile->files)) {
400                         ED_area_tag_redraw(sa);
401                 }
402         }
403
404         return OPERATOR_FINISHED;
405 }
406
407 void FILE_OT_loadimages(wmOperatorType *ot)
408 {
409         
410         /* identifiers */
411         ot->name= "Load Images";
412         ot->idname= "FILE_OT_loadimages";
413         
414         /* api callbacks */
415         ot->invoke= loadimages_invoke;
416         
417         ot->poll= ED_operator_file_active;
418 }
419
420 int file_hilight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
421 {
422         FileSelectParams* params;
423         int numfiles, actfile;
424         
425         if(sfile==NULL || sfile->files==NULL) return 0;
426         
427         numfiles = filelist_numfiles(sfile->files);
428         params = ED_fileselect_get_params(sfile);
429
430         actfile = find_file_mouse(sfile, ar, mx , my, 0);
431         
432         if (params && (actfile >= 0) && (actfile < numfiles) ) {
433                 params->active_file=actfile;
434                 return 1;
435         } 
436         params->active_file= -1;
437         return 0;
438 }
439
440 static int file_highlight_invoke(bContext *C, wmOperator *op, wmEvent *event)
441 {
442         ARegion *ar= CTX_wm_region(C);
443         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
444         
445         if( file_hilight_set(sfile, ar, event->x - ar->winrct.xmin, event->y - ar->winrct.ymin)) {
446                 ED_area_tag_redraw(CTX_wm_area(C));
447         }
448         
449         return OPERATOR_FINISHED;
450 }
451
452 void FILE_OT_highlight(struct wmOperatorType *ot)
453 {
454         /* identifiers */
455         ot->name= "Highlight File";
456         ot->idname= "FILE_OT_highlight";
457         
458         /* api callbacks */
459         ot->invoke= file_highlight_invoke;
460         ot->poll= ED_operator_file_active;
461 }
462
463 int file_cancel_exec(bContext *C, wmOperator *unused)
464 {
465         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
466
467         folderlist_free(sfile->folders_prev);
468         folderlist_free(sfile->folders_next);
469
470         WM_event_fileselect_event(C, sfile->op, EVT_FILESELECT_CANCEL);
471         sfile->op = NULL;
472         
473         return OPERATOR_FINISHED;
474 }
475
476 void FILE_OT_cancel(struct wmOperatorType *ot)
477 {
478         /* identifiers */
479         ot->name= "Cancel File Load";
480         ot->idname= "FILE_OT_cancel";
481         
482         /* api callbacks */
483         ot->exec= file_cancel_exec;
484         ot->poll= ED_operator_file_active;
485 }
486
487 /* sends events now, so things get handled on windowqueue level */
488 int file_exec(bContext *C, wmOperator *unused)
489 {
490         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
491         char name[FILE_MAX];
492         
493         if(sfile->op) {
494                 wmOperator *op= sfile->op;
495                 
496                 sfile->op = NULL;
497                 BLI_strncpy(name, sfile->params->dir, sizeof(name));
498                 strcat(name, sfile->params->file);
499                 RNA_string_set(op->ptr, "filename", name);
500                 
501                 /* some ops have multiple files to select */
502                 {
503                         PointerRNA itemptr;
504                         int i, numfiles = filelist_numfiles(sfile->files);
505                         struct direntry *file;
506                         if(RNA_struct_find_property(op->ptr, "files")) {
507                                 for (i=0; i<numfiles; i++) {
508                                         file = filelist_file(sfile->files, i);
509                                         if(file->flags & ACTIVE) {
510                                                 if ((file->type & S_IFDIR)==0) {
511                                                         RNA_collection_add(op->ptr, "files", &itemptr);
512                                                         RNA_string_set(&itemptr, "name", file->relname);
513                                                 }
514                                         }
515                                 }
516                         }
517                         
518                         if(RNA_struct_find_property(op->ptr, "dirs")) {
519                                 for (i=0; i<numfiles; i++) {
520                                         file = filelist_file(sfile->files, i);
521                                         if(file->flags & ACTIVE) {
522                                                 if ((file->type & S_IFDIR)) {
523                                                         RNA_collection_add(op->ptr, "dirs", &itemptr);
524                                                         RNA_string_set(&itemptr, "name", file->relname);
525                                                 }
526                                         }
527                                 }
528                         }
529                 }
530                 
531                 folderlist_free(sfile->folders_prev);
532                 folderlist_free(sfile->folders_next);
533
534                 fsmenu_insert_entry(fsmenu_get(), FS_CATEGORY_RECENT, sfile->params->dir,0, 1);
535                 BLI_make_file_string(G.sce, name, BLI_gethome(), ".Bfs");
536                 fsmenu_write_file(fsmenu_get(), name);
537                 WM_event_fileselect_event(C, op, EVT_FILESELECT_EXEC);
538         }
539                                 
540         return OPERATOR_FINISHED;
541 }
542
543 void FILE_OT_exec(struct wmOperatorType *ot)
544 {
545         /* identifiers */
546         ot->name= "Execute File Window";
547         ot->idname= "FILE_OT_exec";
548         
549         /* api callbacks */
550         ot->exec= file_exec;
551         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
552 }
553
554
555 int file_parent_exec(bContext *C, wmOperator *unused)
556 {
557         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
558         
559         if(sfile->params) {
560                 if (BLI_has_parent(sfile->params->dir)) {
561                         BLI_parent_dir(sfile->params->dir);
562                         BLI_cleanup_dir(G.sce, sfile->params->dir);
563                         file_change_dir(sfile);
564                         WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL);
565                 }
566         }               
567         
568         return OPERATOR_FINISHED;
569
570 }
571
572
573 void FILE_OT_parent(struct wmOperatorType *ot)
574 {
575         /* identifiers */
576         ot->name= "Parent File";
577         ot->idname= "FILE_OT_parent";
578         
579         /* api callbacks */
580         ot->exec= file_parent_exec;
581         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
582 }
583
584
585 int file_refresh_exec(bContext *C, wmOperator *unused)
586 {
587         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
588         
589         file_change_dir(sfile);
590
591         WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL);
592
593         return OPERATOR_FINISHED;
594
595 }
596
597 void FILE_OT_previous(struct wmOperatorType *ot)
598 {
599         /* identifiers */
600         ot->name= "Previous Folder";
601         ot->idname= "FILE_OT_previous";
602         
603         /* api callbacks */
604         ot->exec= file_previous_exec;
605         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
606 }
607
608 int file_previous_exec(bContext *C, wmOperator *unused)
609 {
610         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
611
612         if(sfile->params) {
613                 if (!sfile->folders_next)
614                         sfile->folders_next = folderlist_new();
615
616                 folderlist_pushdir(sfile->folders_next, sfile->params->dir);
617                 folderlist_popdir(sfile->folders_prev, sfile->params->dir);
618                 folderlist_pushdir(sfile->folders_next, sfile->params->dir);
619
620                 file_change_dir(sfile);
621         }
622         WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL);
623
624         return OPERATOR_FINISHED;
625 }
626
627 void FILE_OT_next(struct wmOperatorType *ot)
628 {
629         /* identifiers */
630         ot->name= "Next Folder";
631         ot->idname= "FILE_OT_next";
632         
633         /* api callbacks */
634         ot->exec= file_next_exec;
635         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
636 }
637
638 int file_next_exec(bContext *C, wmOperator *unused)
639 {
640         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
641                 if(sfile->params) {
642                         if (!sfile->folders_next)
643                         sfile->folders_next = folderlist_new();
644
645                 folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
646                 folderlist_popdir(sfile->folders_next, sfile->params->dir);
647
648                 // update folder_prev so we can check for it in folderlist_clear_next()
649                 folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
650
651                 file_change_dir(sfile);
652         }               
653         WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL);
654
655         return OPERATOR_FINISHED;
656 }
657
658 int file_directory_new_exec(bContext *C, wmOperator *unused)
659 {
660         char tmpstr[FILE_MAX];
661         char tmpdir[FILE_MAXFILE];
662         int i = 1;
663
664         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
665         
666         if(sfile->params) {
667                  
668                 BLI_strncpy(tmpstr, sfile->params->dir, FILE_MAX);
669                 BLI_join_dirfile(tmpstr, tmpstr, "New Folder");
670                 while (BLI_exists(tmpstr)) {
671                         BLI_snprintf(tmpdir, FILE_MAXFILE, "New Folder(%d)", i++);
672                         BLI_strncpy(tmpstr, sfile->params->dir, FILE_MAX);
673                         BLI_join_dirfile(tmpstr, tmpstr, tmpdir);
674                 }
675                 BLI_recurdir_fileops(tmpstr);
676                 if (!BLI_exists(tmpstr)) {
677                         filelist_free(sfile->files);
678                         filelist_parent(sfile->files);
679                         BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), FILE_MAX);
680                 } 
681         }               
682         WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL);
683
684         return OPERATOR_FINISHED;
685 }
686
687
688 void FILE_OT_directory_new(struct wmOperatorType *ot)
689 {
690         /* identifiers */
691         ot->name= "Create New Directory";
692         ot->idname= "FILE_OT_directory_new";
693         
694         /* api callbacks */
695         ot->invoke= WM_operator_confirm;
696         ot->exec= file_directory_new_exec;
697         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
698 }
699
700 int file_directory_exec(bContext *C, wmOperator *unused)
701 {
702         char tmpstr[FILE_MAX];
703
704         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
705         
706         if(sfile->params) {
707
708                 if ( sfile->params->dir[0] == '~' ) {
709                         if (sfile->params->dir[1] == '\0') {
710                                 BLI_strncpy(sfile->params->dir, BLI_gethome(), sizeof(sfile->params->dir) );
711                         } else {
712                                 /* replace ~ with home */
713                                 char homestr[FILE_MAX];
714                                 char *d = &sfile->params->dir[1];
715
716                                 while ( (*d == '\\') || (*d == '/') )
717                                         d++;
718                                 BLI_strncpy(homestr,  BLI_gethome(), FILE_MAX);
719                                 BLI_add_slash(homestr);
720                                 BLI_join_dirfile(tmpstr, homestr, d);
721                                 BLI_strncpy(sfile->params->dir, tmpstr, sizeof(sfile->params->dir));
722                         }
723                 }
724 #ifdef WIN32
725                 if (sfile->params->dir[0] == '\0')
726                         get_default_root(sfile->params->dir);
727 #endif
728                 BLI_cleanup_dir(G.sce, sfile->params->dir);
729                 BLI_add_slash(sfile->params->dir);
730                 file_change_dir(sfile);
731                 WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL);
732         }               
733         
734
735         return OPERATOR_FINISHED;
736 }
737
738 int file_filename_exec(bContext *C, wmOperator *unused)
739 {
740         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
741         
742         if(sfile->params) {
743                 if (file_select_match(sfile, sfile->params->file))
744                 {
745                         sfile->params->file[0] = '\0';
746                         WM_event_add_notifier(C, NC_FILE|ND_PARAMS, NULL);
747                 }
748         }               
749
750         return OPERATOR_FINISHED;
751 }
752
753
754 void FILE_OT_refresh(struct wmOperatorType *ot)
755 {
756         /* identifiers */
757         ot->name= "Refresh Filelist";
758         ot->idname= "FILE_OT_refresh";
759         
760         /* api callbacks */
761         ot->exec= file_refresh_exec;
762         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
763 }
764
765 int file_hidedot_exec(bContext *C, wmOperator *unused)
766 {
767         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
768         
769         if(sfile->params) {
770                 sfile->params->flag ^= FILE_HIDE_DOT;
771                 filelist_free(sfile->files);
772                 sfile->params->active_file = -1;
773                 WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL);
774         }
775         
776         return OPERATOR_FINISHED;
777
778 }
779
780
781 void FILE_OT_hidedot(struct wmOperatorType *ot)
782 {
783         /* identifiers */
784         ot->name= "Toggle Hide Dot Files";
785         ot->idname= "FILE_OT_hidedot";
786         
787         /* api callbacks */
788         ot->exec= file_hidedot_exec;
789         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
790 }
791
792 struct ARegion *file_buttons_region(struct ScrArea *sa)
793 {
794         ARegion *ar, *arnew;
795         
796         for(ar= sa->regionbase.first; ar; ar= ar->next)
797                 if(ar->regiontype==RGN_TYPE_CHANNELS)
798                         return ar;
799
800         /* add subdiv level; after header */
801         for(ar= sa->regionbase.first; ar; ar= ar->next)
802                 if(ar->regiontype==RGN_TYPE_HEADER)
803                         break;
804         
805         /* is error! */
806         if(ar==NULL) return NULL;
807         
808         arnew= MEM_callocN(sizeof(ARegion), "buttons for file panels");
809         
810         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
811         arnew->regiontype= RGN_TYPE_CHANNELS;
812         arnew->alignment= RGN_ALIGN_LEFT;
813         
814         arnew->flag = RGN_FLAG_HIDDEN;
815         
816         return arnew;
817 }
818
819 int file_bookmark_toggle_exec(bContext *C, wmOperator *unused)
820 {
821         ScrArea *sa= CTX_wm_area(C);
822         ARegion *ar= file_buttons_region(sa);
823         
824         if(ar) {
825                 ar->flag ^= RGN_FLAG_HIDDEN;
826                 ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */
827                 
828                 ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
829                 ED_area_tag_redraw(sa);
830         }
831         return OPERATOR_FINISHED;
832 }
833
834 void FILE_OT_bookmark_toggle(struct wmOperatorType *ot)
835 {
836         /* identifiers */
837         ot->name= "Toggle Bookmarks";
838         ot->idname= "FILE_OT_bookmark_toggle";
839         
840         /* api callbacks */
841         ot->exec= file_bookmark_toggle_exec;
842         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
843 }
844
845
846 int file_filenum_exec(bContext *C, wmOperator *op)
847 {
848         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
849         
850         int inc = RNA_int_get(op->ptr, "increment");
851         if(sfile->params && (inc != 0)) {
852                 BLI_newname(sfile->params->file, inc);
853                 WM_event_add_notifier(C, NC_WINDOW, NULL);
854         }
855         
856         return OPERATOR_FINISHED;
857
858 }
859
860 void FILE_OT_filenum(struct wmOperatorType *ot)
861 {
862         /* identifiers */
863         ot->name= "Increment Number in Filename";
864         ot->idname= "FILE_OT_filenum";
865         
866         /* api callbacks */
867         ot->exec= file_filenum_exec;
868         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
869
870         /* props */
871         RNA_def_int(ot->srna, "increment", 1, 0, 100, "Increment", "", 0,100);
872 }
873
874 int file_delete_poll(bContext *C)
875 {
876         int poll = ED_operator_file_active(C);
877         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
878         struct direntry* file;
879
880         if(!sfile->params ) poll= 0;
881
882         if (sfile->params->active_file < 0) { 
883                 poll= 0;
884         } else {
885                 file = filelist_file(sfile->files, sfile->params->active_file);
886                 if (file && S_ISDIR(file->type)) poll= 0;
887         }
888         return poll;
889 }
890
891 int file_delete_exec(bContext *C, wmOperator *op)
892 {
893         char str[FILE_MAX];
894         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
895         struct direntry* file;
896         
897         
898         file = filelist_file(sfile->files, sfile->params->active_file);
899         BLI_make_file_string(G.sce, str, sfile->params->dir, file->relname);
900         BLI_delete(str, 0, 0);  
901         WM_event_add_notifier(C, NC_FILE | ND_FILELIST, NULL);
902         
903         return OPERATOR_FINISHED;
904
905 }
906
907 void FILE_OT_delete(struct wmOperatorType *ot)
908 {
909         /* identifiers */
910         ot->name= "Delete File";
911         ot->idname= "FILE_OT_delete";
912         
913         /* api callbacks */
914         ot->invoke= WM_operator_confirm;
915         ot->exec= file_delete_exec;
916         ot->poll= file_delete_poll; /* <- important, handler is on window level */
917 }
918