2.5
[blender-staging.git] / source / blender / editors / space_file / fsmenu.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BMF_Api.h"
37
38 #include "BLI_blenlib.h"
39 #include "BLI_linklist.h"
40 #include "BLI_dynstr.h"
41
42
43 #include "fsmenu.h"  /* include ourselves */
44
45
46 /* FSMENU HANDLING */
47
48         /* FSMenuEntry's without paths indicate seperators */
49 typedef struct _FSMenuEntry FSMenuEntry;
50 struct _FSMenuEntry {
51         FSMenuEntry *next;
52
53         char *path;
54         short save;
55 };
56
57 static FSMenuEntry *fsmenu= 0;
58
59 int fsmenu_get_nentries(void)
60 {
61         FSMenuEntry *fsme;
62         int count= 0;
63
64         for (fsme= fsmenu; fsme; fsme= fsme->next) 
65                 count++;
66
67         return count;
68 }
69 int fsmenu_is_entry_a_seperator(int idx)
70 {
71         FSMenuEntry *fsme;
72
73         for (fsme= fsmenu; fsme && idx; fsme= fsme->next)
74                 idx--;
75
76         return (fsme && !fsme->path)?1:0;
77 }
78 char *fsmenu_get_entry(int idx)
79 {
80         FSMenuEntry *fsme;
81
82         for (fsme= fsmenu; fsme && idx; fsme= fsme->next)
83                 idx--;
84
85         return fsme?fsme->path:NULL;
86 }
87 char *fsmenu_build_menu(void)
88 {
89         DynStr *ds= BLI_dynstr_new();
90         FSMenuEntry *fsme;
91         char *menustr;
92
93         for (fsme= fsmenu; fsme; fsme= fsme->next) {
94                 if (!fsme->path) {
95                                 /* clean consecutive seperators and ignore trailing ones */
96                         if (fsme->next) {
97                                 if (fsme->next->path) {
98                                         BLI_dynstr_append(ds, "%l|");
99                                 } else {
100                                         FSMenuEntry *next= fsme->next;
101                                         fsme->next= next->next;
102                                         MEM_freeN(next);
103                                 }
104                         }
105                 } else {
106                         if (fsme->save) {
107                                 BLI_dynstr_append(ds, "o ");
108                         } else {
109                                 BLI_dynstr_append(ds, "  ");
110                         }
111                         BLI_dynstr_append(ds, fsme->path);
112                         if (fsme->next) BLI_dynstr_append(ds, "|");
113                 }
114         }
115
116         menustr= BLI_dynstr_get_cstring(ds);
117         BLI_dynstr_free(ds);
118         return menustr;
119 }
120 static FSMenuEntry *fsmenu_get_last_separator(void) 
121 {
122         FSMenuEntry *fsme, *lsep=NULL;
123
124         for (fsme= fsmenu; fsme; fsme= fsme->next)
125                 if (!fsme->path)
126                         lsep= fsme;
127
128         return lsep;
129 }
130
131 static FSMenuEntry *fsmenu_get_first_separator(void) 
132 {
133         FSMenuEntry *fsme, *lsep=NULL;
134
135         for (fsme= fsmenu; fsme; fsme= fsme->next)
136                 if (!fsme->path) {
137                         lsep= fsme;
138                         break;
139                 }
140
141         return lsep;
142 }
143
144 void fsmenu_insert_entry(char *path, int sorted, short save)
145 {
146         FSMenuEntry *prev;
147         FSMenuEntry *fsme;
148
149         if (save) {
150                 prev = fsmenu_get_first_separator();
151         } else {
152                 prev = fsmenu_get_last_separator();
153         }
154         fsme= prev?prev->next:fsmenu;
155
156         for (; fsme; prev= fsme, fsme= fsme->next) {
157                 if (fsme->path) {
158                         if (BLI_streq(path, fsme->path)) {
159                                 return;
160                         } else if (sorted && strcmp(path, fsme->path)<0) {
161                                 break;
162                         }
163                 } else {
164                         // if we're bookmarking this, file should come 
165                         // before the last separator, only automatically added
166                         // current dir go after the last sep.
167                         if (save) {
168                                 break;
169                         }
170                 }
171         }
172         
173         fsme= MEM_mallocN(sizeof(*fsme), "fsme");
174         fsme->path= BLI_strdup(path);
175         fsme->save = save;
176
177         if (prev) {
178                 fsme->next= prev->next;
179                 prev->next= fsme;
180         } else {
181                 fsme->next= fsmenu;
182                 fsmenu= fsme;
183         }
184 }
185 void fsmenu_append_separator(void)
186 {
187         if (fsmenu) {
188                 FSMenuEntry *fsme= fsmenu;
189
190                 while (fsme->next) fsme= fsme->next;
191
192                 fsme->next= MEM_mallocN(sizeof(*fsme), "fsme");
193                 fsme->next->next= NULL;
194                 fsme->next->path= NULL;
195         }
196 }
197 void fsmenu_remove_entry(int idx)
198 {
199         FSMenuEntry *prev= NULL, *fsme= fsmenu;
200
201         for (fsme= fsmenu; fsme && idx; prev= fsme, fsme= fsme->next)           
202                 idx--;
203
204         if (fsme) {
205                 /* you should only be able to remove entries that were 
206                    not added by default, like windows drives.
207                    also separators (where path == NULL) shouldn't be removed */
208                 if (fsme->save && fsme->path) {
209
210                         /* remove fsme from list */
211                         if (prev) {
212                                 prev->next= fsme->next;
213                         } else {
214                                 fsmenu= fsme->next;
215                         }
216                         /* free entry */
217                         MEM_freeN(fsme->path);
218                         MEM_freeN(fsme);
219                 }
220         }
221 }
222
223 void fsmenu_write_file(const char *filename)
224 {
225         FSMenuEntry *fsme= fsmenu;
226
227         FILE *fp = fopen(filename, "w");
228         if (!fp) return;
229
230         for (fsme= fsmenu; fsme; fsme= fsme->next) {
231                 if (fsme->path && fsme->save) {
232                         fprintf(fp, "%s\n", fsme->path);
233                 }
234         }
235         fclose(fp);
236 }
237
238 void fsmenu_free(void)
239 {
240         FSMenuEntry *fsme= fsmenu;
241
242         while (fsme) {
243                 FSMenuEntry *n= fsme->next;
244
245                 if (fsme->path) MEM_freeN(fsme->path);
246                 MEM_freeN(fsme);
247
248                 fsme= n;
249         }
250 }
251
252
253