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