doxygen: blender/editors tagged.
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 /** \file blender/editors/space_file/file_ops.c
30  *  \ingroup spfile
31  */
32
33
34 #include "BKE_context.h"
35 #include "BKE_screen.h"
36 #include "BKE_global.h"
37 #include "BKE_report.h"
38 #include "BKE_main.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_utildefines.h"
42 #include "BLI_storage_types.h"
43 #ifdef WIN32
44 #include "BLI_winstuff.h"
45 #endif
46
47 #include "ED_screen.h"
48 #include "ED_fileselect.h"
49
50 #include "MEM_guardedalloc.h"
51
52 #include "RNA_access.h"
53 #include "RNA_define.h"
54
55 #include "UI_view2d.h"
56
57 #include "WM_api.h"
58 #include "WM_types.h"
59
60 #include "file_intern.h"
61 #include "filelist.h"
62 #include "fsmenu.h"
63
64 #include <stdlib.h>
65 #include <string.h>
66 #include <stdio.h>
67
68 /* for events */
69 #define NOTACTIVEFILE                   0
70 #define ACTIVATE                        1
71 #define INACTIVATE                      2
72
73 /* ---------- FILE SELECTION ------------ */
74
75 static int find_file_mouse(SpaceFile *sfile, struct ARegion* ar, int clamp_bounds, int x, int y)
76 {
77         float fx,fy;
78         int active_file = -1;
79         View2D* v2d = &ar->v2d;
80
81         UI_view2d_region_to_view(v2d, x, y, &fx, &fy);
82
83         active_file = ED_fileselect_layout_offset(sfile->layout, clamp_bounds, v2d->tot.xmin + fx, v2d->tot.ymax - fy);
84         
85         return active_file;
86 }
87
88
89 static void file_deselect_all(SpaceFile* sfile)
90 {
91         int numfiles = filelist_numfiles(sfile->files);
92         int i;
93
94         for ( i=0; i < numfiles; ++i) {
95                 struct direntry* file = filelist_file(sfile->files, i);
96                 if (file && (file->flags & ACTIVEFILE)) {
97                         file->flags &= ~ACTIVEFILE;
98                 }
99         }
100 }
101
102 typedef enum FileSelect { FILE_SELECT_DIR = 1, 
103   FILE_SELECT_FILE = 2 } FileSelect;
104
105
106 static void clamp_to_filelist(int numfiles, int *first_file, int *last_file)
107 {
108         /* border select before the first file */
109         if ( (*first_file < 0) && (*last_file >=0 ) ) {
110                 *first_file = 0;
111         }
112         /* don't select if everything is outside filelist */
113         if ( (*first_file >= numfiles) && ((*last_file < 0) || (*last_file >= numfiles)) ) {
114                 *first_file = -1;
115                 *last_file = -1;
116         }
117         
118         /* fix if last file invalid */
119         if ( (*first_file > 0) && (*last_file < 0) )
120                 *last_file = numfiles-1;
121
122         /* clamp */
123         if ( (*first_file >= numfiles) ) {
124                 *first_file = numfiles-1;
125         }
126         if ( (*last_file >= numfiles) ) {
127                 *last_file = numfiles-1;
128         }
129 }
130
131 static FileSelect file_select(bContext* C, const rcti* rect, short selecting, short toggle_one, short fill)
132 {
133         ARegion *ar= CTX_wm_region(C);
134         SpaceFile *sfile= CTX_wm_space_file(C);
135         int first_file = -1;
136         int last_file = -1;
137         int act_file;
138         FileSelect retval = FILE_SELECT_FILE;
139
140         FileSelectParams *params = ED_fileselect_get_params(sfile);
141         // FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
142
143         int numfiles = filelist_numfiles(sfile->files);
144         
145         params->selstate = NOTACTIVEFILE;
146         first_file = find_file_mouse(sfile, ar, 1, rect->xmin, rect->ymax);
147         last_file = find_file_mouse(sfile, ar, 1, rect->xmax, rect->ymin);
148         
149         clamp_to_filelist(numfiles, &first_file, &last_file);
150
151         if (fill && (last_file >= 0) && (last_file < numfiles) ) {
152                 int f= last_file;
153                 while (f >= 0) {
154                         struct direntry* file = filelist_file(sfile->files, f);
155                         if (file->flags & ACTIVEFILE)
156                                 break;
157                         f--;
158                 }
159                 if (f >= 0) {
160                         first_file = f+1;
161                 }
162         }
163
164         /* select all valid files between first and last indicated */
165         if ( (first_file >= 0) && (first_file < numfiles) && (last_file >= 0) && (last_file < numfiles) ) {
166                 for (act_file = first_file; act_file <= last_file; act_file++) {
167                         struct direntry* file = filelist_file(sfile->files, act_file);
168                         
169                         if (toggle_one) {
170                                 if (file->flags & ACTIVEFILE) {
171                                         file->flags &= ~ACTIVEFILE;
172                                         selecting=0;
173                                 } else
174                                         file->flags |= ACTIVEFILE;
175                         } else if (selecting) 
176                                 file->flags |= ACTIVEFILE;
177                         else
178                                 file->flags &= ~ACTIVEFILE;
179                 }
180         }
181
182         /* Don't act on multiple selected files */
183         if (first_file != last_file) selecting= 0;
184
185         /* make the last file active */
186         if (selecting && (last_file >= 0 && last_file < numfiles)) {
187                 struct direntry* file = filelist_file(sfile->files, last_file);
188                 params->active_file = last_file;
189
190                 if(file && S_ISDIR(file->type)) {
191                         /* the path is too long and we are not going up! */
192                         if (strcmp(file->relname, "..") && strlen(params->dir) + strlen(file->relname) >= FILE_MAX ) 
193                         {
194                                 // XXX error("Path too long, cannot enter this directory");
195                         } else {
196                                 if (strcmp(file->relname, "..")==0) {    
197                                         /* avoids /../../ */     
198                                         BLI_parent_dir(params->dir);     
199                                 } else {
200                                         BLI_cleanup_dir(G.main->name, params->dir);
201                                         strcat(params->dir, file->relname);
202                                         BLI_add_slash(params->dir);
203                                 }
204
205                                 file_change_dir(C, 0);
206                                 retval = FILE_SELECT_DIR;
207                         }
208                 }
209                 else if (file)
210                 {
211                         if (file->relname) {
212                                 BLI_strncpy(params->file, file->relname, FILE_MAXFILE);
213                         }
214                         
215                 }       
216         }
217         
218         /* update operator for name change event */
219         file_draw_check_cb(C, NULL, NULL);
220         
221         return retval;
222 }
223
224
225
226 static int file_border_select_exec(bContext *C, wmOperator *op)
227 {
228         ARegion *ar= CTX_wm_region(C);
229         short selecting;
230         rcti rect;
231         
232         selecting= (RNA_int_get(op->ptr, "gesture_mode")==GESTURE_MODAL_SELECT);
233         rect.xmin= RNA_int_get(op->ptr, "xmin");
234         rect.ymin= RNA_int_get(op->ptr, "ymin");
235         rect.xmax= RNA_int_get(op->ptr, "xmax");
236         rect.ymax= RNA_int_get(op->ptr, "ymax");
237
238         BLI_isect_rcti(&(ar->v2d.mask), &rect, &rect);
239         
240         if (FILE_SELECT_DIR == file_select(C, &rect, selecting, 0, 0)) {
241                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
242         } else {
243                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL);
244         }
245         return OPERATOR_FINISHED;
246 }
247
248 void FILE_OT_select_border(wmOperatorType *ot)
249 {
250         /* identifiers */
251         ot->name= "Activate/Select File";
252         ot->description= "Activate/select the file(s) contained in the border";
253         ot->idname= "FILE_OT_select_border";
254         
255         /* api callbacks */
256         ot->invoke= WM_border_select_invoke;
257         ot->exec= file_border_select_exec;
258         ot->modal= WM_border_select_modal;
259         ot->poll= ED_operator_file_active;
260
261         /* rna */
262         WM_operator_properties_gesture_border(ot, 0);
263 }
264
265 static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
266 {
267         ARegion *ar= CTX_wm_region(C);
268         SpaceFile *sfile= CTX_wm_space_file(C);
269         rcti rect;
270         int extend = RNA_boolean_get(op->ptr, "extend");
271         int fill = RNA_boolean_get(op->ptr, "fill");
272
273         if(ar->regiontype != RGN_TYPE_WINDOW)
274                 return OPERATOR_CANCELLED;
275
276         rect.xmin = rect.xmax = event->x - ar->winrct.xmin;
277         rect.ymin = rect.ymax = event->y - ar->winrct.ymin;
278
279         if(!BLI_in_rcti(&ar->v2d.mask, rect.xmin, rect.ymin))
280                 return OPERATOR_CANCELLED;
281
282         /* single select, deselect all selected first */
283         if (!extend) file_deselect_all(sfile);
284
285         if (FILE_SELECT_DIR == file_select(C, &rect, 1, extend, fill ))
286                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
287         else
288                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL);
289
290         WM_event_add_mousemove(C); /* for directory changes */
291         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL);
292
293         return OPERATOR_FINISHED;
294 }
295
296 void FILE_OT_select(wmOperatorType *ot)
297 {
298         /* identifiers */
299         ot->name= "Activate/Select File";
300         ot->description= "Activate/select file";
301         ot->idname= "FILE_OT_select";
302         
303         /* api callbacks */
304         ot->invoke= file_select_invoke;
305         ot->poll= ED_operator_file_active;
306
307         /* rna */
308         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first.");
309         RNA_def_boolean(ot->srna, "fill", 0, "Fill", "Select everything beginning with the last selection.");
310 }
311
312 static int file_select_all_exec(bContext *C, wmOperator *UNUSED(op))
313 {
314         ScrArea *sa= CTX_wm_area(C);
315         SpaceFile *sfile= CTX_wm_space_file(C);
316         int numfiles = filelist_numfiles(sfile->files);
317         int i;
318         int select = 1;
319
320         /* if any file is selected, deselect all first */
321         for ( i=0; i < numfiles; ++i) {
322                 struct direntry* file = filelist_file(sfile->files, i);
323                 if (file && (file->flags & ACTIVEFILE)) {
324                         file->flags &= ~ACTIVEFILE;
325                         select = 0;
326                         ED_area_tag_redraw(sa);
327                 }
328         }
329         /* select all only if previously no file was selected */
330         if (select) {
331                 for ( i=0; i < numfiles; ++i) {
332                         struct direntry* file = filelist_file(sfile->files, i);
333                         if(file && !S_ISDIR(file->type)) {
334                                 file->flags |= ACTIVEFILE;
335                                 ED_area_tag_redraw(sa);
336                         }
337                 }
338         }
339         return OPERATOR_FINISHED;
340 }
341
342 void FILE_OT_select_all_toggle(wmOperatorType *ot)
343 {
344         /* identifiers */
345         ot->name= "Select/Deselect All Files";
346         ot->description= "Select/deselect all files";
347         ot->idname= "FILE_OT_select_all_toggle";
348         
349         /* api callbacks */
350         ot->exec= file_select_all_exec;
351
352         /* rna */
353
354         ot->poll= ED_operator_file_active;
355 }
356
357 /* ---------- BOOKMARKS ----------- */
358
359 static int bookmark_select_exec(bContext *C, wmOperator *op)
360 {
361         SpaceFile *sfile= CTX_wm_space_file(C);
362
363         if(RNA_struct_find_property(op->ptr, "dir")) {
364                 char entry[256];
365                 FileSelectParams* params = sfile->params;
366
367                 RNA_string_get(op->ptr, "dir", entry);
368                 BLI_strncpy(params->dir, entry, sizeof(params->dir));
369                 BLI_cleanup_dir(G.main->name, params->dir);
370                 file_change_dir(C, 1);
371
372                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
373         }
374         
375         return OPERATOR_FINISHED;
376 }
377
378 void FILE_OT_select_bookmark(wmOperatorType *ot)
379 {
380         /* identifiers */
381         ot->name= "Select Directory";
382         ot->description= "Select a bookmarked directory";
383         ot->idname= "FILE_OT_select_bookmark";
384         
385         /* api callbacks */
386         ot->exec= bookmark_select_exec;
387         ot->poll= ED_operator_file_active;
388
389         RNA_def_string(ot->srna, "dir", "", 256, "Dir", "");
390 }
391
392 static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op))
393 {
394         ScrArea *sa= CTX_wm_area(C);
395         SpaceFile *sfile= CTX_wm_space_file(C);
396         struct FSMenu* fsmenu = fsmenu_get();
397         struct FileSelectParams* params= ED_fileselect_get_params(sfile);
398
399         if (params->dir[0] != '\0') {
400                 char name[FILE_MAX];
401         
402                 fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, 0, 1);
403                 BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
404                 fsmenu_write_file(fsmenu, name);
405         }
406
407         ED_area_tag_redraw(sa);
408         return OPERATOR_FINISHED;
409 }
410
411 void FILE_OT_bookmark_add(wmOperatorType *ot)
412 {
413         /* identifiers */
414         ot->name= "Add Bookmark";
415         ot->description= "Add a bookmark for the selected/active directory";
416         ot->idname= "FILE_OT_bookmark_add";
417         
418         /* api callbacks */
419         ot->exec= bookmark_add_exec;
420         ot->poll= ED_operator_file_active;
421 }
422
423 static int bookmark_delete_exec(bContext *C, wmOperator *op)
424 {
425         ScrArea *sa= CTX_wm_area(C);
426         struct FSMenu* fsmenu = fsmenu_get();
427         int nentries = fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS);
428         
429         if(RNA_struct_find_property(op->ptr, "index")) {
430                 int index = RNA_int_get(op->ptr, "index");
431                 if ( (index >-1) && (index < nentries)) {
432                         char name[FILE_MAX];
433                         
434                         fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index);
435                         BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
436                         fsmenu_write_file(fsmenu, name);
437                         ED_area_tag_redraw(sa);
438                 }
439         }
440
441         return OPERATOR_FINISHED;
442 }
443
444 void FILE_OT_delete_bookmark(wmOperatorType *ot)
445 {
446         /* identifiers */
447         ot->name= "Delete Bookmark";
448         ot->description= "Delete selected bookmark";
449         ot->idname= "FILE_OT_delete_bookmark";
450         
451         /* api callbacks */
452         ot->exec= bookmark_delete_exec;
453         ot->poll= ED_operator_file_active;
454
455         RNA_def_int(ot->srna, "index", -1, -1, 20000, "Index", "", -1, 20000);
456 }
457
458 int file_hilight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
459 {
460         FileSelectParams* params;
461         int numfiles, actfile, origfile;
462         
463         if(sfile==NULL || sfile->files==NULL) return 0;
464
465         numfiles = filelist_numfiles(sfile->files);
466         params = ED_fileselect_get_params(sfile);
467
468         origfile= params->active_file;
469
470         mx -= ar->winrct.xmin;
471         my -= ar->winrct.ymin;
472
473         if(BLI_in_rcti(&ar->v2d.mask, mx, my)) {
474                 actfile = find_file_mouse(sfile, ar, 0, mx , my);
475
476                 if((actfile >= 0) && (actfile < numfiles))
477                         params->active_file=actfile;
478                 else
479                         params->active_file= -1;
480         }
481         else
482                 params->active_file= -1;
483
484         return (params->active_file != origfile);
485 }
486
487 static int file_highlight_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
488 {
489         ARegion *ar= CTX_wm_region(C);
490         SpaceFile *sfile= CTX_wm_space_file(C);
491
492         if(!file_hilight_set(sfile, ar, event->x, event->y))
493                 return OPERATOR_CANCELLED;
494
495         ED_area_tag_redraw(CTX_wm_area(C));
496         
497         return OPERATOR_FINISHED;
498 }
499
500 void FILE_OT_highlight(struct wmOperatorType *ot)
501 {
502         /* identifiers */
503         ot->name= "Highlight File";
504         ot->description= "Highlight selected file(s)";
505         ot->idname= "FILE_OT_highlight";
506         
507         /* api callbacks */
508         ot->invoke= file_highlight_invoke;
509         ot->poll= ED_operator_file_active;
510 }
511
512 int file_cancel_exec(bContext *C, wmOperator *UNUSED(unused))
513 {
514         SpaceFile *sfile= CTX_wm_space_file(C);
515         wmOperator *op = sfile->op;
516         
517         sfile->op = NULL;
518
519         WM_event_fileselect_event(C, op, EVT_FILESELECT_CANCEL);
520         
521         return OPERATOR_FINISHED;
522 }
523
524 static int file_operator_poll(bContext *C)
525 {
526         int poll = ED_operator_file_active(C);
527         SpaceFile *sfile= CTX_wm_space_file(C);
528
529         if (!sfile || !sfile->op) poll= 0;
530
531         return poll;
532 }
533
534 void FILE_OT_cancel(struct wmOperatorType *ot)
535 {
536         /* identifiers */
537         ot->name= "Cancel File Load";
538         ot->description= "Cancel loading of selected file";
539         ot->idname= "FILE_OT_cancel";
540         
541         /* api callbacks */
542         ot->exec= file_cancel_exec;
543         ot->poll= file_operator_poll;
544 }
545
546
547 void file_sfile_to_operator(wmOperator *op, SpaceFile *sfile, char *filepath)
548 {
549         BLI_join_dirfile(filepath, FILE_MAX, sfile->params->dir, sfile->params->file); /* XXX, not real length */
550         if(RNA_struct_find_property(op->ptr, "relative_path")) {
551                 if(RNA_boolean_get(op->ptr, "relative_path")) {
552                         BLI_path_rel(filepath, G.main->name);
553                 }
554         }
555
556         if(RNA_struct_find_property(op->ptr, "filename")) {
557                 RNA_string_set(op->ptr, "filename", sfile->params->file);
558         }
559         if(RNA_struct_find_property(op->ptr, "directory")) {
560                 RNA_string_set(op->ptr, "directory", sfile->params->dir);
561         }
562         if(RNA_struct_find_property(op->ptr, "filepath")) {
563                 RNA_string_set(op->ptr, "filepath", filepath);
564         }
565         
566         /* some ops have multiple files to select */
567         {
568                 PointerRNA itemptr;
569                 int i, numfiles = filelist_numfiles(sfile->files);
570                 struct direntry *file;
571                 if(RNA_struct_find_property(op->ptr, "files")) {
572                         for (i=0; i<numfiles; i++) {
573                                 file = filelist_file(sfile->files, i);
574                                 if(file->flags & ACTIVEFILE) {
575                                         if ((file->type & S_IFDIR)==0) {
576                                                 RNA_collection_add(op->ptr, "files", &itemptr);
577                                                 RNA_string_set(&itemptr, "name", file->relname);
578                                         }
579                                 }
580                         }
581                 }
582                 
583                 if(RNA_struct_find_property(op->ptr, "dirs")) {
584                         for (i=0; i<numfiles; i++) {
585                                 file = filelist_file(sfile->files, i);
586                                 if(file->flags & ACTIVEFILE) {
587                                         if ((file->type & S_IFDIR)) {
588                                                 RNA_collection_add(op->ptr, "dirs", &itemptr);
589                                                 RNA_string_set(&itemptr, "name", file->relname);
590                                         }
591                                 }
592                         }
593                 }
594         }
595 }
596
597 void file_operator_to_sfile(SpaceFile *sfile, wmOperator *op)
598 {
599         int change= FALSE;
600         if(RNA_struct_find_property(op->ptr, "filename")) {
601                 RNA_string_get(op->ptr, "filename", sfile->params->file);
602                 change= TRUE;
603         }
604         if(RNA_struct_find_property(op->ptr, "directory")) {
605                 RNA_string_get(op->ptr, "directory", sfile->params->dir);
606                 change= TRUE;
607         }
608         
609         /* If neither of the above are set, split the filepath back */
610         if(RNA_struct_find_property(op->ptr, "filepath")) {
611                 if(change==FALSE) {
612                         char filepath[FILE_MAX];
613                         RNA_string_get(op->ptr, "filepath", filepath);
614                         BLI_split_dirfile(filepath, sfile->params->dir, sfile->params->file);
615                 }
616         }
617         
618         /* XXX, files and dirs updates missing, not really so important though */
619 }
620
621 void file_draw_check_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
622 {
623         SpaceFile *sfile= CTX_wm_space_file(C);
624         wmOperator *op= sfile->op;
625         if(op) { /* fail on reload */
626                 if(op->type->check) {
627                         char filepath[FILE_MAX];
628                         file_sfile_to_operator(op, sfile, filepath);
629                         
630                         /* redraw */
631                         if(op->type->check(C, op)) {
632                                 file_operator_to_sfile(sfile, op);
633         
634                                 /* redraw, else the changed settings wont get updated */
635                                 ED_area_tag_redraw(CTX_wm_area(C));
636                         }
637                 }
638         }
639 }
640
641 int file_draw_check_exists(SpaceFile *sfile)
642 {
643         if(sfile->op) { /* fails on reload */
644                 if(RNA_struct_find_property(sfile->op->ptr, "check_existing")) {
645                         if(RNA_boolean_get(sfile->op->ptr, "check_existing")) {
646                                 char filepath[FILE_MAX];
647                                 BLI_join_dirfile(filepath, sizeof(filepath), sfile->params->dir, sfile->params->file);
648                                 if(BLI_exists(filepath) && !BLI_is_dir(filepath)) {
649                                         return TRUE;
650                                 }
651                         }
652                 }
653         }
654
655         return FALSE;
656 }
657
658 /* sends events now, so things get handled on windowqueue level */
659 int file_exec(bContext *C, wmOperator *exec_op)
660 {
661         SpaceFile *sfile= CTX_wm_space_file(C);
662         char filepath[FILE_MAX];
663         
664         if(sfile->op) {
665                 wmOperator *op= sfile->op;
666         
667                 /* when used as a macro, for doubleclick, 
668                  to prevent closing when doubleclicking on .. item */
669                 if (RNA_boolean_get(exec_op->ptr, "need_active")) {
670                         int i, active=0;
671                         struct direntry *file;
672                         
673                         for (i=0; i<filelist_numfiles(sfile->files); i++) {
674                                 file = filelist_file(sfile->files, i);
675                                 if(file->flags & ACTIVEFILE) {
676                                         active=1;
677                                 }
678                         }
679                         if (active == 0)
680                                 return OPERATOR_CANCELLED;
681                 }
682                 
683                 sfile->op = NULL;
684
685                 file_sfile_to_operator(op, sfile, filepath);
686
687                 fsmenu_insert_entry(fsmenu_get(), FS_CATEGORY_RECENT, sfile->params->dir,0, 1);
688                 BLI_make_file_string(G.main->name, filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
689                 fsmenu_write_file(fsmenu_get(), filepath);
690                 WM_event_fileselect_event(C, op, EVT_FILESELECT_EXEC);
691
692         }
693                                 
694         return OPERATOR_FINISHED;
695 }
696
697 void FILE_OT_execute(struct wmOperatorType *ot)
698 {
699         /* identifiers */
700         ot->name= "Execute File Window";
701         ot->description= "Execute selected file";
702         ot->idname= "FILE_OT_execute";
703         
704         /* api callbacks */
705         ot->exec= file_exec;
706         ot->poll= file_operator_poll; 
707         
708         RNA_def_boolean(ot->srna, "need_active", 0, "Need Active", "Only execute if there's an active selected file in the file list.");
709 }
710
711
712 int file_parent_exec(bContext *C, wmOperator *UNUSED(unused))
713 {
714         SpaceFile *sfile= CTX_wm_space_file(C);
715         
716         if(sfile->params) {
717                 if (BLI_has_parent(sfile->params->dir)) {
718                         BLI_parent_dir(sfile->params->dir);
719                         BLI_cleanup_dir(G.main->name, sfile->params->dir);
720                         file_change_dir(C, 0);
721                         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
722                 }
723         }               
724         
725         return OPERATOR_FINISHED;
726
727 }
728
729
730 void FILE_OT_parent(struct wmOperatorType *ot)
731 {
732         /* identifiers */
733         ot->name= "Parent File";
734         ot->description= "Move to parent directory";
735         ot->idname= "FILE_OT_parent";
736         
737         /* api callbacks */
738         ot->exec= file_parent_exec;
739         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
740 }
741
742
743 static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused))
744 {
745         SpaceFile *sfile= CTX_wm_space_file(C);
746
747         ED_fileselect_clear(C, sfile);
748
749         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
750
751         return OPERATOR_FINISHED;
752
753 }
754
755 void FILE_OT_previous(struct wmOperatorType *ot)
756 {
757         /* identifiers */
758         ot->name= "Previous Folder";
759         ot->description= "Move to previous folder";
760         ot->idname= "FILE_OT_previous";
761         
762         /* api callbacks */
763         ot->exec= file_previous_exec;
764         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
765 }
766
767 int file_previous_exec(bContext *C, wmOperator *UNUSED(unused))
768 {
769         SpaceFile *sfile= CTX_wm_space_file(C);
770
771         if(sfile->params) {
772                 if (!sfile->folders_next)
773                         sfile->folders_next = folderlist_new();
774
775                 folderlist_pushdir(sfile->folders_next, sfile->params->dir);
776                 folderlist_popdir(sfile->folders_prev, sfile->params->dir);
777                 folderlist_pushdir(sfile->folders_next, sfile->params->dir);
778
779                 file_change_dir(C, 1);
780         }
781         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
782
783         return OPERATOR_FINISHED;
784 }
785
786 void FILE_OT_next(struct wmOperatorType *ot)
787 {
788         /* identifiers */
789         ot->name= "Next Folder";
790         ot->description= "Move to next folder";
791         ot->idname= "FILE_OT_next";
792         
793         /* api callbacks */
794         ot->exec= file_next_exec;
795         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
796 }
797
798 int file_next_exec(bContext *C, wmOperator *UNUSED(unused))
799 {
800         SpaceFile *sfile= CTX_wm_space_file(C);
801         if(sfile->params) {
802                 if (!sfile->folders_next)
803                         sfile->folders_next = folderlist_new();
804
805                 folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
806                 folderlist_popdir(sfile->folders_next, sfile->params->dir);
807
808                 // update folder_prev so we can check for it in folderlist_clear_next()
809                 folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
810
811                 file_change_dir(C, 1);
812         }               
813         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
814
815         return OPERATOR_FINISHED;
816 }
817
818
819 /* only meant for timer usage */
820 static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
821 {
822         ScrArea *sa = CTX_wm_area(C);
823         SpaceFile *sfile= CTX_wm_space_file(C);
824         ARegion *ar, *oldar= CTX_wm_region(C);
825         int numfiles, offset;
826         int edit_idx = 0;
827         int numfiles_layout;
828         int i;
829
830         /* escape if not our timer */
831         if(sfile->smoothscroll_timer==NULL || sfile->smoothscroll_timer!=event->customdata)
832                 return OPERATOR_PASS_THROUGH;
833         
834         numfiles = filelist_numfiles(sfile->files);
835
836         /* check if we are editing a name */
837         for (i=0; i < numfiles; ++i)
838         {
839                 struct direntry *file = filelist_file(sfile->files, i); 
840                 if (file->flags & EDITING) {
841                         edit_idx=i;
842                         break;
843                 }
844         }
845
846         /* if we are not editing, we are done */
847         if (0==edit_idx) {
848                 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
849                 sfile->smoothscroll_timer=NULL;
850                 return OPERATOR_PASS_THROUGH;
851         }
852
853         /* we need the correct area for scrolling */
854         ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
855         if (!ar || ar->regiontype != RGN_TYPE_WINDOW) {
856                 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
857                 sfile->smoothscroll_timer=NULL;
858                 return OPERATOR_PASS_THROUGH;
859         }
860
861         offset = ED_fileselect_layout_offset(sfile->layout, 0, ar->v2d.cur.xmin, -ar->v2d.cur.ymax);
862         if (offset<0) offset=0;
863
864         /* scroll offset is the first file in the row/column we are editing in */
865         if (sfile->scroll_offset == 0) {
866                 if (sfile->layout->flag & FILE_LAYOUT_HOR) {
867                         sfile->scroll_offset = (edit_idx/sfile->layout->rows)*sfile->layout->rows;
868                         if (sfile->scroll_offset <= offset) sfile->scroll_offset -= sfile->layout->rows;
869                 } else {
870                         sfile->scroll_offset = (edit_idx/sfile->layout->columns)*sfile->layout->columns;
871                         if (sfile->scroll_offset <= offset) sfile->scroll_offset -= sfile->layout->columns;
872                 }
873         }
874         
875         numfiles_layout = ED_fileselect_layout_numfiles(sfile->layout, ar);
876         
877         /* check if we have reached our final scroll position */
878         if ( (sfile->scroll_offset >= offset) && (sfile->scroll_offset < offset + numfiles_layout) ) {
879                 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
880                 sfile->smoothscroll_timer=NULL;
881                 return OPERATOR_FINISHED;
882         }
883
884         /* temporarily set context to the main window region, 
885          * so the scroll operators work */
886         CTX_wm_region_set(C, ar);
887         
888         /* scroll one step in the desired direction */
889         if (sfile->scroll_offset < offset) {
890                 if (sfile->layout->flag & FILE_LAYOUT_HOR) {
891                         WM_operator_name_call(C, "VIEW2D_OT_scroll_left", 0, NULL);
892                 } else {
893                         WM_operator_name_call(C, "VIEW2D_OT_scroll_up", 0, NULL);
894                 }
895                 
896         } else {
897                 if (sfile->layout->flag & FILE_LAYOUT_HOR) {
898                         WM_operator_name_call(C, "VIEW2D_OT_scroll_right", 0, NULL);
899                 } else {
900                         WM_operator_name_call(C, "VIEW2D_OT_scroll_down", 0, NULL);
901                 }
902         }
903         
904         ED_region_tag_redraw(CTX_wm_region(C));
905         
906         /* and restore context */
907         CTX_wm_region_set(C, oldar);
908         
909         return OPERATOR_FINISHED;
910 }
911
912
913 void FILE_OT_smoothscroll(wmOperatorType *ot)
914 {
915         
916         /* identifiers */
917         ot->name= "Smooth Scroll";
918         ot->idname= "FILE_OT_smoothscroll";
919         ot->description="Smooth scroll to make editable file visible.";
920         
921         /* api callbacks */
922         ot->invoke= file_smoothscroll_invoke;
923         
924         ot->poll= ED_operator_file_active;
925 }
926
927
928 /* create a new, non-existing folder name, returns 1 if successful, 0 if name couldn't be created.
929    The actual name is returned in 'name', 'folder' contains the complete path, including the new folder name.
930 */
931 static int new_folder_path(const char* parent, char *folder, char *name)
932 {
933         int i = 1;
934         int len = 0;
935
936         BLI_strncpy(name, "New Folder", FILE_MAXFILE);
937         BLI_join_dirfile(folder, FILE_MAX, parent, name); /* XXX, not real length */
938         /* check whether folder with the name already exists, in this case
939            add number to the name. Check length of generated name to avoid
940            crazy case of huge number of folders each named 'New Folder (x)' */
941         while (BLI_exists(folder) && (len<FILE_MAXFILE)) {
942                 len = BLI_snprintf(name, FILE_MAXFILE, "New Folder(%d)", i);
943                 BLI_join_dirfile(folder, FILE_MAX, parent, name); /* XXX, not real length */
944                 i++;
945         }
946
947         return (len<FILE_MAXFILE);
948 }
949
950 int file_directory_new_exec(bContext *C, wmOperator *op)
951 {
952         char name[FILE_MAXFILE];
953         char path[FILE_MAX];
954         int generate_name= 1;
955
956         SpaceFile *sfile= CTX_wm_space_file(C);
957         
958         if(!sfile->params) {
959                 BKE_report(op->reports,RPT_WARNING, "No parent directory given.");
960                 return OPERATOR_CANCELLED;
961         }
962         
963         path[0] = '\0';
964
965         if(RNA_struct_find_property(op->ptr, "directory")) {
966                 RNA_string_get(op->ptr, "directory", path);
967                 if (path[0] != '\0') generate_name= 0;
968         }
969
970         if (generate_name) {
971                 /* create a new, non-existing folder name */
972                 if (!new_folder_path(sfile->params->dir, path, name)) {
973                         BKE_report(op->reports,RPT_ERROR, "Couldn't create new folder name.");
974                         return OPERATOR_CANCELLED;
975                 }
976         }
977
978         /* create the file */
979         BLI_recurdir_fileops(path);
980
981         if (!BLI_exists(path)) {
982                 BKE_report(op->reports,RPT_ERROR, "Couldn't create new folder.");
983                 return OPERATOR_CANCELLED;
984         } 
985
986         /* now remember file to jump into editing */
987         BLI_strncpy(sfile->params->renamefile, name, FILE_MAXFILE);
988
989         /* set timer to smoothly view newly generated file */
990         sfile->smoothscroll_timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER1, 1.0/1000.0);        /* max 30 frs/sec */
991         sfile->scroll_offset=0;
992
993         /* reload dir to make sure we're seeing what's in the directory */
994         ED_fileselect_clear(C, sfile);
995         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
996
997         return OPERATOR_FINISHED;
998 }
999
1000
1001 void FILE_OT_directory_new(struct wmOperatorType *ot)
1002 {
1003         /* identifiers */
1004         ot->name= "Create New Directory";
1005         ot->description= "Create a new directory";
1006         ot->idname= "FILE_OT_directory_new";
1007         
1008         /* api callbacks */
1009         ot->invoke= WM_operator_confirm;
1010         ot->exec= file_directory_new_exec;
1011         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
1012
1013         RNA_def_string_dir_path(ot->srna, "directory", "", FILE_MAX, "Directory", "Name of new directory");
1014
1015 }
1016
1017
1018 static void file_expand_directory(bContext *C)
1019 {
1020         SpaceFile *sfile= CTX_wm_space_file(C);
1021         
1022         if(sfile->params) {
1023                 if ( sfile->params->dir[0] == '~' ) {
1024                         char tmpstr[sizeof(sfile->params->dir)-1];
1025                         BLI_strncpy(tmpstr, sfile->params->dir+1, sizeof(tmpstr));
1026                         BLI_join_dirfile(sfile->params->dir, sizeof(sfile->params->dir), BLI_getDefaultDocumentFolder(), tmpstr);
1027                 }
1028
1029 #ifdef WIN32
1030                 if (sfile->params->dir[0] == '\0')
1031                         get_default_root(sfile->params->dir);
1032 #endif
1033         }
1034 }
1035
1036 static int file_directory_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1037 {
1038         SpaceFile *sfile= CTX_wm_space_file(C);
1039
1040         if(sfile->params) {
1041                 file_expand_directory(C);
1042                 
1043                 if (!BLI_exists(sfile->params->dir)) {
1044                         return WM_operator_confirm_message(C, op, "Create new directory?");
1045                 } 
1046
1047                 return file_directory_exec(C, op);
1048         }
1049
1050         return OPERATOR_CANCELLED;
1051 }
1052
1053
1054
1055 int file_directory_exec(bContext *C, wmOperator *UNUSED(unused))
1056 {
1057         SpaceFile *sfile= CTX_wm_space_file(C);
1058         
1059         if(sfile->params) {
1060                 file_expand_directory(C);
1061
1062                 if (!BLI_exists(sfile->params->dir)) {
1063                         BLI_recurdir_fileops(sfile->params->dir);
1064                 }
1065
1066                 /* special case, user may have pasted a fulepath into the directory */
1067                 if(BLI_exists(sfile->params->dir) && BLI_is_dir(sfile->params->dir) == 0) {
1068                         char path[sizeof(sfile->params->dir)];
1069                         BLI_strncpy(path, sfile->params->dir, sizeof(path));
1070                         BLI_split_dirfile(path, sfile->params->dir, sfile->params->file);
1071                 }
1072
1073                 BLI_cleanup_dir(G.main->name, sfile->params->dir);
1074                 BLI_add_slash(sfile->params->dir);
1075                 file_change_dir(C, 1);
1076
1077                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
1078         }               
1079         
1080
1081         return OPERATOR_FINISHED;
1082 }
1083
1084 int file_filename_exec(bContext *C, wmOperator *UNUSED(unused))
1085 {
1086         SpaceFile *sfile= CTX_wm_space_file(C);
1087         
1088         if(sfile->params) {
1089                 if (file_select_match(sfile, sfile->params->file))
1090                 {
1091                         sfile->params->file[0] = '\0';
1092                         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL);
1093                 }
1094         }               
1095
1096         return OPERATOR_FINISHED;
1097 }
1098
1099 void FILE_OT_directory(struct wmOperatorType *ot)
1100 {
1101         /* identifiers */
1102         ot->name= "Enter Directory Name";
1103         ot->description= "Enter a directory name";
1104         ot->idname= "FILE_OT_directory";
1105         
1106         /* api callbacks */
1107         ot->invoke= file_directory_invoke;
1108         ot->exec= file_directory_exec;
1109         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
1110 }
1111
1112 void FILE_OT_refresh(struct wmOperatorType *ot)
1113 {
1114         /* identifiers */
1115         ot->name= "Refresh Filelist";
1116         ot->description= "Refresh the file list";
1117         ot->idname= "FILE_OT_refresh";
1118         
1119         /* api callbacks */
1120         ot->exec= file_refresh_exec;
1121         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
1122 }
1123
1124 static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused))
1125 {
1126         SpaceFile *sfile= CTX_wm_space_file(C);
1127         
1128         if(sfile->params) {
1129                 sfile->params->flag ^= FILE_HIDE_DOT;
1130                 ED_fileselect_clear(C, sfile);
1131                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
1132         }
1133         
1134         return OPERATOR_FINISHED;
1135 }
1136
1137
1138 void FILE_OT_hidedot(struct wmOperatorType *ot)
1139 {
1140         /* identifiers */
1141         ot->name= "Toggle Hide Dot Files";
1142         ot->description= "Toggle hide hidden dot files";
1143         ot->idname= "FILE_OT_hidedot";
1144         
1145         /* api callbacks */
1146         ot->exec= file_hidedot_exec;
1147         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
1148 }
1149
1150 struct ARegion *file_buttons_region(struct ScrArea *sa)
1151 {
1152         ARegion *ar, *arnew;
1153         
1154         for(ar= sa->regionbase.first; ar; ar= ar->next)
1155                 if(ar->regiontype==RGN_TYPE_CHANNELS)
1156                         return ar;
1157
1158         /* add subdiv level; after header */
1159         for(ar= sa->regionbase.first; ar; ar= ar->next)
1160                 if(ar->regiontype==RGN_TYPE_HEADER)
1161                         break;
1162         
1163         /* is error! */
1164         if(ar==NULL) return NULL;
1165         
1166         arnew= MEM_callocN(sizeof(ARegion), "buttons for file panels");
1167         
1168         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
1169         arnew->regiontype= RGN_TYPE_CHANNELS;
1170         arnew->alignment= RGN_ALIGN_LEFT;
1171         
1172         arnew->flag = RGN_FLAG_HIDDEN;
1173         
1174         return arnew;
1175 }
1176
1177 static int file_bookmark_toggle_exec(bContext *C, wmOperator *UNUSED(unused))
1178 {
1179         ScrArea *sa= CTX_wm_area(C);
1180         ARegion *ar= file_buttons_region(sa);
1181         
1182         if(ar)
1183                 ED_region_toggle_hidden(C, ar);
1184
1185         return OPERATOR_FINISHED;
1186 }
1187
1188 void FILE_OT_bookmark_toggle(struct wmOperatorType *ot)
1189 {
1190         /* identifiers */
1191         ot->name= "Toggle Bookmarks";
1192         ot->description= "Toggle bookmarks display";
1193         ot->idname= "FILE_OT_bookmark_toggle";
1194         
1195         /* api callbacks */
1196         ot->exec= file_bookmark_toggle_exec;
1197         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
1198 }
1199
1200
1201 static int file_filenum_exec(bContext *C, wmOperator *op)
1202 {
1203         SpaceFile *sfile= CTX_wm_space_file(C);
1204         ScrArea *sa= CTX_wm_area(C);
1205         
1206         int inc = RNA_int_get(op->ptr, "increment");
1207         if(sfile->params && (inc != 0)) {
1208                 BLI_newname(sfile->params->file, inc);
1209                 ED_area_tag_redraw(sa);
1210                 file_draw_check_cb(C, NULL, NULL);
1211                 // WM_event_add_notifier(C, NC_WINDOW, NULL);
1212         }
1213         
1214         return OPERATOR_FINISHED;
1215
1216 }
1217
1218 void FILE_OT_filenum(struct wmOperatorType *ot)
1219 {
1220         /* identifiers */
1221         ot->name= "Increment Number in Filename";
1222         ot->description= "Increment number in filename";
1223         ot->idname= "FILE_OT_filenum";
1224         
1225         /* api callbacks */
1226         ot->exec= file_filenum_exec;
1227         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
1228
1229         /* props */
1230         RNA_def_int(ot->srna, "increment", 1, 0, 100, "Increment", "", 0,100);
1231 }
1232
1233 static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
1234 {
1235         ScrArea *sa= CTX_wm_area(C);
1236         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
1237         
1238         if(sfile->params) {
1239                 int idx = sfile->params->active_file;
1240                 int numfiles = filelist_numfiles(sfile->files);
1241                 if ( (0<=idx) && (idx<numfiles) ) {
1242                         struct direntry *file= filelist_file(sfile->files, idx);
1243                         file->flags |= EDITING;
1244                         BLI_strncpy(sfile->params->renameedit, file->relname, FILE_MAXFILE);
1245                         sfile->params->renamefile[0]= '\0';
1246                 }
1247                 ED_area_tag_redraw(sa);
1248         }
1249         
1250         return OPERATOR_FINISHED;
1251
1252 }
1253
1254 static int file_rename_poll(bContext *C)
1255 {
1256         int poll = ED_operator_file_active(C);
1257         SpaceFile *sfile= CTX_wm_space_file(C);
1258
1259         if (sfile && sfile->params) {
1260                 if (sfile->params->active_file < 0) { 
1261                         poll= 0;
1262                 } else {
1263                         char dir[FILE_MAX], group[FILE_MAX];    
1264                         if (filelist_islibrary(sfile->files, dir, group)) poll= 0;
1265                 }
1266         }
1267         else
1268                 poll= 0;
1269         return poll;
1270 }
1271
1272 void FILE_OT_rename(struct wmOperatorType *ot)
1273 {
1274         /* identifiers */
1275         ot->name= "Rename File or Directory";
1276         ot->description= "Rename file or file directory";
1277         ot->idname= "FILE_OT_rename";
1278         
1279         /* api callbacks */
1280         ot->exec= file_rename_exec;
1281         ot->poll= file_rename_poll; 
1282
1283 }
1284
1285 static int file_delete_poll(bContext *C)
1286 {
1287         int poll = ED_operator_file_active(C);
1288         SpaceFile *sfile= CTX_wm_space_file(C);
1289         struct direntry* file;
1290
1291         if (sfile && sfile->params) {
1292                 if (sfile->params->active_file < 0) { 
1293                         poll= 0;
1294                 } else {
1295                         char dir[FILE_MAX], group[FILE_MAX];    
1296                         if (filelist_islibrary(sfile->files, dir, group)) poll= 0;
1297                         file = filelist_file(sfile->files, sfile->params->active_file);
1298                         if (file && S_ISDIR(file->type)) poll= 0;
1299                 }
1300         }
1301         else
1302                 poll= 0;
1303                 
1304         return poll;
1305 }
1306
1307 int file_delete_exec(bContext *C, wmOperator *UNUSED(op))
1308 {
1309         char str[FILE_MAX];
1310         SpaceFile *sfile= CTX_wm_space_file(C);
1311         struct direntry* file;
1312         
1313         
1314         file = filelist_file(sfile->files, sfile->params->active_file);
1315         BLI_make_file_string(G.main->name, str, sfile->params->dir, file->relname);
1316         BLI_delete(str, 0, 0);  
1317         ED_fileselect_clear(C, sfile);
1318         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
1319         
1320         return OPERATOR_FINISHED;
1321
1322 }
1323
1324 void FILE_OT_delete(struct wmOperatorType *ot)
1325 {
1326         /* identifiers */
1327         ot->name= "Delete File";
1328         ot->description= "Delete selected file";
1329         ot->idname= "FILE_OT_delete";
1330         
1331         /* api callbacks */
1332         ot->invoke= WM_operator_confirm;
1333         ot->exec= file_delete_exec;
1334         ot->poll= file_delete_poll; /* <- important, handler is on window level */
1335 }
1336
1337
1338 void ED_operatormacros_file(void)
1339 {
1340         wmOperatorType *ot;
1341         wmOperatorTypeMacro *otmacro;
1342         
1343         ot= WM_operatortype_append_macro("FILE_OT_select_execute", "Select and Execute", OPTYPE_UNDO|OPTYPE_REGISTER);
1344         WM_operatortype_macro_define(ot, "FILE_OT_select");
1345         otmacro= WM_operatortype_macro_define(ot, "FILE_OT_execute");
1346         RNA_boolean_set(otmacro->ptr, "need_active", 1);
1347
1348 }