rename RNA_property_is_set() --> RNA_struct_property_is_set() in preperation to add...
[blender.git] / source / blender / editors / space_file / filesel.c
index 471a1784f024dd4903df8e4415d03a76507aa62a..bf31775a349d8e0c864739a644fa8240b1fe2cc8 100644 (file)
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/editors/space_file/filesel.c
+ *  \ingroup spfile
+ */
+
+
 #include <string.h>
 #include <stdio.h>
 #include <math.h>
@@ -59,9 +62,8 @@
 
 #include "BLI_blenlib.h"
 #include "BLI_linklist.h"
-#include "BLI_path_util.h"
-#include "BLI_storage_types.h"
 #include "BLI_dynstr.h"
+#include "BLI_utildefines.h"
 
 #include "BKE_context.h"
 #include "BKE_global.h"
@@ -79,6 +81,7 @@
 #include "RNA_access.h"
 
 #include "UI_interface.h"
+#include "UI_interface_icons.h"
 
 #include "file_intern.h"
 #include "filelist.h"
@@ -106,7 +109,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
        if (!sfile->params) {
                sfile->params= MEM_callocN(sizeof(FileSelectParams), "fileselparams");
                /* set path to most recently opened .blend */
-               BLI_split_dirfile(G.main->name, sfile->params->dir, sfile->params->file);
+               BLI_split_dirfile(G.main->name, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file));
                sfile->params->filter_glob[0] = '\0';
        }
 
@@ -114,6 +117,12 @@ short ED_fileselect_set_params(SpaceFile *sfile)
 
        /* set the parameters from the operator, if it exists */
        if (op) {
+               const short is_files= (RNA_struct_find_property(op->ptr, "files") != NULL);
+               const short is_filepath= (RNA_struct_find_property(op->ptr, "filepath") != NULL);
+               const short is_filename= (RNA_struct_find_property(op->ptr, "filename") != NULL);
+               const short is_directory= (RNA_struct_find_property(op->ptr, "directory") != NULL);
+               const short is_relative_path= (RNA_struct_find_property(op->ptr, "relative_path") != NULL);
+
                BLI_strncpy(params->title, op->type->name, sizeof(params->title));
 
                if(RNA_struct_find_property(op->ptr, "filemode"))
@@ -121,7 +130,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
                else
                        params->type = FILE_SPECIAL;
 
-               if (RNA_struct_find_property(op->ptr, "filepath") && RNA_property_is_set(op->ptr, "filepath")) {
+               if (is_filepath && RNA_struct_property_is_set(op->ptr, "filepath")) {
                        char name[FILE_MAX];
                        RNA_string_get(op->ptr, "filepath", name);
                        if (params->type == FILE_LOADLIB) {
@@ -129,16 +138,16 @@ short ED_fileselect_set_params(SpaceFile *sfile)
                                sfile->params->file[0]= '\0';
                        }
                        else {
-                               BLI_split_dirfile(name, sfile->params->dir, sfile->params->file);
+                               BLI_split_dirfile(name, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file));
                        }
                }
                else {
-                       if (RNA_struct_find_property(op->ptr, "directory") && RNA_property_is_set(op->ptr, "directory")) {
+                       if (is_directory && RNA_struct_property_is_set(op->ptr, "directory")) {
                                RNA_string_get(op->ptr, "directory", params->dir);
                                sfile->params->file[0]= '\0';
                        }
 
-                       if (RNA_struct_find_property(op->ptr, "filename") && RNA_property_is_set(op->ptr, "filename")) {
+                       if (is_filename && RNA_struct_property_is_set(op->ptr, "filename")) {
                                RNA_string_get(op->ptr, "filename", params->file);
                        }
                }
@@ -148,6 +157,13 @@ short ED_fileselect_set_params(SpaceFile *sfile)
                        BLI_path_abs(params->dir, G.main->name);
                }
 
+               if(is_directory==TRUE && is_filename==FALSE && is_filepath==FALSE && is_files==FALSE) {
+                       params->flag |= FILE_DIRSEL_ONLY;
+               }
+               else {
+                       params->flag &= ~FILE_DIRSEL_ONLY;
+               }
+
                params->filter = 0;
                if(RNA_struct_find_property(op->ptr, "filter_blender"))
                        params->filter |= RNA_boolean_get(op->ptr, "filter_blender") ? BLENDERFILE : 0;
@@ -209,10 +225,17 @@ short ED_fileselect_set_params(SpaceFile *sfile)
                        params->display= FILE_SHORTDISPLAY;
                }
 
-       } else {
+               if (is_relative_path) {
+                       if (!RNA_struct_property_is_set(op->ptr, "relative_path")) {
+                               RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS);
+                       }
+               }
+       }
+       else {
                /* default values, if no operator */
                params->type = FILE_UNIX;
                params->flag |= FILE_HIDE_DOT;
+               params->flag &= ~FILE_DIRSEL_ONLY;
                params->display = FILE_SHORTDISPLAY;
                params->filter = 0;
                params->filter_glob[0] = '\0';
@@ -225,6 +248,11 @@ short ED_fileselect_set_params(SpaceFile *sfile)
                sfile->folders_prev = folderlist_new();
        folderlist_pushdir(sfile->folders_prev, sfile->params->dir);
 
+       /* switching thumbnails needs to recalc layout [#28809] */
+       if (sfile->layout) {
+               sfile->layout->dirty= TRUE;
+       }
+
        return 1;
 }
 
