2.5
authorAndrea Weikert <elubie@gmx.net>
Thu, 18 Dec 2008 19:21:30 +0000 (19:21 +0000)
committerAndrea Weikert <elubie@gmx.net>
Thu, 18 Dec 2008 19:21:30 +0000 (19:21 +0000)
Adding back internal files for file/imagebrowser.

projectfiles_vc9/blender/editors/ED_editors.vcproj
source/blender/editors/space_file/filelist.c [new file with mode: 0644]
source/blender/editors/space_file/filelist.h [new file with mode: 0644]
source/blender/editors/space_file/fsmenu.c [new file with mode: 0644]
source/blender/editors/space_file/fsmenu.h [new file with mode: 0644]

index b8ae116d117e4a3400709908d28b3d2910b36ede..073cfea6a5983dbc2ae8f8c3633f8687bae6f8c8 100644 (file)
                                RelativePath="..\..\..\source\blender\editors\space_file\file_intern.h"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\..\..\source\blender\editors\space_file\filelist.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\..\source\blender\editors\space_file\filelist.h"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\..\source\blender\editors\space_file\filesel.c"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath="..\..\..\source\blender\editors\space_file\fsmenu.c"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\..\..\source\blender\editors\space_file\fsmenu.h"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath="..\..\..\source\blender\editors\space_file\space_file.c"\r
                                >\r
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
new file mode 100644 (file)
index 0000000..ab27fba
--- /dev/null
@@ -0,0 +1,1111 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+/* global includes */
+
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include <direct.h>
+#endif   
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+#include "BLI_storage_types.h"
+
+#ifdef WIN32
+#include "BLI_winstuff.h"
+#endif
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BLO_readfile.h"
+
+#include "DNA_space_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_ID.h"
+#include "DNA_object_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_thumbs.h"
+
+#include "PIL_time.h"
+
+#include "ED_datafiles.h"
+
+#include "filelist.h"
+
+/* Elubie: VERY, really very ugly and evil! Remove asap!!! */
+/* for state of file */
+#define ACTIVE                         2
+
+/* max length of library group name within filesel */
+#define GROUP_MAX 32
+
+typedef struct FileList
+{
+       struct direntry *filelist;
+       int *fidx;
+
+       int numfiles;
+       int numfiltered;
+       char dir[FILE_MAX];
+       short type;
+       short ipotype;
+       struct BlendHandle *libfiledata;
+       int has_func;
+       short prv_w;
+       short prv_h;
+       short hide_dot;
+       unsigned int filter;
+} FileList;
+
+int BIF_groupname_to_code(char *group)
+{
+       char buf[32];
+       char *lslash;
+       
+       BLI_strncpy(buf, group, 31);
+       lslash= BLI_last_slash(buf);
+       if (lslash)
+               lslash[0]= '\0';
+
+       return BLO_idcode_from_name(buf);
+}
+
+
+#define SPECIAL_IMG_SIZE 48
+#define SPECIAL_IMG_ROWS 4
+#define SPECIAL_IMG_COLS 4
+
+#define SPECIAL_IMG_FOLDER 0
+#define SPECIAL_IMG_PARENT 1
+#define SPECIAL_IMG_REFRESH 2
+#define SPECIAL_IMG_BLENDFILE 3
+#define SPECIAL_IMG_SOUNDFILE 4
+#define SPECIAL_IMG_MOVIEFILE 5
+#define SPECIAL_IMG_PYTHONFILE 6
+#define SPECIAL_IMG_TEXTFILE 7
+#define SPECIAL_IMG_FONTFILE 8
+#define SPECIAL_IMG_UNKNOWNFILE 9
+#define SPECIAL_IMG_MAX SPECIAL_IMG_UNKNOWNFILE + 1
+
+static ImBuf* gSpecialFileImages[SPECIAL_IMG_MAX];
+
+
+/* ******************* SORT ******************* */
+
+static int compare_name(const void *a1, const void *a2)
+{
+       const struct direntry *entry1=a1, *entry2=a2;
+
+       /* type is is equal to stat.st_mode */
+
+       if (S_ISDIR(entry1->type)){
+               if (S_ISDIR(entry2->type)==0) return (-1);
+       } else{
+               if (S_ISDIR(entry2->type)) return (1);
+       }
+       if (S_ISREG(entry1->type)){
+               if (S_ISREG(entry2->type)==0) return (-1);
+       } else{
+               if (S_ISREG(entry2->type)) return (1);
+       }
+       if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
+       if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
+       
+       /* make sure "." and ".." are always first */
+       if( strcmp(entry1->relname, ".")==0 ) return (-1);
+       if( strcmp(entry2->relname, ".")==0 ) return (1);
+       if( strcmp(entry1->relname, "..")==0 ) return (-1);
+       
+       return (BLI_strcasecmp(entry1->relname,entry2->relname));
+}
+
+static int compare_date(const void *a1, const void *a2)        
+{
+       const struct direntry *entry1=a1, *entry2=a2;
+       
+       /* type is equal to stat.st_mode */
+
+       if (S_ISDIR(entry1->type)){
+               if (S_ISDIR(entry2->type)==0) return (-1);
+       } else{
+               if (S_ISDIR(entry2->type)) return (1);
+       }
+       if (S_ISREG(entry1->type)){
+               if (S_ISREG(entry2->type)==0) return (-1);
+       } else{
+               if (S_ISREG(entry2->type)) return (1);
+       }
+       if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
+       if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
+
+       /* make sure "." and ".." are always first */
+       if( strcmp(entry1->relname, ".")==0 ) return (-1);
+       if( strcmp(entry2->relname, ".")==0 ) return (1);
+       if( strcmp(entry1->relname, "..")==0 ) return (-1);
+       
+       if ( entry1->s.st_mtime < entry2->s.st_mtime) return 1;
+       if ( entry1->s.st_mtime > entry2->s.st_mtime) return -1;
+       
+       else return BLI_strcasecmp(entry1->relname,entry2->relname);
+}
+
+static int compare_size(const void *a1, const void *a2)        
+{
+       const struct direntry *entry1=a1, *entry2=a2;
+
+       /* type is equal to stat.st_mode */
+
+       if (S_ISDIR(entry1->type)){
+               if (S_ISDIR(entry2->type)==0) return (-1);
+       } else{
+               if (S_ISDIR(entry2->type)) return (1);
+       }
+       if (S_ISREG(entry1->type)){
+               if (S_ISREG(entry2->type)==0) return (-1);
+       } else{
+               if (S_ISREG(entry2->type)) return (1);
+       }
+       if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
+       if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
+
+       /* make sure "." and ".." are always first */
+       if( strcmp(entry1->relname, ".")==0 ) return (-1);
+       if( strcmp(entry2->relname, ".")==0 ) return (1);
+       if( strcmp(entry1->relname, "..")==0 ) return (-1);
+       
+       if ( entry1->s.st_size < entry2->s.st_size) return 1;
+       if ( entry1->s.st_size > entry2->s.st_size) return -1;
+       else return BLI_strcasecmp(entry1->relname,entry2->relname);
+}
+
+static int compare_extension(const void *a1, const void *a2) {
+       const struct direntry *entry1=a1, *entry2=a2;
+       char *sufix1, *sufix2;
+       char *nil="";
+
+       if (!(sufix1= strstr (entry1->relname, ".blend.gz"))) 
+               sufix1= strrchr (entry1->relname, '.');
+       if (!(sufix2= strstr (entry2->relname, ".blend.gz")))
+               sufix2= strrchr (entry2->relname, '.');
+       if (!sufix1) sufix1= nil;
+       if (!sufix2) sufix2= nil;
+
+       /* type is is equal to stat.st_mode */
+
+       if (S_ISDIR(entry1->type)){
+               if (S_ISDIR(entry2->type)==0) return (-1);
+       } else{
+               if (S_ISDIR(entry2->type)) return (1);
+       }
+       if (S_ISREG(entry1->type)){
+               if (S_ISREG(entry2->type)==0) return (-1);
+       } else{
+               if (S_ISREG(entry2->type)) return (1);
+       }
+       if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1);
+       if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1);
+       
+       /* make sure "." and ".." are always first */
+       if( strcmp(entry1->relname, ".")==0 ) return (-1);
+       if( strcmp(entry2->relname, ".")==0 ) return (1);
+       if( strcmp(entry1->relname, "..")==0 ) return (-1);
+       if( strcmp(entry2->relname, "..")==0 ) return (-1);
+       
+       return (BLI_strcasecmp(sufix1, sufix2));
+}
+
+void filelist_filter(FileList* filelist)
+{
+       char dir[FILE_MAX], group[GROUP_MAX];
+       int num_filtered = 0;
+       int i, j;
+       
+       if (!filelist->filelist)
+               return;
+       
+       if ( ( (filelist->type == FILE_LOADLIB) &&  filelist_islibrary(filelist, dir, group)) 
+               || (filelist->type == FILE_MAIN) ) {
+               filelist->filter = 0;
+       }
+
+       if (!filelist->filter) {
+               if (filelist->fidx) {
+                       MEM_freeN(filelist->fidx);
+                       filelist->fidx = NULL;
+               }
+               filelist->fidx = (int *)MEM_callocN(filelist->numfiles*sizeof(int), "filteridx");
+               for (i = 0; i < filelist->numfiles; ++i) {
+                       filelist->fidx[i] = i;
+               }
+               filelist->numfiltered = filelist->numfiles;
+               return;
+       }
+
+       // How many files are left after filter ?
+       for (i = 0; i < filelist->numfiles; ++i) {
+               if (filelist->filelist[i].flags & filelist->filter) {
+                       num_filtered++;
+               } 
+               else if (filelist->filelist[i].type & S_IFDIR) {
+                       if (filelist->filter & FOLDERFILE) {
+                               num_filtered++;
+                       }
+               }               
+       }
+       
+       if (filelist->fidx) {
+                       MEM_freeN(filelist->fidx);
+                       filelist->fidx = NULL;
+       }
+       filelist->fidx = (int *)MEM_callocN(num_filtered*sizeof(int), "filteridx");
+       filelist->numfiltered = num_filtered;
+
+       for (i = 0, j=0; i < filelist->numfiles; ++i) {
+               if (filelist->filelist[i].flags & filelist->filter) {
+                       filelist->fidx[j++] = i;
+               }
+               else if (filelist->filelist[i].type & S_IFDIR) {
+                       if (filelist->filter & FOLDERFILE) {
+                               filelist->fidx[j++] = i;
+                       }
+               }  
+       }
+}
+
+void filelist_init_icons()
+{
+#if 0 /* XXX add icons here */
+       short x, y, k;
+       ImBuf *bbuf;
+       ImBuf *ibuf;
+       bbuf = IMB_ibImageFromMemory((int *)datatoc_prvicons, datatoc_prvicons_size, IB_rect);
+       if (bbuf) {
+               for (y=0; y<SPECIAL_IMG_ROWS; y++) {
+                       for (x=0; x<SPECIAL_IMG_COLS; x++) {
+                               int tile = SPECIAL_IMG_COLS*y + x; 
+                               if (tile < SPECIAL_IMG_MAX) {
+                                       ibuf = IMB_allocImBuf(SPECIAL_IMG_SIZE, SPECIAL_IMG_SIZE, 32, IB_rect, 0);
+                                       for (k=0; k<SPECIAL_IMG_SIZE; k++) {
+                                               memcpy(&ibuf->rect[k*SPECIAL_IMG_SIZE], &bbuf->rect[(k+y*SPECIAL_IMG_SIZE)*SPECIAL_IMG_SIZE*SPECIAL_IMG_COLS+x*SPECIAL_IMG_SIZE], SPECIAL_IMG_SIZE*sizeof(int));
+                                       }
+                                       gSpecialFileImages[tile] = ibuf;
+                               }
+                       }
+               }
+               IMB_freeImBuf(bbuf);
+       }
+#endif
+}
+
+void filelist_free_icons()
+{
+       int i;
+       for (i=0; i < SPECIAL_IMG_MAX; ++i) {
+               IMB_freeImBuf(gSpecialFileImages[i]);
+               gSpecialFileImages[i] = NULL;
+       }
+}
+
+struct FileList*       filelist_new()
+{
+       FileList* p = MEM_callocN( sizeof(FileList), "filelist" );
+       p->filelist = 0;
+       p->numfiles = 0;
+       p->dir[0] = '\0';
+       p->libfiledata = 0;
+       p->type = 0;
+       p->has_func = 0;
+       p->filter = 0;
+       return p;
+}
+
+struct FileList*       filelist_copy(struct FileList* filelist)
+{
+       FileList* p = filelist_new();
+       BLI_strncpy(p->dir, filelist->dir, FILE_MAX);
+       p->filelist = NULL;
+       p->fidx = NULL;
+       p->type = filelist->type;
+       p->ipotype = filelist->ipotype;
+       p->has_func = filelist->has_func;
+
+       return p;
+}
+
+void filelist_free(struct FileList* filelist)
+{
+       int i;
+
+       if (!filelist) {
+               printf("Attemtping to delete empty filelist.\n");
+               return;
+       }
+
+       if (filelist->fidx) {
+               MEM_freeN(filelist->fidx);
+               filelist->fidx = NULL;
+       }
+
+       for (i = 0; i < filelist->numfiles; ++i) {
+               if (filelist->filelist[i].image) {                      
+                       IMB_freeImBuf(filelist->filelist[i].image);
+               }
+               filelist->filelist[i].image = 0;
+               if (filelist->filelist[i].relname)
+                       MEM_freeN(filelist->filelist[i].relname);
+               filelist->filelist[i].relname = 0;
+               if (filelist->filelist[i].string)
+                       MEM_freeN(filelist->filelist[i].string);
+               filelist->filelist[i].string = 0;
+       }
+       
+       filelist->numfiles = 0;
+       free(filelist->filelist);
+       filelist->filelist = 0; 
+       filelist->filter = 0;
+       filelist->numfiltered =0;
+}
+
+void filelist_freelib(struct FileList* filelist)
+{
+       if(filelist->libfiledata)       
+               BLO_blendhandle_close(filelist->libfiledata);
+       filelist->libfiledata= 0;
+}
+
+struct BlendHandle *filelist_lib(struct FileList* filelist)
+{
+       return filelist->libfiledata;
+}
+
+int    filelist_numfiles(struct FileList* filelist)
+{
+       return filelist->numfiltered;
+}
+
+const char * filelist_dir(struct FileList* filelist)
+{
+       return filelist->dir;
+}
+
+void filelist_setdir(struct FileList* filelist, const char *dir)
+{
+       BLI_strncpy(filelist->dir, dir, FILE_MAX);
+}
+
+void filelist_imgsize(struct FileList* filelist, short w, short h)
+{
+       filelist->prv_w = w;
+       filelist->prv_h = h;
+}
+
+void filelist_loadimage(struct FileList* filelist, int index)
+{
+       ImBuf *imb = NULL;
+       int imgwidth = filelist->prv_w;
+       int imgheight = filelist->prv_h;
+       short ex, ey, dx, dy;
+       float scaledx, scaledy;
+       int fidx = 0;
+       
+       if ( (index < 0) || (index >= filelist->numfiltered) ) {
+               return;
+       }
+       fidx = filelist->fidx[index];
+
+       if (!filelist->filelist[fidx].image)
+       {
+               if (filelist->type != FILE_MAIN)
+               {
+                       if ( filelist->filelist[fidx].flags & IMAGEFILE ) {                             
+                               imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_IMAGE);
+                       } else if ( filelist->filelist[fidx].flags & MOVIEFILE ) {                              
+                               imb = IMB_thumb_manage(filelist->dir, filelist->filelist[fidx].relname, THB_NORMAL, THB_SOURCE_MOVIE);
+                               if (!imb) {
+                                       /* remember that file can't be loaded via IMB_open_anim */
+                                       filelist->filelist[fidx].flags &= ~MOVIEFILE;
+                                       filelist->filelist[fidx].flags |= MOVIEFILE_ICON;
+                               }
+                       }
+                       if (imb) {
+                               if (imb->x > imb->y) {
+                                       scaledx = (float)imgwidth;
+                                       scaledy =  ( (float)imb->y/(float)imb->x )*imgwidth;
+                               }
+                               else {
+                                       scaledy = (float)imgheight;
+                                       scaledx =  ( (float)imb->x/(float)imb->y )*imgheight;
+                               }
+                               ex = (short)scaledx;
+                               ey = (short)scaledy;
+                               
+                               dx = imgwidth - ex;
+                               dy = imgheight - ey;
+                               
+                               IMB_scaleImBuf(imb, ex, ey);
+
+                       } 
+                       filelist->filelist[fidx].image = imb;
+                       
+               }
+       }
+}
+
+struct ImBuf * filelist_getimage(struct FileList* filelist, int index)
+{
+       ImBuf* ibuf = NULL;
+       int fidx = 0;   
+       if ( (index < 0) || (index >= filelist->numfiltered) ) {
+               return NULL;
+       }
+       fidx = filelist->fidx[index];
+       ibuf = filelist->filelist[fidx].image;
+
+       if (ibuf == NULL) {
+               struct direntry *file = &filelist->filelist[fidx];
+               if (file->type & S_IFDIR) {
+                       if ( strcmp(filelist->filelist[fidx].relname, "..") == 0) {
+                               ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
+                       } else if  ( strcmp(filelist->filelist[fidx].relname, ".") == 0) {
+                               ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
+                       } else {
+                               ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
+                       }
+               } else {
+                       ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
+               }
+
+               if (file->flags & BLENDERFILE) {
+                       ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
+               } else if ( (file->flags & MOVIEFILE) || (file->flags & MOVIEFILE_ICON) ) {
+                       ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
+               } else if (file->flags & SOUNDFILE) {
+                       ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
+               } else if (file->flags & PYSCRIPTFILE) {
+                       ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
+               } else if (file->flags & FTFONTFILE) {
+                       ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
+               } else if (file->flags & TEXTFILE) {
+                       ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
+               } 
+       }
+       return ibuf;
+}
+
+struct direntry * filelist_file(struct FileList* filelist, int index)
+{
+       int fidx = 0;
+       
+       if ( (index < 0) || (index >= filelist->numfiltered) ) {
+               return NULL;
+       }
+       fidx = filelist->fidx[index];
+
+       return &filelist->filelist[fidx];
+}
+
+int filelist_find(struct FileList* filelist, char *file)
+{
+       int index = -1;
+       int i;
+       int fidx = -1;
+       
+       if (!filelist->fidx) 
+               return fidx;
+
+       
+       for (i = 0; i < filelist->numfiles; ++i) {
+               if ( strcmp(filelist->filelist[i].relname, file) == 0) {
+                       index = i;
+                       break;
+               }
+       }
+
+       for (i = 0; i < filelist->numfiltered; ++i) {
+               if (filelist->fidx[i] == index) {
+                       fidx = i;
+                       break;
+               }
+       }
+       return fidx;
+}
+
+void filelist_hidedot(struct FileList* filelist, short hide)
+{
+       filelist->hide_dot = hide;
+}
+
+void filelist_setfilter(struct FileList* filelist, unsigned int filter)
+{
+       filelist->filter = filter;
+}
+
+void filelist_readdir(struct FileList* filelist)
+{
+       char wdir[FILE_MAX];
+       int finished = 0;
+
+       if (!filelist) return;
+       filelist->fidx = 0;
+       filelist->filelist = 0;
+
+       if(filelist->type==FILE_MAIN) {
+               filelist_from_main(filelist);
+               finished = 1;
+       } else if(filelist->type==FILE_LOADLIB) {
+               BLI_cleanup_dir(G.sce, filelist->dir);
+               filelist_from_library(filelist);
+               if(filelist->libfiledata) {
+                       finished = 1;
+               }
+       }
+
+       if (!finished) {
+               BLI_getwdN(wdir);        
+               
+               BLI_cleanup_dir(G.sce, filelist->dir);
+               BLI_hide_dot_files(filelist->hide_dot);
+               filelist->numfiles = BLI_getdir(filelist->dir, &(filelist->filelist));
+
+               chdir(wdir);
+               filelist_setfiletypes(filelist, G.have_quicktime);
+               filelist_filter(filelist);
+
+       }
+}
+
+int filelist_empty(struct FileList* filelist)
+{      
+       return filelist->filelist == 0;
+}
+
+void filelist_parent(struct FileList* filelist)
+{
+       BLI_parent_dir(filelist->dir);
+       BLI_make_exist(filelist->dir);
+       filelist_readdir(filelist);
+}
+
+void filelist_setfiletypes(struct FileList* filelist, short has_quicktime)
+{
+       struct direntry *file;
+       int num;
+
+       file= filelist->filelist;
+
+       for(num=0; num<filelist->numfiles; num++, file++) {
+               file->flags= 0;
+               file->type= file->s.st_mode;    /* restore the mess below */ 
+
+                       /* Don't check extensions for directories */ 
+               if (file->type & S_IFDIR)
+                       continue;
+                               
+               
+               
+               if(BLO_has_bfile_extension(file->relname)) {
+                       file->flags |= BLENDERFILE;
+                       if(filelist->type==FILE_LOADLIB) {              
+                               char name[FILE_MAXDIR+FILE_MAXFILE];
+                               BLI_strncpy(name, filelist->dir, sizeof(name));
+                               strcat(name, file->relname);
+                               
+                               /* prevent current file being used as acceptable dir */
+                               if (BLI_streq(G.main->name, name)==0) {
+                                       file->type &= ~S_IFMT;
+                                       file->type |= S_IFDIR;
+                               }
+                       }
+               } else if(BLI_testextensie(file->relname, ".py")) {
+                               file->flags |= PYSCRIPTFILE;
+               } else if(BLI_testextensie(file->relname, ".txt")) {
+                               file->flags |= TEXTFILE;
+               } else if( BLI_testextensie(file->relname, ".ttf")
+                                       || BLI_testextensie(file->relname, ".ttc")
+                                       || BLI_testextensie(file->relname, ".pfb")
+                                       || BLI_testextensie(file->relname, ".otf")
+                                       || BLI_testextensie(file->relname, ".otc")) {
+                               file->flags |= FTFONTFILE;                      
+               } else if (has_quicktime){
+                       if(             BLI_testextensie(file->relname, ".int")
+                               ||  BLI_testextensie(file->relname, ".inta")
+                               ||  BLI_testextensie(file->relname, ".jpg")
+                               ||      BLI_testextensie(file->relname, ".jpeg")
+                               ||      BLI_testextensie(file->relname, ".tga")
+                               ||      BLI_testextensie(file->relname, ".rgb")
+                               ||      BLI_testextensie(file->relname, ".rgba")
+                               ||      BLI_testextensie(file->relname, ".bmp")
+                               ||      BLI_testextensie(file->relname, ".png")
+                               ||      BLI_testextensie(file->relname, ".iff")
+                               ||      BLI_testextensie(file->relname, ".lbm")
+                               ||      BLI_testextensie(file->relname, ".gif")
+                               ||      BLI_testextensie(file->relname, ".psd")
+                               ||      BLI_testextensie(file->relname, ".tif")
+                               ||      BLI_testextensie(file->relname, ".tiff")
+                               ||      BLI_testextensie(file->relname, ".pct")
+                               ||      BLI_testextensie(file->relname, ".pict")
+                               ||      BLI_testextensie(file->relname, ".pntg") //macpaint
+                               ||      BLI_testextensie(file->relname, ".qtif")
+                               ||      BLI_testextensie(file->relname, ".sgi")
+                               ||      BLI_testextensie(file->relname, ".hdr")
+#ifdef WITH_DDS
+                               ||      BLI_testextensie(file->relname, ".dds")
+#endif
+#ifdef WITH_OPENEXR
+                               ||      BLI_testextensie(file->relname, ".exr")
+#endif
+                           ) {
+                               file->flags |= IMAGEFILE;                       
+                       }
+                       else if(BLI_testextensie(file->relname, ".avi")
+                               ||      BLI_testextensie(file->relname, ".flc")
+                               ||      BLI_testextensie(file->relname, ".mov")
+                               ||      BLI_testextensie(file->relname, ".movie")
+                               ||      BLI_testextensie(file->relname, ".mp4")
+                               ||      BLI_testextensie(file->relname, ".m4v")
+                               ||      BLI_testextensie(file->relname, ".mv")) {
+                               file->flags |= MOVIEFILE;                       
+                       }
+                       else if(BLI_testextensie(file->relname, ".wav")) {
+                               file->flags |= SOUNDFILE;
+                       }
+               } else { // no quicktime
+                       if(BLI_testextensie(file->relname, ".int")
+                               ||      BLI_testextensie(file->relname, ".inta")
+                               ||      BLI_testextensie(file->relname, ".jpg")
+                               ||      BLI_testextensie(file->relname, ".tga")
+                               ||      BLI_testextensie(file->relname, ".rgb")
+                               ||      BLI_testextensie(file->relname, ".rgba")
+                               ||      BLI_testextensie(file->relname, ".bmp")
+                               ||      BLI_testextensie(file->relname, ".png")
+                               ||      BLI_testextensie(file->relname, ".iff")
+                               ||      BLI_testextensie(file->relname, ".tif")
+                               ||      BLI_testextensie(file->relname, ".tiff")
+                               ||      BLI_testextensie(file->relname, ".hdr")
+#ifdef WITH_DDS
+                               ||      BLI_testextensie(file->relname, ".dds")
+#endif
+#ifdef WITH_OPENEXR
+                               ||      BLI_testextensie(file->relname, ".exr")
+#endif
+                               ||      BLI_testextensie(file->relname, ".lbm")
+                               ||      BLI_testextensie(file->relname, ".sgi")) {
+                               file->flags |= IMAGEFILE;                       
+                       }
+                       else if(BLI_testextensie(file->relname, ".avi")
+                               ||      BLI_testextensie(file->relname, ".mp4")
+                               ||      BLI_testextensie(file->relname, ".mv")) {
+                               file->flags |= MOVIEFILE;                       
+                       }
+                       else if(BLI_testextensie(file->relname, ".wav")) {
+                               file->flags |= SOUNDFILE;
+                       }
+               }
+       }
+}
+
+void filelist_swapselect(struct FileList* filelist)
+{
+       struct direntry *file;
+       int num, act= 0;
+       
+       file= filelist->filelist;
+       for(num=0; num<filelist->numfiles; num++, file++) {
+               if(file->flags & ACTIVE) {
+                       act= 1;
+                       break;
+               }
+       }
+       file= filelist->filelist+2;
+       for(num=2; num<filelist->numfiles; num++, file++) {
+               if(act) file->flags &= ~ACTIVE;
+               else file->flags |= ACTIVE;
+       }
+}
+
+int filelist_islibrary(struct FileList* filelist, char* dir, char* group)
+{
+        /* return ok when a blenderfile, in dir is the filename,
+        * in group the type of libdata
+        */
+       int len;
+       char *fd;
+       
+       strcpy(dir, filelist->dir);
+       len= strlen(dir);
+       if(len<7) return 0;
+       if( dir[len-1] != '/' && dir[len-1] != '\\') return 0;
+               
+       group[0]= 0;
+       dir[len-1]= 0;
+
+       /* Find the last slash */
+       fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
+
+       if(fd==0) return 0;
+       *fd= 0;
+       if(BLO_has_bfile_extension(fd+1)) {
+               *fd= '/';
+       }
+       else {
+               char *gp = fd+1; // in case we have a .blend file, gp points to the group
+
+               /* Find the last slash */
+               fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
+               if (!fd || !BLO_has_bfile_extension(fd+1)) return 0;
+
+               /* now we know that we are in a blend file and it is safe to 
+                  assume that gp actually points to a group */
+               BLI_strncpy(group, gp, GROUP_MAX);
+       }
+       return 1;
+}
+
+void filelist_from_library(struct FileList* filelist)
+{
+       LinkNode *l, *names, *previews;
+       struct ImBuf* ima;
+       int ok, i, nnames, idcode;
+       char filename[FILE_MAXDIR+FILE_MAXFILE];
+       char dir[FILE_MAX], group[GROUP_MAX];   
+       
+       filelist->type = FILE_LOADLIB;
+
+       /* name test */
+       ok= filelist_islibrary(filelist, dir, group);
+       if (!ok) {
+               /* free */
+               if(filelist->libfiledata) BLO_blendhandle_close(filelist->libfiledata);
+               filelist->libfiledata= 0;
+               return;
+       }
+       
+       BLI_strncpy(filename, G.sce, sizeof(filename)); // G.sce = last file loaded, for UI
+
+       /* there we go */
+       /* for the time being only read filedata when libfiledata==0 */
+       if (filelist->libfiledata==0) {
+               filelist->libfiledata= BLO_blendhandle_from_file(dir);
+               if(filelist->libfiledata==0) return;
+       }
+       
+       idcode= BIF_groupname_to_code(group);
+
+               // memory for strings is passed into filelist[i].relname
+               // and free'd in freefilelist
+       previews = NULL;
+       if (idcode) {
+               previews= BLO_blendhandle_get_previews(filelist->libfiledata, idcode);
+               names= BLO_blendhandle_get_datablock_names(filelist->libfiledata, idcode);
+               /* ugh, no rewind, need to reopen */
+               BLO_blendhandle_close(filelist->libfiledata);
+               filelist->libfiledata= BLO_blendhandle_from_file(dir);
+               
+       } else {
+               names= BLO_blendhandle_get_linkable_groups(filelist->libfiledata);
+       }
+       
+       nnames= BLI_linklist_length(names);
+
+       filelist->numfiles= nnames + 2;
+       filelist->filelist= malloc(filelist->numfiles * sizeof(*filelist->filelist));
+       memset(filelist->filelist, 0, filelist->numfiles * sizeof(*filelist->filelist));
+
+       filelist->filelist[0].relname= BLI_strdup(".");
+       filelist->filelist[0].type |= S_IFDIR;
+       filelist->filelist[1].relname= BLI_strdup("..");
+       filelist->filelist[1].type |= S_IFDIR;
+               
+       for (i=0, l= names; i<nnames; i++, l= l->next) {
+               char *blockname= l->link;
+
+               filelist->filelist[i + 2].relname= BLI_strdup(blockname);
+               if (!idcode)
+                       filelist->filelist[i + 2].type |= S_IFDIR;
+       }
+       
+       if(previews) {
+               for (i=0, l= previews; i<nnames; i++, l= l->next) {
+                       PreviewImage *img= l->link;
+                       
+                       if (img) {
+                               unsigned int w = img->w[PREVIEW_MIPMAP_LARGE];
+                               unsigned int h = img->h[PREVIEW_MIPMAP_LARGE];
+                               unsigned int *rect = img->rect[PREVIEW_MIPMAP_LARGE];
+
+                               /* first allocate imbuf for copying preview into it */
+                               if (w > 0 && h > 0 && rect) {
+                                       ima = IMB_allocImBuf(w, h, 32, IB_rect, 0);
+                                       memcpy(ima->rect, rect, w*h*sizeof(unsigned int));
+                                       filelist->filelist[i + 2].image = ima;
+                                       filelist->filelist[i + 2].flags = IMAGEFILE;
+                               }
+                       }
+               }
+       }
+
+       BLI_linklist_free(names, free);
+       if (previews) BLI_linklist_free(previews, (void(*)(void*)) MEM_freeN);
+
+       filelist_sort(filelist, FILE_SORTALPHA);
+
+       BLI_strncpy(G.sce, filename, sizeof(filename)); // prevent G.sce to change
+
+       filelist->filter = 0;
+       filelist_filter(filelist);
+}
+
+void filelist_append_library(struct FileList *filelist, char *dir, char *file, short flag, int idcode, struct Scene* scene)
+{
+       BLO_library_append_(&filelist->libfiledata, filelist->filelist, filelist->numfiles, dir, file, flag, idcode, scene);
+}
+
+void filelist_from_main(struct FileList *filelist)
+{
+       ID *id;
+       struct direntry *files, *firstlib = NULL;
+       ListBase *lb;
+       int a, fake, idcode, ok, totlib, totbl;
+       
+       filelist->type = FILE_MAIN;
+
+       if(filelist->dir[0]=='/') filelist->dir[0]= 0;
+       
+       if(filelist->dir[0]) {
+               idcode= BIF_groupname_to_code(filelist->dir);
+               if(idcode==0) filelist->dir[0]= 0;
+       }
+       
+       if( filelist->dir[0]==0) {
+               
+               /* make directories */
+               filelist->numfiles= 23;
+               filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry));
+               
+               for(a=0; a<filelist->numfiles; a++) {
+                       memset( &(filelist->filelist[a]), 0 , sizeof(struct direntry));
+                       filelist->filelist[a].type |= S_IFDIR;
+               }
+               
+               filelist->filelist[0].relname= BLI_strdup("..");
+               filelist->filelist[1].relname= BLI_strdup(".");
+               filelist->filelist[2].relname= BLI_strdup("Scene");
+               filelist->filelist[3].relname= BLI_strdup("Object");
+               filelist->filelist[4].relname= BLI_strdup("Mesh");
+               filelist->filelist[5].relname= BLI_strdup("Curve");
+               filelist->filelist[6].relname= BLI_strdup("Metaball");
+               filelist->filelist[7].relname= BLI_strdup("Material");
+               filelist->filelist[8].relname= BLI_strdup("Texture");
+               filelist->filelist[9].relname= BLI_strdup("Image");
+               filelist->filelist[10].relname= BLI_strdup("Ika");
+               filelist->filelist[11].relname= BLI_strdup("Wave");
+               filelist->filelist[12].relname= BLI_strdup("Lattice");
+               filelist->filelist[13].relname= BLI_strdup("Lamp");
+               filelist->filelist[14].relname= BLI_strdup("Camera");
+               filelist->filelist[15].relname= BLI_strdup("Ipo");
+               filelist->filelist[16].relname= BLI_strdup("World");
+               filelist->filelist[17].relname= BLI_strdup("Screen");
+               filelist->filelist[18].relname= BLI_strdup("VFont");
+               filelist->filelist[19].relname= BLI_strdup("Text");
+               filelist->filelist[20].relname= BLI_strdup("Armature");
+               filelist->filelist[21].relname= BLI_strdup("Action");
+               filelist->filelist[22].relname= BLI_strdup("NodeTree");
+               filelist_sort(filelist, FILE_SORTALPHA);
+       }
+       else {
+
+               /* make files */
+               idcode= BIF_groupname_to_code(filelist->dir);
+               
+               lb= wich_libbase(G.main, idcode );
+               if(lb==0) return;
+               
+               id= lb->first;
+               filelist->numfiles= 0;
+               while(id) {
+                       
+                       if(filelist->has_func && idcode==ID_IP) {
+                               if(filelist->ipotype== ((Ipo *)id)->blocktype) filelist->numfiles++;
+                       }
+                       else if (!filelist->hide_dot || id->name[2] != '.') {
+                               filelist->numfiles++;
+                       }
+                       
+                       id= id->next;
+               }
+               
+               if(!filelist->has_func) filelist->numfiles+= 2;
+               filelist->filelist= (struct direntry *)malloc(filelist->numfiles * sizeof(struct direntry));
+               
+               files = filelist->filelist;
+               
+               if(!filelist->has_func) {
+                       memset( &(filelist->filelist[0]), 0 , sizeof(struct direntry));
+                       filelist->filelist[0].relname= BLI_strdup(".");
+                       filelist->filelist[0].type |= S_IFDIR;
+                       memset( &(filelist->filelist[1]), 0 , sizeof(struct direntry));
+                       filelist->filelist[1].relname= BLI_strdup("..");
+                       filelist->filelist[1].type |= S_IFDIR;
+               
+                       files+= 2;
+               }
+               
+               id= lb->first;
+               totlib= totbl= 0;
+               
+               while(id) {
+                       
+                       ok= 0;
+                       if(filelist->has_func && idcode==ID_IP) {
+                               if(filelist->ipotype== ((Ipo *)id)->blocktype) ok= 1;
+                       }
+                       else ok= 1;
+                       
+                       if(ok) {
+                               /* TODO: hide dot files - elubie */
+                               memset( files, 0 , sizeof(struct direntry));
+                               if(id->lib==NULL)
+                                       files->relname= BLI_strdup(id->name+2);
+                               else {
+                                       files->relname= MEM_mallocN(FILE_MAXDIR+FILE_MAXFILE+32, "filename for lib");
+                                       sprintf(files->relname, "%s | %s", id->lib->name, id->name+2);
+                               }
+                               /* files->type |= S_IFDIR; */
+                               if(!filelist->has_func) { /* F4 DATA BROWSE */
+                                       if(idcode==ID_OB) {
+                                               if( ((Object *)id)->flag & SELECT) files->flags |= ACTIVE;
+                                       }
+                                       else if(idcode==ID_SCE) {
+                                               if( ((Scene *)id)->r.scemode & R_BG_RENDER) files->flags |= ACTIVE;
+                                       }                                       
+                               }
+                               files->nr= totbl+1;
+                               files->poin= id;
+                               fake= id->flag & LIB_FAKEUSER;
+                               if(idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO || idcode == ID_IM) {
+                                       files->flags |= IMAGEFILE;
+                               }
+                               if(id->lib && fake) sprintf(files->extra, "LF %d", id->us);
+                               else if(id->lib) sprintf(files->extra, "L    %d", id->us);
+                               else if(fake) sprintf(files->extra, "F    %d", id->us);
+                               else sprintf(files->extra, "      %d", id->us);
+                               
+                               if(id->lib) {
+                                       if(totlib==0) firstlib= files;
+                                       totlib++;
+                               }
+                               
+                               files++;
+                               totbl++;
+                       }
+                       
+                       id= id->next;
+               }
+               
+               /* only qsort of library blocks */
+               if(totlib>1) {
+                       qsort(firstlib, totlib, sizeof(struct direntry), compare_name);
+               }
+       }
+       filelist->filter = 0;
+       filelist_filter(filelist);
+}
+
+
+void filelist_settype(struct FileList* filelist, int type)
+{
+       filelist->type = type;
+}
+
+short filelist_gettype(struct FileList* filelist)
+{
+       return filelist->type;
+}
+
+void filelist_sort(struct FileList* filelist, short sort)
+{
+       struct direntry *file;
+       int num;/*  , act= 0; */
+
+       switch(sort) {
+       case FILE_SORTALPHA:
+               qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_name);   
+               break;
+       case FILE_SORTDATE:
+               qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_date);   
+               break;
+       case FILE_SORTSIZE:
+               qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_size);   
+               break;
+       case FILE_SORTEXTENS:
+               qsort(filelist->filelist, filelist->numfiles, sizeof(struct direntry), compare_extension);      
+       }
+
+       file= filelist->filelist;
+       for(num=0; num<filelist->numfiles; num++, file++) {
+               file->flags &= ~HILITE;
+       }
+       filelist_filter(filelist);
+}
+
+
+void filelist_setipotype(struct FileList* filelist, short ipotype)
+{
+       filelist->ipotype = ipotype;
+}
+
+void filelist_hasfunc(struct FileList* filelist, int has_func)
+{
+       filelist->has_func = has_func;
+}
+
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
new file mode 100644 (file)
index 0000000..4a4c431
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef FILELIST_H
+#define FILELIST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct FileList;
+struct direntry;
+struct BlendHandle;
+struct Scene;
+
+struct FileList *      filelist_new();
+void                           filelist_init_icons();
+void                           filelist_free_icons();
+struct FileList *      filelist_copy(struct FileList* filelist);
+int                                    filelist_find(struct FileList* filelist, char *file);
+void                           filelist_free(struct FileList* filelist);
+void                           filelist_freelib(struct FileList* filelist);
+void                           filelist_sort(struct FileList* filelist, short sort);
+int                                    filelist_numfiles(struct FileList* filelist);
+const char *           filelist_dir(struct FileList* filelist);
+void                           filelist_setdir(struct FileList* filelist, const char *dir);
+struct direntry *      filelist_file(struct FileList* filelist, int index);
+void                           filelist_hidedot(struct FileList* filelist, short hide);
+void                           filelist_setfilter(struct FileList* filelist, unsigned int filter);
+void                           filelist_filter(struct FileList* filelist);
+void                           filelist_swapselect(struct FileList* filelist);
+void                           filelist_imgsize(struct FileList* filelist, short w, short h);
+void                           filelist_loadimage(struct FileList* filelist, int index);
+struct ImBuf *         filelist_getimage(struct FileList* filelist, int index);
+
+void                           filelist_readdir(struct FileList* filelist);
+
+int                                    filelist_empty(struct FileList* filelist);
+void                           filelist_parent(struct FileList* filelist);
+void                           filelist_setfiletypes(struct FileList* filelist, short has_quicktime);
+int                                    filelist_islibrary (struct FileList* filelist, char* dir, char* group);
+void                           filelist_from_main(struct FileList* filelist);
+void                           filelist_from_library(struct FileList* filelist);
+void                           filelist_append_library(struct FileList* filelist, char *dir, char* file, short flag, int idcode, struct Scene* scene);
+void                           filelist_settype(struct FileList* filelist, int type);
+short                          filelist_gettype(struct FileList* filelist);
+void                           filelist_setipotype(struct FileList* filelist, short ipotype);
+void                           filelist_hasfunc(struct FileList* filelist, int has_func);
+
+struct BlendHandle *filelist_lib(struct FileList* filelist);
+int                                    groupname_to_code(char *group); /* TODO: where should this go */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
new file mode 100644 (file)
index 0000000..843649f
--- /dev/null
@@ -0,0 +1,253 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_linklist.h"
+#include "BLI_dynstr.h"
+
+
+#include "fsmenu.h"  /* include ourselves */
+
+
+/* FSMENU HANDLING */
+
+       /* FSMenuEntry's without paths indicate seperators */
+typedef struct _FSMenuEntry FSMenuEntry;
+struct _FSMenuEntry {
+       FSMenuEntry *next;
+
+       char *path;
+       short save;
+};
+
+static FSMenuEntry *fsmenu= 0;
+
+int fsmenu_get_nentries(void)
+{
+       FSMenuEntry *fsme;
+       int count= 0;
+
+       for (fsme= fsmenu; fsme; fsme= fsme->next) 
+               count++;
+
+       return count;
+}
+int fsmenu_is_entry_a_seperator(int idx)
+{
+       FSMenuEntry *fsme;
+
+       for (fsme= fsmenu; fsme && idx; fsme= fsme->next)
+               idx--;
+
+       return (fsme && !fsme->path)?1:0;
+}
+char *fsmenu_get_entry(int idx)
+{
+       FSMenuEntry *fsme;
+
+       for (fsme= fsmenu; fsme && idx; fsme= fsme->next)
+               idx--;
+
+       return fsme?fsme->path:NULL;
+}
+char *fsmenu_build_menu(void)
+{
+       DynStr *ds= BLI_dynstr_new();
+       FSMenuEntry *fsme;
+       char *menustr;
+
+       for (fsme= fsmenu; fsme; fsme= fsme->next) {
+               if (!fsme->path) {
+                               /* clean consecutive seperators and ignore trailing ones */
+                       if (fsme->next) {
+                               if (fsme->next->path) {
+                                       BLI_dynstr_append(ds, "%l|");
+                               } else {
+                                       FSMenuEntry *next= fsme->next;
+                                       fsme->next= next->next;
+                                       MEM_freeN(next);
+                               }
+                       }
+               } else {
+                       if (fsme->save) {
+                               BLI_dynstr_append(ds, "o ");
+                       } else {
+                               BLI_dynstr_append(ds, "  ");
+                       }
+                       BLI_dynstr_append(ds, fsme->path);
+                       if (fsme->next) BLI_dynstr_append(ds, "|");
+               }
+       }
+
+       menustr= BLI_dynstr_get_cstring(ds);
+       BLI_dynstr_free(ds);
+       return menustr;
+}
+static FSMenuEntry *fsmenu_get_last_separator(void) 
+{
+       FSMenuEntry *fsme, *lsep=NULL;
+
+       for (fsme= fsmenu; fsme; fsme= fsme->next)
+               if (!fsme->path)
+                       lsep= fsme;
+
+       return lsep;
+}
+
+static FSMenuEntry *fsmenu_get_first_separator(void) 
+{
+       FSMenuEntry *fsme, *lsep=NULL;
+
+       for (fsme= fsmenu; fsme; fsme= fsme->next)
+               if (!fsme->path) {
+                       lsep= fsme;
+                       break;
+               }
+
+       return lsep;
+}
+
+void fsmenu_insert_entry(char *path, int sorted, short save)
+{
+       FSMenuEntry *prev;
+       FSMenuEntry *fsme;
+
+       if (save) {
+               prev = fsmenu_get_first_separator();
+       } else {
+               prev = fsmenu_get_last_separator();
+       }
+       fsme= prev?prev->next:fsmenu;
+
+       for (; fsme; prev= fsme, fsme= fsme->next) {
+               if (fsme->path) {
+                       if (BLI_streq(path, fsme->path)) {
+                               return;
+                       } else if (sorted && strcmp(path, fsme->path)<0) {
+                               break;
+                       }
+               } else {
+                       // if we're bookmarking this, file should come 
+                       // before the last separator, only automatically added
+                       // current dir go after the last sep.
+                       if (save) {
+                               break;
+                       }
+               }
+       }
+       
+       fsme= MEM_mallocN(sizeof(*fsme), "fsme");
+       fsme->path= BLI_strdup(path);
+       fsme->save = save;
+
+       if (prev) {
+               fsme->next= prev->next;
+               prev->next= fsme;
+       } else {
+               fsme->next= fsmenu;
+               fsmenu= fsme;
+       }
+}
+void fsmenu_append_separator(void)
+{
+       if (fsmenu) {
+               FSMenuEntry *fsme= fsmenu;
+
+               while (fsme->next) fsme= fsme->next;
+
+               fsme->next= MEM_mallocN(sizeof(*fsme), "fsme");
+               fsme->next->next= NULL;
+               fsme->next->path= NULL;
+       }
+}
+void fsmenu_remove_entry(int idx)
+{
+       FSMenuEntry *prev= NULL, *fsme= fsmenu;
+
+       for (fsme= fsmenu; fsme && idx; prev= fsme, fsme= fsme->next)           
+               idx--;
+
+       if (fsme) {
+               /* you should only be able to remove entries that were 
+                  not added by default, like windows drives.
+                  also separators (where path == NULL) shouldn't be removed */
+               if (fsme->save && fsme->path) {
+
+                       /* remove fsme from list */
+                       if (prev) {
+                               prev->next= fsme->next;
+                       } else {
+                               fsmenu= fsme->next;
+                       }
+                       /* free entry */
+                       MEM_freeN(fsme->path);
+                       MEM_freeN(fsme);
+               }
+       }
+}
+
+void fsmenu_write_file(const char *filename)
+{
+       FSMenuEntry *fsme= fsmenu;
+
+       FILE *fp = fopen(filename, "w");
+       if (!fp) return;
+
+       for (fsme= fsmenu; fsme; fsme= fsme->next) {
+               if (fsme->path && fsme->save) {
+                       fprintf(fp, "%s\n", fsme->path);
+               }
+       }
+       fclose(fp);
+}
+
+void fsmenu_free(void)
+{
+       FSMenuEntry *fsme= fsmenu;
+
+       while (fsme) {
+               FSMenuEntry *n= fsme->next;
+
+               if (fsme->path) MEM_freeN(fsme->path);
+               MEM_freeN(fsme);
+
+               fsme= n;
+       }
+}
+
+
+
diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h
new file mode 100644 (file)
index 0000000..7cd7f78
--- /dev/null
@@ -0,0 +1,73 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * 
+ */
+
+#ifndef BSE_FSMENU_H
+#define BSE_FSMENU_H
+
+       /** Returns the number of entries in the Fileselect Menu */
+int            fsmenu_get_nentries             (void);
+
+       /** Returns true if the fsmenu entry at @a index exists and
+        * is a seperator.
+        */
+int    fsmenu_is_entry_a_seperator     (int index);
+
+       /** Returns the fsmenu entry at @a index (or NULL if a bad index)
+     * or a seperator.
+        */
+char*  fsmenu_get_entry                (int index);
+
+       /** Returns a new menu description string representing the
+        * fileselect menu. Should be free'd with MEM_freeN.
+        */
+char*  fsmenu_build_menu               (void);
+
+       /** Append a seperator to the FSMenu, inserts always follow the
+        * last seperator.
+        */
+void   fsmenu_append_separator (void);
+
+       /** Inserts a new fsmenu entry with the given @a path.
+        * Duplicate entries are not added.
+        * @param sorted Should entry be inserted in sorted order?
+        */
+void   fsmenu_insert_entry             (char *path, int sorted, short save);
+
+       /** Removes the fsmenu entry at the given @a index. */
+void   fsmenu_remove_entry             (int index);
+
+       /** saves the 'favourites' to the specified file */
+void   fsmenu_write_file(const char *filename);
+
+       /** Free's all the memory associated with the fsmenu */
+void   fsmenu_free                             (void);
+
+#endif
+