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