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