@@ -240,34 +268,76 @@ int ED_fileselect_layout_numfiles(FileLayout* layout, struct ARegion *ar)
        int numfiles;
 
        if (layout->flag & FILE_LAYOUT_HOR) {
-               int width = ar->v2d.cur.xmax - ar->v2d.cur.xmin - 2*layout->tile_border_x;
-               numfiles = (float)width/(float)layout->tile_w+0.5;
+               int width = (int)(ar->v2d.cur.xmax - ar->v2d.cur.xmin - 2*layout->tile_border_x);
+               numfiles = (int)((float)width / (float)layout->tile_w + 0.5f);
                return numfiles*layout->rows;
        } else {
-               int height = ar->v2d.cur.ymax - ar->v2d.cur.ymin - 2*layout->tile_border_y;
-               numfiles = (float)height/(float)layout->tile_h+0.5;
+               int height = (int)(ar->v2d.cur.ymax - ar->v2d.cur.ymin - 2*layout->tile_border_y);
+               numfiles = (int)((float)height/(float)layout->tile_h + 0.5f);
                return numfiles*layout->columns;
        }
 }
 
-int ED_fileselect_layout_offset(FileLayout* layout, int clamp_bounds, int x, int y)
+static int is_inside(int x, int y, int cols, int rows)
+{
+       return ( (x >= 0) && (x<cols) && (y>=0) && (y<rows) );
+}
+
+FileSelection ED_fileselect_layout_offset_rect(FileLayout* layout, const rcti* rect)
+{
+       int colmin, colmax, rowmin, rowmax;
+       FileSelection sel;
+       sel.first = sel.last = -1;
+
+       if (layout == NULL)
+               return sel;
+       
+       colmin = (rect->xmin)/(layout->tile_w + 2*layout->tile_border_x);
+       rowmin = (rect->ymin)/(layout->tile_h + 2*layout->tile_border_y);
+       colmax = (rect->xmax)/(layout->tile_w + 2*layout->tile_border_x);
+       rowmax = (rect->ymax)/(layout->tile_h + 2*layout->tile_border_y);
+       
+       if ( is_inside(colmin, rowmin, layout->columns, layout->rows) || 
+                is_inside(colmax, rowmax, layout->columns, layout->rows) ) {
+               CLAMP(colmin, 0, layout->columns-1);
+               CLAMP(rowmin, 0, layout->rows-1);
+               CLAMP(colmax, 0, layout->columns-1);
+               CLAMP(rowmax, 0, layout->rows-1);
+       } 
+       
+       if  ( (colmin > layout->columns-1) || (rowmin > layout->rows-1) ) {
+               sel.first = -1;
+       } else {
+               if (layout->flag & FILE_LAYOUT_HOR) 
+                       sel.first = layout->rows*colmin + rowmin;
+               else
+                       sel.first = colmin + layout->columns*rowmin;
+       }
+       if  ( (colmax > layout->columns-1) || (rowmax > layout->rows-1) ) {
+               sel.last = -1;
+       } else {
+               if (layout->flag & FILE_LAYOUT_HOR) 
+                       sel.last = layout->rows*colmax + rowmax;
+               else
+                       sel.last = colmax + layout->columns*rowmax;
+       }
+
+       return sel;
+}
+
+int ED_fileselect_layout_offset(FileLayout* layout, int x, int y)
 {
        int offsetx, offsety;
        int active_file;
 
        if (layout == NULL)
-               return 0;
+               return -1;
        
        offsetx = (x)/(layout->tile_w + 2*layout->tile_border_x);
        offsety = (y)/(layout->tile_h + 2*layout->tile_border_y);
        
-       if (clamp_bounds) {
-               CLAMP(offsetx, 0, layout->columns-1);
-               CLAMP(offsety, 0, layout->rows-1);
-       } else {
-               if (offsetx > layout->columns-1) return -1 ;
-               if (offsety > layout->rows-1) return -1 ;
-       }
+       if (offsetx > layout->columns-1) return -1 ;
+       if (offsety > layout->rows-1) return -1 ;
        
        if (layout->flag & FILE_LAYOUT_HOR) 
                active_file = layout->rows*offsetx + offsety;
@@ -313,7 +383,7 @@ float file_shorten_string(char* string, float w, int front)
                        shortened = 1;
                }
                if (shortened) {
-                       int slen = strlen(s);                   
+                       int slen = strlen(s);
                        BLI_strncpy(temp+3, s, slen+1);
                        temp[slen+4] = '\0';
                        BLI_strncpy(string, temp, slen+4);
@@ -330,7 +400,7 @@ float file_shorten_string(char* string, float w, int front)
                if (shortened) {
                        int slen = strlen(string);
                        if (slen > 3) {
-                               BLI_strncpy(string+slen-3, "...", 4);                           
+                               BLI_strncpy(string+slen-3, "...", 4);
                        }
                }
        }
