Blender  V2.59
file_ops.c
Go to the documentation of this file.
00001 /*
00002  * $Id: file_ops.c 39046 2011-08-05 06:06:15Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. 
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2008 Blender Foundation.
00021  * All rights reserved.
00022  *
00023  * 
00024  * Contributor(s): Andrea Weikert (c) 2008 Blender Foundation
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include "BKE_context.h"
00035 #include "BKE_screen.h"
00036 #include "BKE_global.h"
00037 #include "BKE_report.h"
00038 #include "BKE_main.h"
00039 
00040 #include "BLI_blenlib.h"
00041 #include "BLI_utildefines.h"
00042 #include "BLI_storage_types.h"
00043 #ifdef WIN32
00044 #include "BLI_winstuff.h"
00045 #endif
00046 
00047 #include "ED_screen.h"
00048 #include "ED_fileselect.h"
00049 
00050 #include "MEM_guardedalloc.h"
00051 
00052 #include "RNA_access.h"
00053 #include "RNA_define.h"
00054 
00055 #include "UI_view2d.h"
00056 
00057 #include "WM_api.h"
00058 #include "WM_types.h"
00059 
00060 #include "file_intern.h"
00061 #include "filelist.h"
00062 #include "fsmenu.h"
00063 
00064 #include <stdlib.h>
00065 #include <string.h>
00066 #include <stdio.h>
00067 #include <ctype.h>
00068 
00069 /* for events */
00070 #define NOTACTIVEFILE                   0
00071 #define ACTIVATE                        1
00072 #define INACTIVATE                      2
00073 
00074 /* ---------- FILE SELECTION ------------ */
00075 static FileSelection find_file_mouse_rect(SpaceFile *sfile, struct ARegion* ar, const rcti* rect)
00076 {
00077         FileSelection sel;
00078         float fxmin,fymin,fxmax, fymax;
00079         
00080         View2D* v2d = &ar->v2d;
00081         rcti rect_view;
00082 
00083         UI_view2d_region_to_view(v2d, rect->xmin, rect->ymin, &fxmin, &fymin);
00084         UI_view2d_region_to_view(v2d, rect->xmax, rect->ymax, &fxmax, &fymax);
00085 
00086         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));
00087 
00088         sel  = ED_fileselect_layout_offset_rect(sfile->layout, &rect_view);
00089         
00090         return sel;
00091 }
00092 
00093 static void file_deselect_all(SpaceFile* sfile, unsigned int flag)
00094 {
00095         FileSelection sel;
00096         sel.first = 0;
00097         sel.last = filelist_numfiles(sfile->files)-1;
00098         
00099         filelist_select(sfile->files, &sel, FILE_SEL_REMOVE, flag, CHECK_ALL);
00100 }
00101 
00102 typedef enum FileSelect { 
00103         FILE_SELECT_NOTHING = 0,
00104         FILE_SELECT_DIR = 1, 
00105         FILE_SELECT_FILE = 2 
00106 } FileSelect;
00107 
00108 static void clamp_to_filelist(int numfiles, FileSelection* sel)
00109 {
00110         /* border select before the first file */
00111         if ( (sel->first < 0) && (sel->last >=0 ) ) {
00112                 sel->first = 0;
00113         }
00114         /* don't select if everything is outside filelist */
00115         if ( (sel->first >= numfiles) && ((sel->last < 0) || (sel->last >= numfiles)) ) {
00116                 sel->first = -1;
00117                 sel->last = -1;
00118         }
00119         
00120         /* fix if last file invalid */
00121         if ( (sel->first > 0) && (sel->last < 0) )
00122                 sel->last = numfiles-1;
00123 
00124         /* clamp */
00125         if ( (sel->first >= numfiles) ) {
00126                 sel->first = numfiles-1;
00127         }
00128         if ( (sel->last >= numfiles) ) {
00129                 sel->last = numfiles-1;
00130         }
00131 }
00132 
00133 static FileSelection file_selection_get(bContext* C, const rcti* rect, short fill)
00134 {
00135         ARegion *ar= CTX_wm_region(C);
00136         SpaceFile *sfile= CTX_wm_space_file(C);
00137         int numfiles = filelist_numfiles(sfile->files);
00138         FileSelection sel;
00139 
00140         sel = find_file_mouse_rect(sfile, ar, rect);
00141         if ( !((sel.first == -1) && (sel.last == -1)) ) {
00142                 clamp_to_filelist(numfiles, &sel);
00143         }
00144 
00145 
00146         /* if desired, fill the selection up from the last selected file to the current one */
00147         if (fill && (sel.last >= 0) && (sel.last < numfiles) ) {
00148                 int f= sel.last;
00149                 while (f >= 0) {
00150                         if ( filelist_is_selected(sfile->files, f, CHECK_ALL) )
00151                                 break;
00152                         f--;
00153                 }
00154                 if (f >= 0) {
00155                         sel.first = f+1;
00156                 }
00157         }
00158         return sel;
00159 }
00160 
00161 static FileSelect file_select_do(bContext* C, int selected_idx)
00162 {
00163         FileSelect retval = FILE_SELECT_NOTHING;
00164         SpaceFile *sfile= CTX_wm_space_file(C);
00165         FileSelectParams *params = ED_fileselect_get_params(sfile);
00166         int numfiles = filelist_numfiles(sfile->files);
00167 
00168         /* make the selected file active */
00169         if ( (selected_idx >= 0) && (selected_idx < numfiles)) {
00170                 struct direntry* file = filelist_file(sfile->files, selected_idx);
00171                 params->active_file = selected_idx;
00172 
00173                 if(file && S_ISDIR(file->type)) {
00174                         /* the path is too long and we are not going up! */
00175                         if (strcmp(file->relname, "..") && strlen(params->dir) + strlen(file->relname) >= FILE_MAX ) 
00176                         {
00177                                 // XXX error("Path too long, cannot enter this directory");
00178                         } else {
00179                                 if (strcmp(file->relname, "..")==0) {    
00180                                         /* avoids /../../ */     
00181                                         BLI_parent_dir(params->dir);     
00182                                 } else {
00183                                         BLI_cleanup_dir(G.main->name, params->dir);
00184                                         strcat(params->dir, file->relname);
00185                                         BLI_add_slash(params->dir);
00186                                 }
00187 
00188                                 file_change_dir(C, 0);
00189                                 retval = FILE_SELECT_DIR;
00190                         }
00191                 }
00192                 else if (file)
00193                 {
00194                         if (file->relname) {
00195                                 BLI_strncpy(params->file, file->relname, FILE_MAXFILE);
00196                         }
00197                         retval = FILE_SELECT_FILE;
00198                 }
00199         }
00200         return retval;
00201 }
00202 
00203 
00204 static FileSelect file_select(bContext* C, const rcti* rect, FileSelType select, short fill)
00205 {
00206         SpaceFile *sfile= CTX_wm_space_file(C);
00207         FileSelect retval = FILE_SELECT_NOTHING;
00208         FileSelection sel= file_selection_get(C, rect, fill); /* get the selection */
00209         const FileCheckType check_type= (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_ALL;
00210         
00211         /* flag the files as selected in the filelist */
00212         filelist_select(sfile->files, &sel, select, SELECTED_FILE, check_type);
00213         
00214         /* Don't act on multiple selected files */
00215         if (sel.first != sel.last) select = 0;
00216 
00217         /* Do we have a valid selection and are we actually selecting */
00218         if ( (sel.last >= 0) && ((select == FILE_SEL_ADD) || (select == FILE_SEL_TOGGLE)) )
00219         {
00220                 /* Check last selection, if selected, act on the file or dir */
00221                 if (filelist_is_selected(sfile->files, sel.last, check_type)) {
00222                         retval = file_select_do(C, sel.last);
00223                 }
00224         }
00225 
00226         /* update operator for name change event */
00227         file_draw_check_cb(C, NULL, NULL);
00228         
00229         return retval;
00230 }
00231 
00232 static int file_border_select_modal(bContext *C, wmOperator *op, wmEvent *event)
00233 {
00234         ARegion *ar= CTX_wm_region(C);
00235         SpaceFile *sfile= CTX_wm_space_file(C);
00236         FileSelectParams *params = ED_fileselect_get_params(sfile);
00237         FileSelection sel;
00238         rcti rect;
00239 
00240         int result;
00241 
00242         result= WM_border_select_modal(C, op, event);
00243 
00244         if(result==OPERATOR_RUNNING_MODAL)      {
00245 
00246                 rect.xmin= RNA_int_get(op->ptr, "xmin");
00247                 rect.ymin= RNA_int_get(op->ptr, "ymin");
00248                 rect.xmax= RNA_int_get(op->ptr, "xmax");
00249                 rect.ymax= RNA_int_get(op->ptr, "ymax");
00250 
00251                 BLI_isect_rcti(&(ar->v2d.mask), &rect, &rect);
00252 
00253                 sel = file_selection_get(C, &rect, 0);
00254                 if ( (sel.first != params->sel_first) || (sel.last != params->sel_last) ) {
00255                         file_deselect_all(sfile, HILITED_FILE);
00256                         filelist_select(sfile->files, &sel, FILE_SEL_ADD, HILITED_FILE, CHECK_ALL);
00257                         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL);
00258                 }
00259                 params->sel_first = sel.first; params->sel_last = sel.last;
00260 
00261         }else {
00262                 params->active_file = -1;
00263                 params->sel_first = params->sel_last = -1;
00264                 file_deselect_all(sfile, HILITED_FILE);
00265                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL);
00266         }
00267 
00268         return result;
00269 }
00270 
00271 static int file_border_select_exec(bContext *C, wmOperator *op)
00272 {
00273         ARegion *ar= CTX_wm_region(C);
00274         rcti rect;
00275         FileSelect ret;
00276 
00277         short select= (RNA_int_get(op->ptr, "gesture_mode")==GESTURE_MODAL_SELECT);
00278         rect.xmin= RNA_int_get(op->ptr, "xmin");
00279         rect.ymin= RNA_int_get(op->ptr, "ymin");
00280         rect.xmax= RNA_int_get(op->ptr, "xmax");
00281         rect.ymax= RNA_int_get(op->ptr, "ymax");
00282 
00283         BLI_isect_rcti(&(ar->v2d.mask), &rect, &rect);
00284 
00285         ret = file_select(C, &rect, select ? FILE_SEL_ADD : FILE_SEL_REMOVE, 0);
00286         if (FILE_SELECT_DIR == ret) {
00287                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
00288         } else if (FILE_SELECT_FILE == ret) {
00289                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL);
00290         }
00291         return OPERATOR_FINISHED;
00292 }
00293 
00294 void FILE_OT_select_border(wmOperatorType *ot)
00295 {
00296         /* identifiers */
00297         ot->name= "Activate/Select File";
00298         ot->description= "Activate/select the file(s) contained in the border";
00299         ot->idname= "FILE_OT_select_border";
00300         
00301         /* api callbacks */
00302         ot->invoke= WM_border_select_invoke;
00303         ot->exec= file_border_select_exec;
00304         ot->modal= file_border_select_modal;
00305         ot->poll= ED_operator_file_active;
00306         ot->cancel= WM_border_select_cancel;
00307 
00308         /* rna */
00309         WM_operator_properties_gesture_border(ot, 0);
00310 }
00311 
00312 static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
00313 {
00314         ARegion *ar= CTX_wm_region(C);
00315         SpaceFile *sfile= CTX_wm_space_file(C);
00316         FileSelect ret;
00317         rcti rect;
00318         int extend = RNA_boolean_get(op->ptr, "extend");
00319         int fill = RNA_boolean_get(op->ptr, "fill");
00320 
00321         if(ar->regiontype != RGN_TYPE_WINDOW)
00322                 return OPERATOR_CANCELLED;
00323 
00324         rect.xmin = rect.xmax = event->mval[0];
00325         rect.ymin = rect.ymax = event->mval[1];
00326 
00327         if(!BLI_in_rcti(&ar->v2d.mask, rect.xmin, rect.ymin))
00328                 return OPERATOR_CANCELLED;
00329 
00330         /* single select, deselect all selected first */
00331         if (!extend) file_deselect_all(sfile, SELECTED_FILE);
00332 
00333         ret = file_select(C, &rect, extend ? FILE_SEL_TOGGLE : FILE_SEL_ADD, fill);
00334         if (FILE_SELECT_DIR == ret)
00335                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
00336         else if (FILE_SELECT_FILE == ret)
00337                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL);
00338 
00339         WM_event_add_mousemove(C); /* for directory changes */
00340         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL);
00341 
00342         return OPERATOR_FINISHED;
00343 }
00344 
00345 void FILE_OT_select(wmOperatorType *ot)
00346 {
00347         /* identifiers */
00348         ot->name= "Activate/Select File";
00349         ot->description= "Activate/select file";
00350         ot->idname= "FILE_OT_select";
00351         
00352         /* api callbacks */
00353         ot->invoke= file_select_invoke;
00354         ot->poll= ED_operator_file_active;
00355 
00356         /* rna */
00357         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first.");
00358         RNA_def_boolean(ot->srna, "fill", 0, "Fill", "Select everything beginning with the last selection.");
00359 }
00360 
00361 static int file_select_all_exec(bContext *C, wmOperator *UNUSED(op))
00362 {
00363         ScrArea *sa= CTX_wm_area(C);
00364         SpaceFile *sfile= CTX_wm_space_file(C);
00365         FileSelection sel;
00366         int numfiles = filelist_numfiles(sfile->files);
00367         int i;
00368         int is_selected = 0;
00369 
00370         sel.first = 0; 
00371         sel.last = numfiles-1;
00372 
00373         /* Is any file selected ? */
00374         for ( i=0; i < numfiles; ++i) {
00375                 if (filelist_is_selected(sfile->files, i, CHECK_ALL)) {
00376                         is_selected = 1;
00377                         break;
00378                 }
00379         }
00380         /* select all only if previously no file was selected */
00381         if (is_selected) {
00382                 filelist_select(sfile->files, &sel, FILE_SEL_REMOVE, SELECTED_FILE, CHECK_ALL);
00383         }
00384         else {
00385                 const FileCheckType check_type= (sfile->params->flag & FILE_DIRSEL_ONLY) ? CHECK_DIRS : CHECK_FILES;
00386                 filelist_select(sfile->files, &sel, FILE_SEL_ADD, SELECTED_FILE, check_type);
00387         }
00388         ED_area_tag_redraw(sa);
00389         return OPERATOR_FINISHED;
00390 }
00391 
00392 void FILE_OT_select_all_toggle(wmOperatorType *ot)
00393 {
00394         /* identifiers */
00395         ot->name= "Select/Deselect All Files";
00396         ot->description= "Select/deselect all files";
00397         ot->idname= "FILE_OT_select_all_toggle";
00398         
00399         /* api callbacks */
00400         ot->exec= file_select_all_exec;
00401         ot->poll= ED_operator_file_active;
00402 
00403         /* rna */
00404 
00405         
00406 }
00407 
00408 /* ---------- BOOKMARKS ----------- */
00409 
00410 static int bookmark_select_exec(bContext *C, wmOperator *op)
00411 {
00412         SpaceFile *sfile= CTX_wm_space_file(C);
00413 
00414         if(RNA_struct_find_property(op->ptr, "dir")) {
00415                 char entry[256];
00416                 FileSelectParams* params = sfile->params;
00417 
00418                 RNA_string_get(op->ptr, "dir", entry);
00419                 BLI_strncpy(params->dir, entry, sizeof(params->dir));
00420                 BLI_cleanup_dir(G.main->name, params->dir);
00421                 file_change_dir(C, 1);
00422 
00423                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
00424         }
00425         
00426         return OPERATOR_FINISHED;
00427 }
00428 
00429 void FILE_OT_select_bookmark(wmOperatorType *ot)
00430 {
00431         /* identifiers */
00432         ot->name= "Select Directory";
00433         ot->description= "Select a bookmarked directory";
00434         ot->idname= "FILE_OT_select_bookmark";
00435         
00436         /* api callbacks */
00437         ot->exec= bookmark_select_exec;
00438         ot->poll= ED_operator_file_active;
00439 
00440         RNA_def_string(ot->srna, "dir", "", 256, "Dir", "");
00441 }
00442 
00443 static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op))
00444 {
00445         ScrArea *sa= CTX_wm_area(C);
00446         SpaceFile *sfile= CTX_wm_space_file(C);
00447         struct FSMenu* fsmenu = fsmenu_get();
00448         struct FileSelectParams* params= ED_fileselect_get_params(sfile);
00449 
00450         if (params->dir[0] != '\0') {
00451                 char name[FILE_MAX];
00452         
00453                 fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, 0, 1);
00454                 BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
00455                 fsmenu_write_file(fsmenu, name);
00456         }
00457 
00458         ED_area_tag_redraw(sa);
00459         return OPERATOR_FINISHED;
00460 }
00461 
00462 void FILE_OT_bookmark_add(wmOperatorType *ot)
00463 {
00464         /* identifiers */
00465         ot->name= "Add Bookmark";
00466         ot->description= "Add a bookmark for the selected/active directory";
00467         ot->idname= "FILE_OT_bookmark_add";
00468         
00469         /* api callbacks */
00470         ot->exec= bookmark_add_exec;
00471         ot->poll= ED_operator_file_active;
00472 }
00473 
00474 static int bookmark_delete_exec(bContext *C, wmOperator *op)
00475 {
00476         ScrArea *sa= CTX_wm_area(C);
00477         struct FSMenu* fsmenu = fsmenu_get();
00478         int nentries = fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS);
00479         
00480         if(RNA_struct_find_property(op->ptr, "index")) {
00481                 int index = RNA_int_get(op->ptr, "index");
00482                 if ( (index >-1) && (index < nentries)) {
00483                         char name[FILE_MAX];
00484                         
00485                         fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index);
00486                         BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
00487                         fsmenu_write_file(fsmenu, name);
00488                         ED_area_tag_redraw(sa);
00489                 }
00490         }
00491 
00492         return OPERATOR_FINISHED;
00493 }
00494 
00495 void FILE_OT_delete_bookmark(wmOperatorType *ot)
00496 {
00497         /* identifiers */
00498         ot->name= "Delete Bookmark";
00499         ot->description= "Delete selected bookmark";
00500         ot->idname= "FILE_OT_delete_bookmark";
00501         
00502         /* api callbacks */
00503         ot->exec= bookmark_delete_exec;
00504         ot->poll= ED_operator_file_active;
00505 
00506         RNA_def_int(ot->srna, "index", -1, -1, 20000, "Index", "", -1, 20000);
00507 }
00508 
00509 int file_hilight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
00510 {
00511         View2D* v2d = &ar->v2d;
00512         FileSelectParams* params;
00513         int numfiles, origfile; 
00514 
00515         if(sfile==NULL || sfile->files==NULL) return 0;
00516 
00517         numfiles = filelist_numfiles(sfile->files);
00518         params = ED_fileselect_get_params(sfile);
00519 
00520         origfile= params->active_file;
00521 
00522         mx -= ar->winrct.xmin;
00523         my -= ar->winrct.ymin;
00524 
00525         if(BLI_in_rcti(&ar->v2d.mask, mx, my)) {
00526                 float fx, fy;
00527                 int active_file;
00528 
00529                 UI_view2d_region_to_view(v2d, mx, my, &fx, &fy);
00530 
00531                 active_file = ED_fileselect_layout_offset(sfile->layout, (int)(v2d->tot.xmin + fx), (int)(v2d->tot.ymax - fy));
00532 
00533                 if((active_file >= 0) && (active_file < numfiles))
00534                         params->active_file=active_file;
00535                 else
00536                         params->active_file= -1;
00537         }
00538         else
00539                 params->active_file= -1;
00540 
00541         return (params->active_file != origfile);
00542 }
00543 
00544 static int file_highlight_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
00545 {
00546         ARegion *ar= CTX_wm_region(C);
00547         SpaceFile *sfile= CTX_wm_space_file(C);
00548 
00549         if(!file_hilight_set(sfile, ar, event->x, event->y))
00550                 return OPERATOR_CANCELLED;
00551 
00552         ED_area_tag_redraw(CTX_wm_area(C));
00553         
00554         return OPERATOR_FINISHED;
00555 }
00556 
00557 void FILE_OT_highlight(struct wmOperatorType *ot)
00558 {
00559         /* identifiers */
00560         ot->name= "Highlight File";
00561         ot->description= "Highlight selected file(s)";
00562         ot->idname= "FILE_OT_highlight";
00563         
00564         /* api callbacks */
00565         ot->invoke= file_highlight_invoke;
00566         ot->poll= ED_operator_file_active;
00567 }
00568 
00569 int file_cancel_exec(bContext *C, wmOperator *UNUSED(unused))
00570 {
00571         SpaceFile *sfile= CTX_wm_space_file(C);
00572         wmOperator *op = sfile->op;
00573         
00574         sfile->op = NULL;
00575 
00576         WM_event_fileselect_event(C, op, EVT_FILESELECT_CANCEL);
00577         
00578         return OPERATOR_FINISHED;
00579 }
00580 
00581 static int file_operator_poll(bContext *C)
00582 {
00583         int poll = ED_operator_file_active(C);
00584         SpaceFile *sfile= CTX_wm_space_file(C);
00585 
00586         if (!sfile || !sfile->op) poll= 0;
00587 
00588         return poll;
00589 }
00590 
00591 void FILE_OT_cancel(struct wmOperatorType *ot)
00592 {
00593         /* identifiers */
00594         ot->name= "Cancel File Load";
00595         ot->description= "Cancel loading of selected file";
00596         ot->idname= "FILE_OT_cancel";
00597         
00598         /* api callbacks */
00599         ot->exec= file_cancel_exec;
00600         ot->poll= file_operator_poll;
00601 }
00602 
00603 
00604 void file_sfile_to_operator(wmOperator *op, SpaceFile *sfile, char *filepath)
00605 {
00606         BLI_join_dirfile(filepath, FILE_MAX, sfile->params->dir, sfile->params->file); /* XXX, not real length */
00607         if(RNA_struct_find_property(op->ptr, "relative_path")) {
00608                 if(RNA_boolean_get(op->ptr, "relative_path")) {
00609                         BLI_path_rel(filepath, G.main->name);
00610                 }
00611         }
00612 
00613         if(RNA_struct_find_property(op->ptr, "filename")) {
00614                 RNA_string_set(op->ptr, "filename", sfile->params->file);
00615         }
00616         if(RNA_struct_find_property(op->ptr, "directory")) {
00617                 RNA_string_set(op->ptr, "directory", sfile->params->dir);
00618         }
00619         if(RNA_struct_find_property(op->ptr, "filepath")) {
00620                 RNA_string_set(op->ptr, "filepath", filepath);
00621         }
00622         
00623         /* some ops have multiple files to select */
00624         {
00625                 PointerRNA itemptr;
00626                 int i, numfiles = filelist_numfiles(sfile->files);
00627 
00628                 if(RNA_struct_find_property(op->ptr, "files")) {
00629                         for (i=0; i<numfiles; i++) {
00630                                 if (filelist_is_selected(sfile->files, i, CHECK_FILES)) {
00631                                         struct direntry *file= filelist_file(sfile->files, i);
00632                                         RNA_collection_add(op->ptr, "files", &itemptr);
00633                                         RNA_string_set(&itemptr, "name", file->relname);
00634                                 }
00635                         }
00636                 }
00637                 
00638                 if(RNA_struct_find_property(op->ptr, "dirs")) {
00639                         for (i=0; i<numfiles; i++) {
00640                                 if (filelist_is_selected(sfile->files, i, CHECK_DIRS)) {
00641                                         struct direntry *file= filelist_file(sfile->files, i);
00642                                         RNA_collection_add(op->ptr, "dirs", &itemptr);
00643                                         RNA_string_set(&itemptr, "name", file->relname);
00644                                 }
00645                         }
00646                 }
00647 
00648 
00649         }
00650 }
00651 
00652 void file_operator_to_sfile(SpaceFile *sfile, wmOperator *op)
00653 {
00654         int change= FALSE;
00655         if(RNA_struct_find_property(op->ptr, "filename")) {
00656                 RNA_string_get(op->ptr, "filename", sfile->params->file);
00657                 change= TRUE;
00658         }
00659         if(RNA_struct_find_property(op->ptr, "directory")) {
00660                 RNA_string_get(op->ptr, "directory", sfile->params->dir);
00661                 change= TRUE;
00662         }
00663         
00664         /* If neither of the above are set, split the filepath back */
00665         if(RNA_struct_find_property(op->ptr, "filepath")) {
00666                 if(change==FALSE) {
00667                         char filepath[FILE_MAX];
00668                         RNA_string_get(op->ptr, "filepath", filepath);
00669                         BLI_split_dirfile(filepath, sfile->params->dir, sfile->params->file);
00670                 }
00671         }
00672         
00673         /* XXX, files and dirs updates missing, not really so important though */
00674 }
00675 
00676 void file_draw_check_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
00677 {
00678         SpaceFile *sfile= CTX_wm_space_file(C);
00679         wmOperator *op= sfile->op;
00680         if(op) { /* fail on reload */
00681                 if(op->type->check) {
00682                         char filepath[FILE_MAX];
00683                         file_sfile_to_operator(op, sfile, filepath);
00684                         
00685                         /* redraw */
00686                         if(op->type->check(C, op)) {
00687                                 file_operator_to_sfile(sfile, op);
00688         
00689                                 /* redraw, else the changed settings wont get updated */
00690                                 ED_area_tag_redraw(CTX_wm_area(C));
00691                         }
00692                 }
00693         }
00694 }
00695 
00696 int file_draw_check_exists(SpaceFile *sfile)
00697 {
00698         if(sfile->op) { /* fails on reload */
00699                 if(RNA_struct_find_property(sfile->op->ptr, "check_existing")) {
00700                         if(RNA_boolean_get(sfile->op->ptr, "check_existing")) {
00701                                 char filepath[FILE_MAX];
00702                                 BLI_join_dirfile(filepath, sizeof(filepath), sfile->params->dir, sfile->params->file);
00703                                 if(BLI_exists(filepath) && !BLI_is_dir(filepath)) {
00704                                         return TRUE;
00705                                 }
00706                         }
00707                 }
00708         }
00709 
00710         return FALSE;
00711 }
00712 
00713 /* sends events now, so things get handled on windowqueue level */
00714 int file_exec(bContext *C, wmOperator *exec_op)
00715 {
00716         SpaceFile *sfile= CTX_wm_space_file(C);
00717         char filepath[FILE_MAX];
00718         
00719         if(sfile->op) {
00720                 wmOperator *op= sfile->op;
00721         
00722                 /* when used as a macro, for doubleclick, 
00723                  to prevent closing when doubleclicking on .. item */
00724                 if (RNA_boolean_get(exec_op->ptr, "need_active")) {
00725                         int i, active=0;
00726                         
00727                         for (i=0; i<filelist_numfiles(sfile->files); i++) {
00728                                 if(filelist_is_selected(sfile->files, i, CHECK_ALL)) {
00729                                         active=1;
00730                                         break;
00731                                 }
00732                         }
00733                         if (active == 0)
00734                                 return OPERATOR_CANCELLED;
00735                 }
00736                 
00737                 sfile->op = NULL;
00738 
00739                 file_sfile_to_operator(op, sfile, filepath);
00740 
00741                 fsmenu_insert_entry(fsmenu_get(), FS_CATEGORY_RECENT, sfile->params->dir,0, 1);
00742                 BLI_make_file_string(G.main->name, filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
00743                 fsmenu_write_file(fsmenu_get(), filepath);
00744                 WM_event_fileselect_event(C, op, EVT_FILESELECT_EXEC);
00745 
00746         }
00747                                 
00748         return OPERATOR_FINISHED;
00749 }
00750 
00751 void FILE_OT_execute(struct wmOperatorType *ot)
00752 {
00753         /* identifiers */
00754         ot->name= "Execute File Window";
00755         ot->description= "Execute selected file";
00756         ot->idname= "FILE_OT_execute";
00757         
00758         /* api callbacks */
00759         ot->exec= file_exec;
00760         ot->poll= file_operator_poll; 
00761         
00762         RNA_def_boolean(ot->srna, "need_active", 0, "Need Active", "Only execute if there's an active selected file in the file list.");
00763 }
00764 
00765 
00766 int file_parent_exec(bContext *C, wmOperator *UNUSED(unused))
00767 {
00768         SpaceFile *sfile= CTX_wm_space_file(C);
00769         
00770         if(sfile->params) {
00771                 if (BLI_has_parent(sfile->params->dir)) {
00772                         BLI_parent_dir(sfile->params->dir);
00773                         BLI_cleanup_dir(G.main->name, sfile->params->dir);
00774                         file_change_dir(C, 0);
00775                         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
00776                 }
00777         }               
00778         
00779         return OPERATOR_FINISHED;
00780 
00781 }
00782 
00783 
00784 void FILE_OT_parent(struct wmOperatorType *ot)
00785 {
00786         /* identifiers */
00787         ot->name= "Parent File";
00788         ot->description= "Move to parent directory";
00789         ot->idname= "FILE_OT_parent";
00790         
00791         /* api callbacks */
00792         ot->exec= file_parent_exec;
00793         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
00794 }
00795 
00796 
00797 static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused))
00798 {
00799         SpaceFile *sfile= CTX_wm_space_file(C);
00800 
00801         ED_fileselect_clear(C, sfile);
00802 
00803         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
00804 
00805         return OPERATOR_FINISHED;
00806 
00807 }
00808 
00809 void FILE_OT_previous(struct wmOperatorType *ot)
00810 {
00811         /* identifiers */
00812         ot->name= "Previous Folder";
00813         ot->description= "Move to previous folder";
00814         ot->idname= "FILE_OT_previous";
00815         
00816         /* api callbacks */
00817         ot->exec= file_previous_exec;
00818         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
00819 }
00820 
00821 int file_previous_exec(bContext *C, wmOperator *UNUSED(unused))
00822 {
00823         SpaceFile *sfile= CTX_wm_space_file(C);
00824 
00825         if(sfile->params) {
00826                 if (!sfile->folders_next)
00827                         sfile->folders_next = folderlist_new();
00828 
00829                 folderlist_pushdir(sfile->folders_next, sfile->params->dir);
00830                 folderlist_popdir(sfile->folders_prev, sfile->params->dir);
00831                 folderlist_pushdir(sfile->folders_next, sfile->params->dir);
00832 
00833                 file_change_dir(C, 1);
00834         }
00835         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
00836 
00837         return OPERATOR_FINISHED;
00838 }
00839 
00840 void FILE_OT_next(struct wmOperatorType *ot)
00841 {
00842         /* identifiers */
00843         ot->name= "Next Folder";
00844         ot->description= "Move to next folder";
00845         ot->idname= "FILE_OT_next";
00846         
00847         /* api callbacks */
00848         ot->exec= file_next_exec;
00849         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
00850 }
00851 
00852 int file_next_exec(bContext *C, wmOperator *UNUSED(unused))
00853 {
00854         SpaceFile *sfile= CTX_wm_space_file(C);
00855         if(sfile->params) {
00856                 if (!sfile->folders_next)
00857                         sfile->folders_next = folderlist_new();
00858 
00859                 folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
00860                 folderlist_popdir(sfile->folders_next, sfile->params->dir);
00861 
00862                 // update folders_prev so we can check for it in folderlist_clear_next()
00863                 folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
00864 
00865                 file_change_dir(C, 1);
00866         }               
00867         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
00868 
00869         return OPERATOR_FINISHED;
00870 }
00871 
00872 
00873 /* only meant for timer usage */
00874 static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
00875 {
00876         ScrArea *sa = CTX_wm_area(C);
00877         SpaceFile *sfile= CTX_wm_space_file(C);
00878         ARegion *ar, *oldar= CTX_wm_region(C);
00879         int offset;
00880         int numfiles, numfiles_layout;
00881         int edit_idx = 0;
00882         int i;
00883 
00884         /* escape if not our timer */
00885         if(sfile->smoothscroll_timer==NULL || sfile->smoothscroll_timer!=event->customdata)
00886                 return OPERATOR_PASS_THROUGH;
00887         
00888         numfiles = filelist_numfiles(sfile->files);
00889 
00890         /* check if we are editing a name */
00891         for (i=0; i < numfiles; ++i)
00892         {
00893                 if (filelist_is_selected(sfile->files, i, CHECK_ALL) ) {
00894                         edit_idx=i;
00895                         break;
00896                 }
00897         }
00898 
00899         /* if we are not editing, we are done */
00900         if (0==edit_idx) {
00901                 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
00902                 sfile->smoothscroll_timer=NULL;
00903                 return OPERATOR_PASS_THROUGH;
00904         }
00905 
00906         /* we need the correct area for scrolling */
00907         ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
00908         if (!ar || ar->regiontype != RGN_TYPE_WINDOW) {
00909                 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
00910                 sfile->smoothscroll_timer=NULL;
00911                 return OPERATOR_PASS_THROUGH;
00912         }
00913 
00914         offset = ED_fileselect_layout_offset(sfile->layout, (int)ar->v2d.cur.xmin, (int)-ar->v2d.cur.ymax);
00915         if (offset<0) offset=0;
00916 
00917         /* scroll offset is the first file in the row/column we are editing in */
00918         if (sfile->scroll_offset == 0) {
00919                 if (sfile->layout->flag & FILE_LAYOUT_HOR) {
00920                         sfile->scroll_offset = (edit_idx/sfile->layout->rows)*sfile->layout->rows;
00921                         if (sfile->scroll_offset <= offset) sfile->scroll_offset -= sfile->layout->rows;
00922                 } else {
00923                         sfile->scroll_offset = (edit_idx/sfile->layout->columns)*sfile->layout->columns;
00924                         if (sfile->scroll_offset <= offset) sfile->scroll_offset -= sfile->layout->columns;
00925                 }
00926         }
00927         
00928         numfiles_layout = ED_fileselect_layout_numfiles(sfile->layout, ar);
00929         
00930         /* check if we have reached our final scroll position */
00931         if ( (sfile->scroll_offset >= offset) && (sfile->scroll_offset < offset + numfiles_layout) ) {
00932                 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), sfile->smoothscroll_timer);
00933                 sfile->smoothscroll_timer=NULL;
00934                 return OPERATOR_FINISHED;
00935         }
00936 
00937         /* temporarily set context to the main window region, 
00938          * so the scroll operators work */
00939         CTX_wm_region_set(C, ar);
00940         
00941         /* scroll one step in the desired direction */
00942         if (sfile->scroll_offset < offset) {
00943                 if (sfile->layout->flag & FILE_LAYOUT_HOR) {
00944                         WM_operator_name_call(C, "VIEW2D_OT_scroll_left", 0, NULL);
00945                 } else {
00946                         WM_operator_name_call(C, "VIEW2D_OT_scroll_up", 0, NULL);
00947                 }
00948                 
00949         } else {
00950                 if (sfile->layout->flag & FILE_LAYOUT_HOR) {
00951                         WM_operator_name_call(C, "VIEW2D_OT_scroll_right", 0, NULL);
00952                 } else {
00953                         WM_operator_name_call(C, "VIEW2D_OT_scroll_down", 0, NULL);
00954                 }
00955         }
00956         
00957         ED_region_tag_redraw(CTX_wm_region(C));
00958         
00959         /* and restore context */
00960         CTX_wm_region_set(C, oldar);
00961         
00962         return OPERATOR_FINISHED;
00963 }
00964 
00965 
00966 void FILE_OT_smoothscroll(wmOperatorType *ot)
00967 {
00968         
00969         /* identifiers */
00970         ot->name= "Smooth Scroll";
00971         ot->idname= "FILE_OT_smoothscroll";
00972         ot->description="Smooth scroll to make editable file visible.";
00973         
00974         /* api callbacks */
00975         ot->invoke= file_smoothscroll_invoke;
00976         
00977         ot->poll= ED_operator_file_active;
00978 }
00979 
00980 
00981 /* create a new, non-existing folder name, returns 1 if successful, 0 if name couldn't be created.
00982    The actual name is returned in 'name', 'folder' contains the complete path, including the new folder name.
00983 */
00984 static int new_folder_path(const char* parent, char *folder, char *name)
00985 {
00986         int i = 1;
00987         int len = 0;
00988 
00989         BLI_strncpy(name, "New Folder", FILE_MAXFILE);
00990         BLI_join_dirfile(folder, FILE_MAX, parent, name); /* XXX, not real length */
00991         /* check whether folder with the name already exists, in this case
00992            add number to the name. Check length of generated name to avoid
00993            crazy case of huge number of folders each named 'New Folder (x)' */
00994         while (BLI_exists(folder) && (len<FILE_MAXFILE)) {
00995                 len = BLI_snprintf(name, FILE_MAXFILE, "New Folder(%d)", i);
00996                 BLI_join_dirfile(folder, FILE_MAX, parent, name); /* XXX, not real length */
00997                 i++;
00998         }
00999 
01000         return (len<FILE_MAXFILE);
01001 }
01002 
01003 int file_directory_new_exec(bContext *C, wmOperator *op)
01004 {
01005         char name[FILE_MAXFILE];
01006         char path[FILE_MAX];
01007         int generate_name= 1;
01008 
01009         SpaceFile *sfile= CTX_wm_space_file(C);
01010         
01011         if(!sfile->params) {
01012                 BKE_report(op->reports,RPT_WARNING, "No parent directory given.");
01013                 return OPERATOR_CANCELLED;
01014         }
01015         
01016         path[0] = '\0';
01017 
01018         if(RNA_struct_find_property(op->ptr, "directory")) {
01019                 RNA_string_get(op->ptr, "directory", path);
01020                 if (path[0] != '\0') generate_name= 0;
01021         }
01022 
01023         if (generate_name) {
01024                 /* create a new, non-existing folder name */
01025                 if (!new_folder_path(sfile->params->dir, path, name)) {
01026                         BKE_report(op->reports,RPT_ERROR, "Couldn't create new folder name.");
01027                         return OPERATOR_CANCELLED;
01028                 }
01029         }
01030 
01031         /* create the file */
01032         BLI_recurdir_fileops(path);
01033 
01034         if (!BLI_exists(path)) {
01035                 BKE_report(op->reports,RPT_ERROR, "Couldn't create new folder.");
01036                 return OPERATOR_CANCELLED;
01037         } 
01038 
01039         /* now remember file to jump into editing */
01040         BLI_strncpy(sfile->params->renamefile, name, FILE_MAXFILE);
01041 
01042         /* set timer to smoothly view newly generated file */
01043         sfile->smoothscroll_timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER1, 1.0/1000.0);        /* max 30 frs/sec */
01044         sfile->scroll_offset=0;
01045 
01046         /* reload dir to make sure we're seeing what's in the directory */
01047         ED_fileselect_clear(C, sfile);
01048         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
01049 
01050         return OPERATOR_FINISHED;
01051 }
01052 
01053 
01054 void FILE_OT_directory_new(struct wmOperatorType *ot)
01055 {
01056         /* identifiers */
01057         ot->name= "Create New Directory";
01058         ot->description= "Create a new directory";
01059         ot->idname= "FILE_OT_directory_new";
01060         
01061         /* api callbacks */
01062         ot->invoke= WM_operator_confirm;
01063         ot->exec= file_directory_new_exec;
01064         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
01065 
01066         RNA_def_string_dir_path(ot->srna, "directory", "", FILE_MAX, "Directory", "Name of new directory");
01067 
01068 }
01069 
01070 
01071 static void file_expand_directory(bContext *C)
01072 {
01073         SpaceFile *sfile= CTX_wm_space_file(C);
01074         
01075         if(sfile->params) {
01076                 if ( sfile->params->dir[0] == '~' ) {
01077                         char tmpstr[sizeof(sfile->params->dir)-1];
01078                         BLI_strncpy(tmpstr, sfile->params->dir+1, sizeof(tmpstr));
01079                         BLI_join_dirfile(sfile->params->dir, sizeof(sfile->params->dir), BLI_getDefaultDocumentFolder(), tmpstr);
01080                 }
01081 
01082 #ifdef WIN32
01083                 if (sfile->params->dir[0] == '\0') {
01084                         get_default_root(sfile->params->dir);
01085                 }
01086                 /* change "C:" --> "C:\", [#28102] */
01087                 else if (   (isalpha(sfile->params->dir[0]) &&
01088                             (sfile->params->dir[1] == ':')) &&
01089                             (sfile->params->dir[2] == '\0')
01090 
01091                 ) {
01092                         sfile->params->dir[2]= '\\';
01093                         sfile->params->dir[3]= '\0';
01094                 }
01095 #endif
01096         }
01097 }
01098 
01099 static int file_directory_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
01100 {
01101         SpaceFile *sfile= CTX_wm_space_file(C);
01102 
01103         if(sfile->params) {
01104                 file_expand_directory(C);
01105                 
01106                 if (!BLI_exists(sfile->params->dir)) {
01107                         return WM_operator_confirm_message(C, op, "Create new directory?");
01108                 } 
01109 
01110                 return file_directory_exec(C, op);
01111         }
01112 
01113         return OPERATOR_CANCELLED;
01114 }
01115 
01116 
01117 
01118 int file_directory_exec(bContext *C, wmOperator *UNUSED(unused))
01119 {
01120         SpaceFile *sfile= CTX_wm_space_file(C);
01121         
01122         if(sfile->params) {
01123                 file_expand_directory(C);
01124 
01125                 if (!BLI_exists(sfile->params->dir)) {
01126                         BLI_recurdir_fileops(sfile->params->dir);
01127                 }
01128 
01129                 /* special case, user may have pasted a fulepath into the directory */
01130                 if(BLI_exists(sfile->params->dir) && BLI_is_dir(sfile->params->dir) == 0) {
01131                         char path[sizeof(sfile->params->dir)];
01132                         BLI_strncpy(path, sfile->params->dir, sizeof(path));
01133                         BLI_split_dirfile(path, sfile->params->dir, sfile->params->file);
01134                 }
01135 
01136                 BLI_cleanup_dir(G.main->name, sfile->params->dir);
01137                 BLI_add_slash(sfile->params->dir);
01138                 file_change_dir(C, 1);
01139 
01140                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
01141         }               
01142         
01143 
01144         return OPERATOR_FINISHED;
01145 }
01146 
01147 int file_filename_exec(bContext *C, wmOperator *UNUSED(unused))
01148 {
01149         SpaceFile *sfile= CTX_wm_space_file(C);
01150         
01151         if(sfile->params) {
01152                 if (file_select_match(sfile, sfile->params->file))
01153                 {
01154                         sfile->params->file[0] = '\0';
01155                         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_PARAMS, NULL);
01156                 }
01157         }               
01158 
01159         return OPERATOR_FINISHED;
01160 }
01161 
01162 void FILE_OT_directory(struct wmOperatorType *ot)
01163 {
01164         /* identifiers */
01165         ot->name= "Enter Directory Name";
01166         ot->description= "Enter a directory name";
01167         ot->idname= "FILE_OT_directory";
01168         
01169         /* api callbacks */
01170         ot->invoke= file_directory_invoke;
01171         ot->exec= file_directory_exec;
01172         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
01173 }
01174 
01175 void FILE_OT_refresh(struct wmOperatorType *ot)
01176 {
01177         /* identifiers */
01178         ot->name= "Refresh Filelist";
01179         ot->description= "Refresh the file list";
01180         ot->idname= "FILE_OT_refresh";
01181         
01182         /* api callbacks */
01183         ot->exec= file_refresh_exec;
01184         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
01185 }
01186 
01187 static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused))
01188 {
01189         SpaceFile *sfile= CTX_wm_space_file(C);
01190         
01191         if(sfile->params) {
01192                 sfile->params->flag ^= FILE_HIDE_DOT;
01193                 ED_fileselect_clear(C, sfile);
01194                 WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
01195         }
01196         
01197         return OPERATOR_FINISHED;
01198 }
01199 
01200 
01201 void FILE_OT_hidedot(struct wmOperatorType *ot)
01202 {
01203         /* identifiers */
01204         ot->name= "Toggle Hide Dot Files";
01205         ot->description= "Toggle hide hidden dot files";
01206         ot->idname= "FILE_OT_hidedot";
01207         
01208         /* api callbacks */
01209         ot->exec= file_hidedot_exec;
01210         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
01211 }
01212 
01213 struct ARegion *file_buttons_region(struct ScrArea *sa)
01214 {
01215         ARegion *ar, *arnew;
01216         
01217         for(ar= sa->regionbase.first; ar; ar= ar->next)
01218                 if(ar->regiontype==RGN_TYPE_CHANNELS)
01219                         return ar;
01220 
01221         /* add subdiv level; after header */
01222         for(ar= sa->regionbase.first; ar; ar= ar->next)
01223                 if(ar->regiontype==RGN_TYPE_HEADER)
01224                         break;
01225         
01226         /* is error! */
01227         if(ar==NULL) return NULL;
01228         
01229         arnew= MEM_callocN(sizeof(ARegion), "buttons for file panels");
01230         
01231         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
01232         arnew->regiontype= RGN_TYPE_CHANNELS;
01233         arnew->alignment= RGN_ALIGN_LEFT;
01234         
01235         arnew->flag = RGN_FLAG_HIDDEN;
01236         
01237         return arnew;
01238 }
01239 
01240 static int file_bookmark_toggle_exec(bContext *C, wmOperator *UNUSED(unused))
01241 {
01242         ScrArea *sa= CTX_wm_area(C);
01243         ARegion *ar= file_buttons_region(sa);
01244         
01245         if(ar)
01246                 ED_region_toggle_hidden(C, ar);
01247 
01248         return OPERATOR_FINISHED;
01249 }
01250 
01251 void FILE_OT_bookmark_toggle(struct wmOperatorType *ot)
01252 {
01253         /* identifiers */
01254         ot->name= "Toggle Bookmarks";
01255         ot->description= "Toggle bookmarks display";
01256         ot->idname= "FILE_OT_bookmark_toggle";
01257         
01258         /* api callbacks */
01259         ot->exec= file_bookmark_toggle_exec;
01260         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
01261 }
01262 
01263 
01264 static int file_filenum_exec(bContext *C, wmOperator *op)
01265 {
01266         SpaceFile *sfile= CTX_wm_space_file(C);
01267         ScrArea *sa= CTX_wm_area(C);
01268         
01269         int inc = RNA_int_get(op->ptr, "increment");
01270         if(sfile->params && (inc != 0)) {
01271                 BLI_newname(sfile->params->file, inc);
01272                 ED_area_tag_redraw(sa);
01273                 file_draw_check_cb(C, NULL, NULL);
01274                 // WM_event_add_notifier(C, NC_WINDOW, NULL);
01275         }
01276         
01277         return OPERATOR_FINISHED;
01278 
01279 }
01280 
01281 void FILE_OT_filenum(struct wmOperatorType *ot)
01282 {
01283         /* identifiers */
01284         ot->name= "Increment Number in Filename";
01285         ot->description= "Increment number in filename";
01286         ot->idname= "FILE_OT_filenum";
01287         
01288         /* api callbacks */
01289         ot->exec= file_filenum_exec;
01290         ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
01291 
01292         /* props */
01293         RNA_def_int(ot->srna, "increment", 1, -100, 100, "Increment", "", -100,100);
01294 }
01295 
01296 static int file_rename_exec(bContext *C, wmOperator *UNUSED(op))
01297 {
01298         ScrArea *sa= CTX_wm_area(C);
01299         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
01300         
01301         if(sfile->params) {
01302                 int idx = sfile->params->active_file;
01303                 int numfiles = filelist_numfiles(sfile->files);
01304                 if ( (0<=idx) && (idx<numfiles) ) {
01305                         struct direntry *file= filelist_file(sfile->files, idx);
01306                         filelist_select_file(sfile->files, idx, FILE_SEL_ADD, EDITING_FILE, CHECK_ALL);
01307                         BLI_strncpy(sfile->params->renameedit, file->relname, FILE_MAXFILE);
01308                         sfile->params->renamefile[0]= '\0';
01309                 }
01310                 ED_area_tag_redraw(sa);
01311         }
01312         
01313         return OPERATOR_FINISHED;
01314 
01315 }
01316 
01317 static int file_rename_poll(bContext *C)
01318 {
01319         int poll = ED_operator_file_active(C);
01320         SpaceFile *sfile= CTX_wm_space_file(C);
01321 
01322         if (sfile && sfile->params) {
01323                 if (sfile->params->active_file < 0) { 
01324                         poll= 0;
01325                 } else {
01326                         char dir[FILE_MAX], group[FILE_MAX];    
01327                         if (filelist_islibrary(sfile->files, dir, group)) poll= 0;
01328                 }
01329         }
01330         else
01331                 poll= 0;
01332         return poll;
01333 }
01334 
01335 void FILE_OT_rename(struct wmOperatorType *ot)
01336 {
01337         /* identifiers */
01338         ot->name= "Rename File or Directory";
01339         ot->description= "Rename file or file directory";
01340         ot->idname= "FILE_OT_rename";
01341         
01342         /* api callbacks */
01343         ot->exec= file_rename_exec;
01344         ot->poll= file_rename_poll; 
01345 
01346 }
01347 
01348 static int file_delete_poll(bContext *C)
01349 {
01350         int poll = ED_operator_file_active(C);
01351         SpaceFile *sfile= CTX_wm_space_file(C);
01352         struct direntry* file;
01353 
01354         if (sfile && sfile->params) {
01355                 if (sfile->params->active_file < 0) { 
01356                         poll= 0;
01357                 } else {
01358                         char dir[FILE_MAX], group[FILE_MAX];    
01359                         if (filelist_islibrary(sfile->files, dir, group)) poll= 0;
01360                         file = filelist_file(sfile->files, sfile->params->active_file);
01361                         if (file && S_ISDIR(file->type)) poll= 0;
01362                 }
01363         }
01364         else
01365                 poll= 0;
01366                 
01367         return poll;
01368 }
01369 
01370 int file_delete_exec(bContext *C, wmOperator *UNUSED(op))
01371 {
01372         char str[FILE_MAX];
01373         SpaceFile *sfile= CTX_wm_space_file(C);
01374         struct direntry* file;
01375         
01376         
01377         file = filelist_file(sfile->files, sfile->params->active_file);
01378         BLI_make_file_string(G.main->name, str, sfile->params->dir, file->relname);
01379         BLI_delete(str, 0, 0);  
01380         ED_fileselect_clear(C, sfile);
01381         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
01382         
01383         return OPERATOR_FINISHED;
01384 
01385 }
01386 
01387 void FILE_OT_delete(struct wmOperatorType *ot)
01388 {
01389         /* identifiers */
01390         ot->name= "Delete File";
01391         ot->description= "Delete selected file";
01392         ot->idname= "FILE_OT_delete";
01393         
01394         /* api callbacks */
01395         ot->invoke= WM_operator_confirm;
01396         ot->exec= file_delete_exec;
01397         ot->poll= file_delete_poll; /* <- important, handler is on window level */
01398 }
01399 
01400 
01401 void ED_operatormacros_file(void)
01402 {
01403 //      wmOperatorType *ot;
01404 //      wmOperatorTypeMacro *otmacro;
01405         
01406         /* future macros */
01407 }