diff options
Diffstat (limited to 'src/lib/FL/Fl_Native_File_Chooser_FLTK.cxx')
-rw-r--r-- | src/lib/FL/Fl_Native_File_Chooser_FLTK.cxx | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/src/lib/FL/Fl_Native_File_Chooser_FLTK.cxx b/src/lib/FL/Fl_Native_File_Chooser_FLTK.cxx new file mode 100644 index 0000000..5d9c1fd --- /dev/null +++ b/src/lib/FL/Fl_Native_File_Chooser_FLTK.cxx | |||
@@ -0,0 +1,339 @@ | |||
1 | // | ||
2 | // Fl_Native_File_Chooser_DEFAULT.cxx -- FLTK native OS file chooser widget | ||
3 | // March 2005 - wrapper around Fl_File_Chooser by natevw | ||
4 | // | ||
5 | // Copyright 2005 by Nathan Vander Wilt. | ||
6 | // | ||
7 | // | ||
8 | // This library is free software; you can redistribute it and/or | ||
9 | // modify it under the terms of the GNU Library General Public | ||
10 | // License as published by the Free Software Foundation; either | ||
11 | // version 2 of the License, or (at your option) any later version. | ||
12 | // | ||
13 | // This library is distributed in the hope that it will be useful, | ||
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | // Library General Public License for more details. | ||
17 | // | ||
18 | // You should have received a copy of the GNU Library General Public | ||
19 | // License along with this library; if not, write to the Free Software | ||
20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
21 | // USA. | ||
22 | // | ||
23 | // Please keep code 80 column compliant. | ||
24 | // | ||
25 | // 10 20 30 40 50 60 70 | ||
26 | // | | | | | | | | ||
27 | // 4567890123456789012345678901234567890123456789012345678901234567890123456789 | ||
28 | // | ||
29 | #include <Fl/x.H> | ||
30 | #include <FL/Fl_File_Icon.H> | ||
31 | #include <FL/Fl_Native_File_Chooser.H> | ||
32 | #include "common.cxx" | ||
33 | |||
34 | static int G_init = 0; // 'first time' initialize flag | ||
35 | |||
36 | // CTOR | ||
37 | Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { | ||
38 | if ( G_init == 0 ) { | ||
39 | // Initialize when instanced for first time | ||
40 | // Fl_File_Icon::load_system_icons(); // OK to call more than once | ||
41 | G_init = 1; // eg. if app already called from main() | ||
42 | } | ||
43 | _btype = val; | ||
44 | _options = NO_OPTIONS; | ||
45 | _filter = NULL; | ||
46 | _parsedfilt = NULL; | ||
47 | _preset_file = NULL; | ||
48 | _prevvalue = NULL; | ||
49 | _directory = NULL; | ||
50 | _errmsg = NULL; | ||
51 | file_chooser = new Fl_File_Chooser(NULL, NULL, 0, NULL); | ||
52 | type(val); // do this after file_chooser created | ||
53 | _nfilters = 0; | ||
54 | } | ||
55 | |||
56 | // DTOR | ||
57 | Fl_Native_File_Chooser::~Fl_Native_File_Chooser() { | ||
58 | delete file_chooser; | ||
59 | _filter = strfree(_filter); | ||
60 | _parsedfilt = strfree(_parsedfilt); | ||
61 | _preset_file = strfree(_preset_file); | ||
62 | _prevvalue = strfree(_prevvalue); | ||
63 | _directory = strfree(_directory); | ||
64 | _errmsg = strfree(_errmsg); | ||
65 | } | ||
66 | |||
67 | // PRIVATE: SET ERROR MESSAGE | ||
68 | void Fl_Native_File_Chooser::errmsg(const char *msg) { | ||
69 | _errmsg = strfree(_errmsg); | ||
70 | _errmsg = strnew(msg); | ||
71 | } | ||
72 | |||
73 | // PRIVATE: translate Native types to Fl_File_Chooser types | ||
74 | int Fl_Native_File_Chooser::type_fl_file(int val) { | ||
75 | switch (val) { | ||
76 | case BROWSE_FILE: | ||
77 | return(Fl_File_Chooser::SINGLE); | ||
78 | case BROWSE_DIRECTORY: | ||
79 | return(Fl_File_Chooser::SINGLE | Fl_File_Chooser::DIRECTORY); | ||
80 | case BROWSE_MULTI_FILE: | ||
81 | return(Fl_File_Chooser::MULTI); | ||
82 | case BROWSE_MULTI_DIRECTORY: | ||
83 | return(Fl_File_Chooser::DIRECTORY | Fl_File_Chooser::MULTI); | ||
84 | case BROWSE_SAVE_FILE: | ||
85 | return(Fl_File_Chooser::SINGLE | Fl_File_Chooser::CREATE); | ||
86 | case BROWSE_SAVE_DIRECTORY: | ||
87 | return(Fl_File_Chooser::DIRECTORY | Fl_File_Chooser::SINGLE | Fl_File_Chooser::CREATE); | ||
88 | default: | ||
89 | return(Fl_File_Chooser::SINGLE); | ||
90 | } | ||
91 | } | ||
92 | |||
93 | void Fl_Native_File_Chooser::type(int val) { | ||
94 | _btype = val; | ||
95 | file_chooser->type(type_fl_file(val)); | ||
96 | } | ||
97 | |||
98 | int Fl_Native_File_Chooser::type() const { | ||
99 | return(_btype); | ||
100 | } | ||
101 | |||
102 | // SET OPTIONS | ||
103 | void Fl_Native_File_Chooser::options(int val) { | ||
104 | _options = val; | ||
105 | } | ||
106 | |||
107 | // GET OPTIONS | ||
108 | int Fl_Native_File_Chooser::options() const { | ||
109 | return(_options); | ||
110 | } | ||
111 | |||
112 | // Show chooser, blocks until done. | ||
113 | // RETURNS: | ||
114 | // 0 - user picked a file | ||
115 | // 1 - user cancelled | ||
116 | // -1 - failed; errmsg() has reason | ||
117 | // | ||
118 | int Fl_Native_File_Chooser::show() { | ||
119 | // FILTER | ||
120 | if ( _parsedfilt ) { | ||
121 | file_chooser->filter(_parsedfilt); | ||
122 | } | ||
123 | |||
124 | // FILTER VALUE | ||
125 | // Set this /after/ setting the filter | ||
126 | // | ||
127 | if (_filtvalue!=-1) | ||
128 | { | ||
129 | file_chooser->filter_value(_filtvalue); | ||
130 | } | ||
131 | |||
132 | // DIRECTORY | ||
133 | if ( _directory && _directory[0] ) { | ||
134 | file_chooser->directory(_directory); | ||
135 | } else { | ||
136 | file_chooser->directory(_prevvalue); | ||
137 | } | ||
138 | |||
139 | // PRESET FILE | ||
140 | if ( _preset_file ) { | ||
141 | file_chooser->value(_preset_file); | ||
142 | } | ||
143 | |||
144 | // OPTIONS: PREVIEW | ||
145 | file_chooser->preview( (options() & PREVIEW) ? 1 : 0); | ||
146 | |||
147 | // OPTIONS: NEW FOLDER | ||
148 | if ( options() & NEW_FOLDER ) | ||
149 | file_chooser->type(file_chooser->type() | Fl_File_Chooser::CREATE); // on | ||
150 | |||
151 | // SHOW | ||
152 | file_chooser->show(); | ||
153 | |||
154 | while ( file_chooser->shown() ) { | ||
155 | Fl::wait(); // block while shown | ||
156 | } | ||
157 | |||
158 | if ( file_chooser->value() && file_chooser->value()[0] ) { | ||
159 | _prevvalue = strfree(_prevvalue); | ||
160 | _prevvalue = strnew(file_chooser->value()); | ||
161 | _filtvalue = file_chooser->filter_value(); // update filter value | ||
162 | |||
163 | // HANDLE SHOWING 'SaveAs' CONFIRM | ||
164 | if ( options() & SAVEAS_CONFIRM && type() == BROWSE_SAVE_FILE ) { | ||
165 | struct stat buf; | ||
166 | if ( stat(file_chooser->value(), &buf) != -1 ) { | ||
167 | if ( buf.st_mode & S_IFREG ) { // Regular file + exists? | ||
168 | if ( fl_choice("File exists. Are you sure you want to overwrite?", "Cancel", " OK ", NULL) == 0 ) { | ||
169 | return(1); | ||
170 | } | ||
171 | } | ||
172 | } | ||
173 | } | ||
174 | } | ||
175 | |||
176 | if ( file_chooser->count() ) return(0); | ||
177 | else return(1); | ||
178 | } | ||
179 | |||
180 | // RETURN ERROR MESSAGE | ||
181 | const char *Fl_Native_File_Chooser::errmsg() const { | ||
182 | return(_errmsg ? _errmsg : "No error"); | ||
183 | } | ||
184 | |||
185 | // GET FILENAME | ||
186 | const char* Fl_Native_File_Chooser::filename() const { | ||
187 | if ( file_chooser->count() > 0 ) return(file_chooser->value()); | ||
188 | return(""); | ||
189 | } | ||
190 | |||
191 | // GET FILENAME FROM LIST OF FILENAMES | ||
192 | const char* Fl_Native_File_Chooser::filename(int i) const { | ||
193 | if ( i < file_chooser->count() ) return(file_chooser->value(i+1)); // convert fltk 1 based to our 0 based | ||
194 | return(""); | ||
195 | } | ||
196 | |||
197 | // SET TITLE | ||
198 | // Can be NULL if no title desired. | ||
199 | // | ||
200 | void Fl_Native_File_Chooser::title(const char *val) { | ||
201 | file_chooser->label(val); | ||
202 | } | ||
203 | |||
204 | // GET TITLE | ||
205 | // Can return NULL if none set. | ||
206 | // | ||
207 | const char *Fl_Native_File_Chooser::title() const { | ||
208 | return(file_chooser->label()); | ||
209 | } | ||
210 | |||
211 | // SET FILTER | ||
212 | // Can be NULL if no filter needed | ||
213 | // | ||
214 | void Fl_Native_File_Chooser::filter(const char *val) { | ||
215 | _filter = strfree(_filter); | ||
216 | _filter = strnew(val); | ||
217 | parse_filter(); | ||
218 | } | ||
219 | |||
220 | // GET FILTER | ||
221 | const char *Fl_Native_File_Chooser::filter() const { | ||
222 | return(_filter); | ||
223 | } | ||
224 | |||
225 | // SET SELECTED FILTER | ||
226 | void Fl_Native_File_Chooser::filter_value(int val) { | ||
227 | _filtvalue = val; | ||
228 | } | ||
229 | |||
230 | // RETURN SELECTED FILTER | ||
231 | int Fl_Native_File_Chooser::filter_value() const { | ||
232 | return(_filtvalue); | ||
233 | } | ||
234 | |||
235 | // GET TOTAL FILENAMES CHOSEN | ||
236 | int Fl_Native_File_Chooser::count() const { | ||
237 | return(file_chooser->count()); | ||
238 | } | ||
239 | |||
240 | // PRESET PATHNAME | ||
241 | // Can be NULL if no preset is desired. | ||
242 | // | ||
243 | void Fl_Native_File_Chooser::directory(const char *val) { | ||
244 | _directory = strfree(_directory); | ||
245 | _directory = strnew(val); | ||
246 | } | ||
247 | |||
248 | // GET PRESET PATHNAME | ||
249 | // Can return NULL if none set. | ||
250 | // | ||
251 | const char *Fl_Native_File_Chooser::directory() const { | ||
252 | return(_directory); | ||
253 | } | ||
254 | |||
255 | // Convert our filter format to Fl_File_Chooser's format | ||
256 | // FROM TO (FLTK) | ||
257 | // ------------------------- -------------------------- | ||
258 | // "*.cxx" "*.cxx Files(*.cxx)" | ||
259 | // "C Files\t*.{cxx,h}" "C Files(*.{cxx,h})" | ||
260 | // "C Files\t*.{cxx,h}\nText Files\t*.txt" "C Files(*.{cxx,h})\tText Files(*.txt)" | ||
261 | // | ||
262 | // Returns a modified version of the filter that the caller is responsible | ||
263 | // for freeing with strfree(). | ||
264 | // | ||
265 | void Fl_Native_File_Chooser::parse_filter() { | ||
266 | _parsedfilt = strfree(_parsedfilt); // clear previous parsed filter (if any) | ||
267 | _nfilters = 0; | ||
268 | char *in = _filter; | ||
269 | if ( !in ) return; | ||
270 | |||
271 | int has_name = strchr(in, '\t') ? 1 : 0; | ||
272 | |||
273 | char mode = has_name ? 'n' : 'w'; // parse mode: n=title, w=wildcard | ||
274 | char wildcard[1024] = ""; // parsed wildcard | ||
275 | char name[1024] = ""; | ||
276 | |||
277 | // Parse filter user specified | ||
278 | for ( ; 1; in++ ) { | ||
279 | |||
280 | /*** DEBUG | ||
281 | printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n", | ||
282 | *in, mode, name, wildcard); | ||
283 | ***/ | ||
284 | |||
285 | switch (*in) { | ||
286 | // FINISHED PARSING NAME? | ||
287 | case '\t': | ||
288 | if ( mode != 'n' ) goto regchar; | ||
289 | mode = 'w'; | ||
290 | break; | ||
291 | |||
292 | // ESCAPE NEXT CHAR | ||
293 | case '\\': | ||
294 | ++in; | ||
295 | goto regchar; | ||
296 | |||
297 | // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS? | ||
298 | case '\r': | ||
299 | case '\n': | ||
300 | case '\0': | ||
301 | // APPEND NEW FILTER TO LIST | ||
302 | if ( wildcard[0] ) { | ||
303 | // OUT: "name(wild)\tname(wild)" | ||
304 | char comp[2048]; | ||
305 | sprintf(comp, "%s%.511s(%.511s)", ((_parsedfilt)?"\t":""), name, wildcard); | ||
306 | _parsedfilt = strapp(_parsedfilt, comp); | ||
307 | _nfilters++; | ||
308 | //DEBUG printf("DEBUG: PARSED FILT NOW <%s>\n", _parsedfilt); | ||
309 | } | ||
310 | // RESET | ||
311 | wildcard[0] = name[0] = '\0'; | ||
312 | mode = strchr(in, '\t') ? 'n' : 'w'; | ||
313 | // DONE? | ||
314 | if ( *in == '\0' ) return; // done | ||
315 | else continue; // not done yet, more filters | ||
316 | |||
317 | // Parse all other chars | ||
318 | default: // handle all non-special chars | ||
319 | regchar: // handle regular char | ||
320 | switch ( mode ) { | ||
321 | case 'n': chrcat(name, *in); continue; | ||
322 | case 'w': chrcat(wildcard, *in); continue; | ||
323 | } | ||
324 | break; | ||
325 | } | ||
326 | } | ||
327 | //NOTREACHED | ||
328 | } | ||
329 | |||
330 | // SET PRESET FILENAME | ||
331 | void Fl_Native_File_Chooser::preset_file(const char* val) { | ||
332 | _preset_file = strfree(_preset_file); | ||
333 | _preset_file = strnew(val); | ||
334 | } | ||
335 | |||
336 | // GET PRESET FILENAME | ||
337 | const char* Fl_Native_File_Chooser::preset_file() const { | ||
338 | return(_preset_file); | ||
339 | } | ||