@@ -340,29 +410,25 @@ float file_shorten_string(char* string, float w, int front)
 
 float file_string_width(const char* str)
 {
-       uiStyle *style= U.uistyles.first;
+       uiStyle *style= UI_GetStyle();
        uiStyleFontSet(&style->widget);
        return BLF_width(style->widget.uifont_id, str);
 }
 
-/* gives the exact width of the string after being shortened to
-   the maximum width. Assumes shortening from the end of the string. */
-float file_string_width_shortened(const char* str, float width)
-{
-       char fname[FILE_MAXFILE];
-
-       BLI_strncpy(fname, str, FILE_MAXFILE);
-       return file_shorten_string(fname, width, 0 );
-}
-
-float file_font_pointsize()
+float file_font_pointsize(void)
 {
+#if 0
        float s;
        char tmp[2] = "X";
-       uiStyle *style= U.uistyles.first;
+       uiStyle *style= UI_GetStyle();
        uiStyleFontSet(&style->widget);
        s = BLF_height(style->widget.uifont_id, tmp);
        return style->widget.points;
+#else
+       uiStyle *style= UI_GetStyle();
+       uiStyleFontSet(&style->widget);
+       return style->widget.points * UI_DPI_FAC;
+#endif
 }
 
 static void column_widths(struct FileList* files, struct FileLayout* layout)
