diff options
author | Andrea Weikert <elubie@gmx.net> | 2008-12-18 22:21:30 +0300 |
---|---|---|
committer | Andrea Weikert <elubie@gmx.net> | 2008-12-18 22:21:30 +0300 |
commit | af746acaad8fcfb289e6e56e9199c5b492429934 (patch) | |
tree | 10a89139f4d1fe904fab65589ec4badb8b8cc052 /source/blender | |
parent | 1d3a42451da1a9ac4f263824363f19ce631e7144 (diff) |
2.5
Adding back internal files for file/imagebrowser.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/space_file/filelist.c | 1111 | ||||
-rw-r--r-- | source/blender/editors/space_file/filelist.h | 87 | ||||
-rw-r--r-- | source/blender/editors/space_file/fsmenu.c | 253 | ||||
-rw-r--r-- | source/blender/editors/space_file/fsmenu.h | 73 |
4 files changed, 1524 insertions, 0 deletions
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c new file mode 100644 index 00000000000..ab27fba1863 --- /dev/null +++ b/source/blender/editors/space_file/filelist.c @@ -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 index 00000000000..4a4c431c323 --- /dev/null +++ b/source/blender/editors/space_file/filelist.h @@ -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 index 00000000000..843649f973d --- /dev/null +++ b/source/blender/editors/space_file/fsmenu.c @@ -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 index 00000000000..7cd7f78a363 --- /dev/null +++ b/source/blender/editors/space_file/fsmenu.h @@ -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 + |