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 "BLI_blenlib.h"
37 #include "BLI_linklist.h"
38 #include "BLI_dynstr.h"
39
40
41 #include "fsmenu.h"  /* include ourselves */
42
43
44 /* FSMENU HANDLING */
45
46         /* FSMenuEntry's without paths indicate seperators */
47 typedef struct _FSMenuEntry FSMenuEntry;
48 struct _FSMenuEntry {
49         FSMenuEntry *next;
50
51         char *path;
52         short save;
53 };
54
55 static FSMenuEntry *fsmenu= 0;
56
57 int fsmenu_get_nentries(void)
58 {
59         FSMenuEntry *fsme;
60         int count= 0;
61
62         for (fsme= fsmenu; fsme; fsme= fsme->next) 
63                 count++;
64
65         return count;
66 }
67 int fsmenu_is_entry_a_seperator(int idx)
68 {
69         FSMenuEntry *fsme;
70
71         for (fsme= fsmenu; fsme && idx; fsme= fsme->next)
72                 idx--;
73
74         return (fsme && !fsme->path)?1:0;
75 }
76 char *fsmenu_get_entry(int idx)
77 {
78         FSMenuEntry *fsme;
79
80         for (fsme= fsmenu; fsme && idx; fsme= fsme->next)
81                 idx--;
82
83         return fsme?fsme->path:NULL;
84 }
85 char *fsmenu_build_menu(void)
86 {
87         DynStr *ds= BLI_dynstr_new();
88         FSMenuEntry *fsme;
89         char *menustr;
90
91         for (fsme= fsmenu; fsme; fsme= fsme->next) {
92                 if (!fsme->path) {
93                                 /* clean consecutive seperators and ignore trailing ones */
94                         if (fsme->next) {
95                                 if (fsme->next->path) {
96                                         BLI_dynstr_append(ds, "%l|");
97                                 } else {
98                                         FSMenuEntry *next= fsme->next;
99                                         fsme->next= next->next;
100                                         MEM_freeN(next);
101                                 }
102                         }
103                 } else {
104                         if (fsme->save) {
105                                 BLI_dynstr_append(ds, "o ");
106                         } else {
107                                 BLI_dynstr_append(ds, "  ");
108                         }
109                         BLI_dynstr_append(ds, fsme->path);
110                         if (fsme->next) BLI_dynstr_append(ds, "|");
111                 }
112         }
113
114         menustr= BLI_dynstr_get_cstring(ds);
115         BLI_dynstr_free(ds);
116         return menustr;
117 }
118 static FSMenuEntry *fsmenu_get_last_separator(void) 
119 {
120         FSMenuEntry *fsme, *lsep=NULL;
121
122         for (fsme= fsmenu; fsme; fsme= fsme->next)
123                 if (!fsme->path)
124                         lsep= fsme;
125
126         return lsep;
127 }
128
129 static FSMenuEntry *fsmenu_get_first_separator(void) 
130 {
131         FSMenuEntry *fsme, *lsep=NULL;
132
133         for (fsme= fsmenu; fsme; fsme= fsme->next)
134                 if (!fsme->path) {
135                         lsep= fsme;
136                         break;
137                 }
138
139         return lsep;
140 }
141
142 void fsmenu_insert_entry(char *path, int sorted, short save)
143 {
144         FSMenuEntry *prev;
145         FSMenuEntry *fsme;
146
147         if (save) {
148                 prev = fsmenu_get_first_separator();
149         } else {
150                 prev = fsmenu_get_last_separator();
151         }
152         fsme= prev?prev->next:fsmenu;
153
154         for (; fsme; prev= fsme, fsme= fsme->next) {
155                 if (fsme->path) {
156                         if (BLI_streq(path, fsme->path)) {
157                                 return;
158                         } else if (sorted && strcmp(path, fsme->path)<0) {
159                                 break;
160                         }
161                 } else {
162                         // if we're bookmarking this, file should come 
163                         // before the last separator, only automatically added
164                         // current dir go after the last sep.
165                         if (save) {
166                                 break;
167                         }
168                 }
169         }
170         
171         fsme= MEM_mallocN(sizeof(*fsme), "fsme");
172         fsme->path= BLI_strdup(path);
173         fsme->save = save;
174
175         if (prev) {
176                 fsme->next= prev->next;
177                 prev->next= fsme;
178         } else {
179                 fsme->next= fsmenu;
180                 fsmenu= fsme;
181         }
182 }
183 void fsmenu_append_separator(void)
184 {
185         if (fsmenu) {
186                 FSMenuEntry *fsme= fsmenu;
187
188                 while (fsme->next) fsme= fsme->next;
189
190                 fsme->next= MEM_mallocN(sizeof(*fsme), "fsme");
191                 fsme->next->next= NULL;
192                 fsme->next->path= NULL;
193         }
194 }
195 void fsmenu_remove_entry(int idx)
196 {
197         FSMenuEntry *prev= NULL, *fsme= fsmenu;
198
199         for (fsme= fsmenu; fsme && idx; prev= fsme, fsme= fsme->next)           
200                 idx--;
201
202         if (fsme) {
203                 /* you should only be able to remove entries that were 
204                    not added by default, like windows drives.
205                    also separators (where path == NULL) shouldn't be removed */
206                 if (fsme->save && fsme->path) {
207
208                         /* remove fsme from list */
209                         if (prev) {
210                                 prev->next= fsme->next;
211                         } else {
212                                 fsmenu= fsme->next;
213                         }
214                         /* free entry */
215                         MEM_freeN(fsme->path);
216                         MEM_freeN(fsme);
217                 }
218         }
219 }
220
221 void fsmenu_write_file(const char *filename)
222 {
223         FSMenuEntry *fsme= fsmenu;
224
225         FILE *fp = fopen(filename, "w");
226         if (!fp) return;
227
228         for (fsme= fsmenu; fsme; fsme= fsme->next) {
229                 if (fsme->path && fsme->save) {
230                         fprintf(fp, "%s\n", fsme->path);
231                 }
232         }
233         fclose(fp);
234 }
235
236 void fsmenu_free(void)
237 {
238         FSMenuEntry *fsme= fsmenu;
239
240         while (fsme) {
241                 FSMenuEntry *n= fsme->next;
242
243                 if (fsme->path) MEM_freeN(fsme->path);
244                 MEM_freeN(fsme);
245
246                 fsme= n;
247         }
248 }
249
250
251