@@ -378,9 +444,9 @@ static void column_widths(struct FileList* files, struct FileLayout* layout)
        {
                struct direntry* file = filelist_file(files, i);        
                if (file) {
-                       int len;
+                       float len;
                        len = file_string_width(file->relname);
-                       if (len > layout->column_widths[COLUMN_NAME]) layout->column_widths[COLUMN_NAME] = len + 20;
+                       if (len > layout->column_widths[COLUMN_NAME]) layout->column_widths[COLUMN_NAME] = len;
                        len = file_string_width(file->date);
                        if (len > layout->column_widths[COLUMN_DATE]) layout->column_widths[COLUMN_DATE] = len;
                        len = file_string_width(file->time);
@@ -402,20 +468,21 @@ static void column_widths(struct FileList* files, struct FileLayout* layout)
 void ED_fileselect_init_layout(struct SpaceFile *sfile, struct ARegion *ar)
 {
        FileSelectParams *params = ED_fileselect_get_params(sfile);
-       FileLayout *layout=0;
+       FileLayout *layout= NULL;
        View2D *v2d= &ar->v2d;
        int maxlen = 0;
        int numfiles;
        int textheight;
-       if (sfile->layout == 0) {
-               sfile->layout = MEM_callocN(sizeof(struct FileLayout), "file_layout");
-               sfile->layout->dirty = 1;
-       } 
 
-       if (!sfile->layout->dirty) return;
+       if (sfile->layout == NULL) {
+               sfile->layout = MEM_callocN(sizeof(struct FileLayout), "file_layout");
+               sfile->layout->dirty = TRUE;
+       } else if (sfile->layout->dirty == FALSE) {
+               return;
+       }
 
        numfiles = filelist_numfiles(sfile->files);
-       textheight = file_font_pointsize();
+       textheight = (int)file_font_pointsize();
        layout = sfile->layout;
        layout->textheight = textheight;
 
@@ -428,7 +495,7 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, struct ARegion *ar)
                layout->prv_border_y = 6;
                layout->tile_w = layout->prv_w + 2*layout->prv_border_x;
                layout->tile_h = layout->prv_h + 2*layout->prv_border_y + textheight;
-               layout->width= (v2d->cur.xmax - v2d->cur.xmin - 2*layout->tile_border_x);
+               layout->width= (int)(v2d->cur.xmax - v2d->cur.xmin - 2*layout->tile_border_x);
                layout->columns= layout->width / (layout->tile_w + 2*layout->tile_border_x);
                if(layout->columns > 0)
                        layout->rows= numfiles/layout->columns + 1; // XXX dirty, modulo is zero
@@ -446,27 +513,28 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, struct ARegion *ar)
                layout->prv_border_x = 0;
                layout->prv_border_y = 0;
                layout->tile_h = textheight*3/2;
-               layout->height= v2d->cur.ymax - v2d->cur.ymin - 2*layout->tile_border_y;
+               layout->height= (int)(v2d->cur.ymax - v2d->cur.ymin - 2*layout->tile_border_y);
                layout->rows = layout->height / (layout->tile_h + 2*layout->tile_border_y);
-        
+
                column_widths(sfile->files, layout);
 
                if (params->display == FILE_SHORTDISPLAY) {
-                       maxlen = layout->column_widths[COLUMN_NAME] + 12 +
-                                        layout->column_widths[COLUMN_SIZE];
-                       maxlen += 20; // for icon
+                       maxlen = ICON_DEFAULT_WIDTH_SCALE + 4 +
+                                        (int)layout->column_widths[COLUMN_NAME] + 12 +
+                                        (int)layout->column_widths[COLUMN_SIZE] + 12;
                } else {
-                       maxlen = layout->column_widths[COLUMN_NAME] + 12 +
+                       maxlen = ICON_DEFAULT_WIDTH_SCALE + 4 +
+                                        (int)layout->column_widths[COLUMN_NAME] + 12 +
 #ifndef WIN32
-                                        layout->column_widths[COLUMN_MODE1] + 12 +
-                                        layout->column_widths[COLUMN_MODE2] + 12 +
-                                        layout->column_widths[COLUMN_MODE3] + 12 +
-                                        layout->column_widths[COLUMN_OWNER] + 12 +
+                                        (int)layout->column_widths[COLUMN_MODE1] + 12 +
+                                        (int)layout->column_widths[COLUMN_MODE2] + 12 +
+                                        (int)layout->column_widths[COLUMN_MODE3] + 12 +
+                                        (int)layout->column_widths[COLUMN_OWNER] + 12 +
 #endif
-                                        layout->column_widths[COLUMN_DATE] + 12 +
-                                        layout->column_widths[COLUMN_TIME] + 12 +
-                                        layout->column_widths[COLUMN_SIZE];
-                       maxlen += 20; // for icon
+                                        (int)layout->column_widths[COLUMN_DATE] + 12 +
+                                        (int)layout->column_widths[COLUMN_TIME] + 12 +
+                                        (int)layout->column_widths[COLUMN_SIZE] + 12;
+
                }
                layout->tile_w = maxlen;
                if(layout->rows > 0)
@@ -478,7 +546,7 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, struct ARegion *ar)
                layout->width = sfile->layout->columns * (layout->tile_w + 2*layout->tile_border_x) + layout->tile_border_x*2;
                layout->flag = FILE_LAYOUT_HOR;
        }
