Blender V2.61 - r43446

file_ops.c

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