aboutsummaryrefslogtreecommitdiff
path: root/src/lib/FL/Fl_Native_File_Chooser_FLTK.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/FL/Fl_Native_File_Chooser_FLTK.cxx')
-rw-r--r--src/lib/FL/Fl_Native_File_Chooser_FLTK.cxx339
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
34static int G_init = 0; // 'first time' initialize flag
35
36// CTOR
37Fl_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
57Fl_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
68void 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
74int 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
93void Fl_Native_File_Chooser::type(int val) {
94 _btype = val;
95 file_chooser->type(type_fl_file(val));
96}
97
98int Fl_Native_File_Chooser::type() const {
99 return(_btype);
100}
101
102// SET OPTIONS
103void Fl_Native_File_Chooser::options(int val) {
104 _options = val;
105}
106
107// GET OPTIONS
108int 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//
118int 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
181const char *Fl_Native_File_Chooser::errmsg() const {
182 return(_errmsg ? _errmsg : "No error");
183}
184
185// GET FILENAME
186const 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
192const 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//
200void 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//
207const 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//
214void Fl_Native_File_Chooser::filter(const char *val) {
215 _filter = strfree(_filter);
216 _filter = strnew(val);
217 parse_filter();
218}
219
220// GET FILTER
221const char *Fl_Native_File_Chooser::filter() const {
222 return(_filter);
223}
224
225// SET SELECTED FILTER
226void Fl_Native_File_Chooser::filter_value(int val) {
227 _filtvalue = val;
228}
229
230// RETURN SELECTED FILTER
231int Fl_Native_File_Chooser::filter_value() const {
232 return(_filtvalue);
233}
234
235// GET TOTAL FILENAMES CHOSEN
236int 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//
243void 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//
251const 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//
265void 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
331void 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
337const char* Fl_Native_File_Chooser::preset_file() const {
338 return(_preset_file);
339}