-       layout->dirty= 0;
+       layout->dirty= FALSE;
 }
 
 FileLayout* ED_fileselect_get_layout(struct SpaceFile *sfile, struct ARegion *ar)
@@ -522,7 +590,7 @@ int file_select_match(struct SpaceFile *sfile, const char *pattern)
                for (i = 0; i < n; i++) {
                        file = filelist_file(sfile->files, i);
                        if (fnmatch(pattern, file->relname, 0) == 0) {
-                               file->flags |= ACTIVEFILE;
+                               file->selflag |= SELECTED_FILE;
                                match = 1;
                        }
                }
@@ -541,7 +609,7 @@ void autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v))
                DIR *dir;
                struct dirent *de;
                
-               BLI_split_dirfile(str, dirname, NULL);
+               BLI_split_dir_part(str, dirname, sizeof(dirname));
 
                dir = opendir(dirname);
 
@@ -556,7 +624,7 @@ void autocomplete_directory(struct bContext *C, char *str, void *UNUSED(arg_v))
                                        char path[FILE_MAX];
                                        struct stat status;
                                        
-                                       BLI_join_dirfile(path, dirname, de->d_name);
+                                       BLI_join_dirfile(path, sizeof(path), dirname, de->d_name);
 
                                        if (stat(path, &status) == 0) {
                                                if (S_ISDIR(status.st_mode)) { /* is subdir */
@@ -599,9 +667,13 @@ void autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v))
 
 void ED_fileselect_clear(struct bContext *C, struct SpaceFile *sfile)
 {
-       thumbnails_stop(sfile->files, C);
-       filelist_freelib(sfile->files);
-       filelist_free(sfile->files);
+       /* only NULL in rare cases - [#29734] */
+       if (sfile->files) {
+               thumbnails_stop(sfile->files, C);
+               filelist_freelib(sfile->files);
+               filelist_free(sfile->files);
+       }
+
        sfile->params->active_file = -1;
        WM_event_add_notifier(C, NC_SPACE|ND_SPACE_FILE_LIST, NULL);
 }
@@ -609,9 +681,10 @@ void ED_fileselect_clear(struct bContext *C, struct SpaceFile *sfile)
 void ED_fileselect_exit(struct bContext *C, struct SpaceFile *sfile)
 {
        if(!sfile) return;
-       if(sfile->op)
+       if(sfile->op) {
                WM_event_fileselect_event(C, sfile->op, EVT_FILESELECT_EXTERNAL_CANCEL);
-       sfile->op = NULL;
+               sfile->op = NULL;
+       }
 
        folderlist_free(sfile->folders_prev);
        folderlist_free(sfile->folders_next);