Line data Source code
1 : /* Copyright (C) 2000-2012 by George Williams */
2 : /*
3 : * Redistribution and use in source and binary forms, with or without
4 : * modification, are permitted provided that the following conditions are met:
5 :
6 : * Redistributions of source code must retain the above copyright notice, this
7 : * list of conditions and the following disclaimer.
8 :
9 : * Redistributions in binary form must reproduce the above copyright notice,
10 : * this list of conditions and the following disclaimer in the documentation
11 : * and/or other materials provided with the distribution.
12 :
13 : * The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 :
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 : * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 : * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 : * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 : #include <stdlib.h>
28 : #include <string.h>
29 : #include "ustring.h"
30 : #include "gfile.h"
31 : #include "gdraw.h"
32 : #include "gwidget.h"
33 : #include "ggadget.h"
34 : #include "ggadgetP.h"
35 : #include "gio.h"
36 : #include "gicons.h"
37 :
38 : struct gfc_data {
39 : int done;
40 : unichar_t *ret;
41 : GGadget *gfc;
42 : };
43 :
44 0 : static void GFD_doesnt(GIOControl *gio) {
45 : /* The filename the user chose doesn't exist, so everything is happy */
46 0 : struct gfc_data *d = gio->userdata;
47 0 : d->done = true;
48 0 : GFileChooserReplaceIO(d->gfc,NULL);
49 0 : }
50 :
51 0 : static void GFD_exists(GIOControl *gio) {
52 : /* The filename the user chose exists, ask user if s/he wants to overwrite */
53 0 : struct gfc_data *d = gio->userdata;
54 :
55 0 : if ( !_ggadget_use_gettext ) {
56 : const unichar_t *rcb[3]; unichar_t rcmn[2];
57 : unichar_t buffer[200];
58 0 : rcb[2]=NULL;
59 0 : rcb[0] = GStringGetResource( _STR_Replace, &rcmn[0]);
60 0 : rcb[1] = GStringGetResource( _STR_Cancel, &rcmn[1]);
61 :
62 0 : u_strcpy(buffer, GStringGetResource(_STR_Fileexistspre,NULL));
63 0 : u_strcat(buffer, u_GFileNameTail(d->ret));
64 0 : u_strcat(buffer, GStringGetResource(_STR_Fileexistspost,NULL));
65 0 : if ( GWidgetAsk(GStringGetResource(_STR_Fileexists,NULL),rcb,rcmn,0,1,buffer)==0 ) {
66 0 : d->done = true;
67 : }
68 : } else {
69 : const char *rcb[3];
70 : char *temp;
71 0 : rcb[2]=NULL;
72 0 : rcb[0] = _("Replace");
73 0 : rcb[1] = _("Cancel");
74 :
75 0 : if ( GWidgetAsk8(_("File Exists"),rcb,0,1,_("File, %s, exists. Replace it?"),
76 0 : temp = u2utf8_copy(u_GFileNameTail(d->ret)))==0 ) {
77 0 : d->done = true;
78 : }
79 0 : free(temp);
80 : }
81 0 : GFileChooserReplaceIO(d->gfc,NULL);
82 0 : }
83 :
84 0 : static int GFD_SaveOk(GGadget *g, GEvent *e) {
85 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
86 0 : struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
87 : GGadget *tf;
88 0 : GFileChooserGetChildren(d->gfc,NULL,NULL,&tf);
89 0 : if ( *_GGadgetGetTitle(tf)!='\0' ) {
90 0 : d->ret = GGadgetGetTitle(d->gfc);
91 0 : GIOfileExists(GFileChooserReplaceIO(d->gfc,
92 0 : GIOCreate(d->ret,d,GFD_exists,GFD_doesnt)));
93 : }
94 : }
95 0 : return( true );
96 : }
97 :
98 0 : static int GFD_Cancel(GGadget *g, GEvent *e) {
99 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
100 0 : struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
101 0 : d->done = true;
102 : }
103 0 : return( true );
104 : }
105 :
106 0 : static void GFD_dircreated(GIOControl *gio) {
107 0 : struct gfc_data *d = gio->userdata;
108 0 : unichar_t *dir = u_copy(gio->path);
109 :
110 0 : GFileChooserReplaceIO(d->gfc,NULL);
111 0 : GFileChooserSetDir(d->gfc,dir);
112 0 : free(dir);
113 0 : }
114 :
115 0 : static void GFD_dircreatefailed(GIOControl *gio) {
116 : /* We couldn't create the directory */
117 0 : struct gfc_data *d = gio->userdata;
118 :
119 0 : if ( !_ggadget_use_gettext ) {
120 : unichar_t buffer[500];
121 : unichar_t title[30];
122 :
123 0 : u_strcpy(title, GStringGetResource(_STR_Couldntcreatedir,NULL));
124 0 : u_strcpy(buffer, title);
125 0 : uc_strcat(buffer,": ");
126 0 : u_strcat(buffer, u_GFileNameTail(gio->path));
127 0 : uc_strcat(buffer, ".\n");
128 0 : if ( gio->error!=NULL ) {
129 0 : u_strcat(buffer,gio->error);
130 0 : uc_strcat(buffer, "\n");
131 : }
132 0 : if ( gio->status[0]!='\0' )
133 0 : u_strcat(buffer,gio->status);
134 0 : GWidgetError(title,buffer);
135 : } else {
136 0 : char *t1=NULL, *t2=NULL;
137 0 : GWidgetError8(_("Couldn't create directory"),
138 0 : _("Couldn't create directory: %1$s\n%2$s\n%3$s"),
139 0 : gio->error!=NULL ? t1 = u2utf8_copy(gio->error) : "",
140 0 : t2 = u2utf8_copy(gio->status));
141 0 : free(t1); free(t2);
142 : }
143 :
144 0 : GFileChooserReplaceIO(d->gfc,NULL);
145 0 : }
146 :
147 0 : static int GFD_NewDir(GGadget *g, GEvent *e) {
148 0 : if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
149 0 : struct gfc_data *d = GDrawGetUserData(GGadgetGetWindow(g));
150 : unichar_t *newdir;
151 0 : if ( _ggadget_use_gettext ) {
152 : char *temp;
153 0 : temp = GWidgetAskString8(_("Create directory..."),NULL,_("Directory name?"));
154 0 : newdir = utf82u_copy(temp);
155 0 : free(temp);
156 : } else
157 0 : newdir = GWidgetAskStringR(_STR_Createdir,NULL,_STR_Dirname);
158 0 : if ( newdir==NULL )
159 0 : return( true );
160 0 : if ( !u_GFileIsAbsolute(newdir)) {
161 0 : unichar_t *temp = u_GFileAppendFile(GFileChooserGetDir(d->gfc),newdir,false);
162 0 : free(newdir);
163 0 : newdir = temp;
164 : }
165 0 : GIOmkDir(GFileChooserReplaceIO(d->gfc,
166 0 : GIOCreate(newdir,d,GFD_dircreated,GFD_dircreatefailed)));
167 0 : free(newdir);
168 : }
169 0 : return( true );
170 : }
171 :
172 0 : static int e_h(GWindow gw, GEvent *event) {
173 0 : if ( event->type==et_close ) {
174 0 : struct gfc_data *d = GDrawGetUserData(gw);
175 0 : d->done = true;
176 0 : } else if ( event->type == et_map ) {
177 : /* Above palettes */
178 0 : GDrawRaise(gw);
179 0 : } else if ( event->type == et_char ) {
180 0 : return( false );
181 0 : } else if ( event->type == et_mousemove ||
182 0 : (event->type==et_mousedown && event->u.mouse.button==3 )) {
183 0 : struct gfc_data *d = GDrawGetUserData(gw);
184 0 : GFileChooserPopupCheck(d->gfc,event);
185 0 : } else if (( event->type==et_mouseup || event->type==et_mousedown ) &&
186 0 : (event->u.mouse.button>=4 && event->u.mouse.button<=7) ) {
187 0 : struct gfc_data *d = GDrawGetUserData(gw);
188 0 : return( GGadgetDispatchEvent((GGadget *) (d->gfc),event));
189 : }
190 0 : return( true );
191 : }
192 :
193 0 : unichar_t *GWidgetSaveAsFileWithGadget(const unichar_t *title, const unichar_t *defaultfile,
194 : const unichar_t *initial_filter, unichar_t **mimetypes,
195 : GFileChooserFilterType filter,
196 : GFileChooserInputFilenameFuncType filenamefunc,
197 : GGadgetCreateData *optional_gcd) {
198 : GRect pos;
199 : GWindow gw;
200 : GWindowAttrs wattrs;
201 : GGadgetCreateData gcd[7], boxes[3], *varray[7], *harray[10];
202 : GTextInfo label[5];
203 : struct gfc_data d;
204 : GGadget *pulldown, *files, *tf;
205 0 : int bs = GIntGetResource(_NUM_Buttonsize), bsbigger, totwid;
206 : int vi;
207 :
208 0 : GProgressPauseTimer();
209 0 : memset(&wattrs,0,sizeof(wattrs));
210 0 : wattrs.mask = wam_events|wam_cursor|wam_wtitle|wam_undercursor|wam_restrict|wam_isdlg;
211 0 : wattrs.event_masks = ~(1<<et_charup);
212 0 : wattrs.restrict_input_to_me = 1;
213 0 : wattrs.is_dlg = 1;
214 0 : wattrs.undercursor = 1;
215 0 : wattrs.cursor = ct_pointer;
216 0 : wattrs.window_title = (unichar_t *) title;
217 0 : pos.x = pos.y = 0;
218 0 : totwid = GGadgetScale(223);
219 0 : bsbigger = 3*bs+4*14>totwid; totwid = bsbigger?3*bs+4*12:totwid;
220 0 : pos.width = GDrawPointsToPixels(NULL,totwid);
221 0 : pos.height = GDrawPointsToPixels(NULL,255);
222 0 : gw = GDrawCreateTopWindow(NULL,&pos,e_h,&d,&wattrs);
223 :
224 0 : memset(&label,0,sizeof(label));
225 0 : memset(&gcd,0,sizeof(gcd));
226 0 : memset(&boxes,0,sizeof(boxes));
227 0 : gcd[0].gd.pos.x = 12; gcd[0].gd.pos.y = 6;
228 0 : gcd[0].gd.pos.width = 223-24; gcd[0].gd.pos.height = 180;
229 0 : gcd[0].gd.flags = gg_visible | gg_enabled;
230 0 : gcd[0].gd.cid = 1000;
231 0 : gcd[0].creator = GFileChooserCreate;
232 0 : varray[0] = &gcd[0]; varray[1] = NULL; vi=2;
233 :
234 0 : if ( optional_gcd!=NULL ) {
235 0 : varray[vi++] = optional_gcd; varray[vi++] = NULL;
236 : }
237 :
238 0 : gcd[1].gd.pos.x = 12; gcd[1].gd.pos.y = 222-3;
239 0 : gcd[1].gd.pos.width = -1;
240 0 : gcd[1].gd.flags = gg_visible | gg_enabled | gg_but_default;
241 0 : if ( _ggadget_use_gettext ) {
242 0 : label[1].text = (unichar_t *) _("_Save");
243 0 : label[1].text_is_1byte = true;
244 : } else
245 0 : label[1].text = (unichar_t *) _STR_Save;
246 0 : label[1].text_in_resource = true;
247 0 : gcd[1].gd.mnemonic = 'S';
248 0 : gcd[1].gd.label = &label[1];
249 0 : gcd[1].gd.handle_controlevent = GFD_SaveOk;
250 0 : gcd[1].creator = GButtonCreate;
251 0 : harray[0] = GCD_Glue; harray[1] = &gcd[1];
252 :
253 0 : gcd[2].gd.pos.x = (totwid-bs)*100/GIntGetResource(_NUM_ScaleFactor)/2; gcd[2].gd.pos.y = 222;
254 0 : gcd[2].gd.pos.width = -1;
255 0 : gcd[2].gd.flags = gg_visible | gg_enabled;
256 0 : if ( _ggadget_use_gettext ) {
257 0 : label[2].text = (unichar_t *) _("_Filter");
258 0 : label[2].text_is_1byte = true;
259 : } else
260 0 : label[2].text = (unichar_t *) _STR_Filter;
261 0 : label[2].text_in_resource = true;
262 0 : gcd[2].gd.mnemonic = 'F';
263 0 : gcd[2].gd.label = &label[2];
264 0 : gcd[2].gd.handle_controlevent = GFileChooserFilterEh;
265 0 : gcd[2].creator = GButtonCreate;
266 0 : harray[2] = GCD_Glue; harray[3] = &gcd[2];
267 :
268 0 : gcd[3].gd.pos.x = gcd[2].gd.pos.x; gcd[3].gd.pos.y = 192;
269 0 : gcd[3].gd.pos.width = -1;
270 0 : gcd[3].gd.flags = gg_visible | gg_enabled;
271 0 : if ( _ggadget_use_gettext ) {
272 0 : label[3].text = (unichar_t *) S_("Directory|_New");
273 0 : label[3].text_is_1byte = true;
274 : } else
275 0 : label[3].text = (unichar_t *) _STR_New;
276 0 : label[3].text_in_resource = true;
277 0 : label[3].image = &_GIcon_dir;
278 0 : label[3].image_precedes = false;
279 0 : gcd[3].gd.mnemonic = 'N';
280 0 : gcd[3].gd.label = &label[3];
281 0 : gcd[3].gd.handle_controlevent = GFD_NewDir;
282 0 : gcd[3].creator = GButtonCreate;
283 0 : harray[4] = GCD_Glue; harray[5] = &gcd[3];
284 :
285 0 : gcd[4].gd.pos.x = -gcd[1].gd.pos.x; gcd[4].gd.pos.y = 222;
286 0 : gcd[4].gd.pos.width = -1;
287 0 : gcd[4].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
288 0 : if ( _ggadget_use_gettext ) {
289 0 : label[4].text = (unichar_t *) _("_Cancel");
290 0 : label[4].text_is_1byte = true;
291 : } else
292 0 : label[4].text = (unichar_t *) _STR_Cancel;
293 0 : label[4].text_in_resource = true;
294 0 : gcd[4].gd.label = &label[4];
295 0 : gcd[4].gd.mnemonic = 'C';
296 0 : gcd[4].gd.handle_controlevent = GFD_Cancel;
297 0 : gcd[4].creator = GButtonCreate;
298 0 : harray[6] = GCD_Glue; harray[7] = &gcd[4]; harray[8] = GCD_Glue; harray[9] = NULL;
299 :
300 0 : boxes[2].gd.flags = gg_visible | gg_enabled;
301 0 : boxes[2].gd.u.boxelements = harray;
302 0 : boxes[2].creator = GHBoxCreate;
303 0 : varray[vi++] = &boxes[2]; varray[vi++] = NULL;
304 0 : varray[vi++] = NULL;
305 :
306 0 : boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
307 0 : boxes[0].gd.flags = gg_visible | gg_enabled;
308 0 : boxes[0].gd.u.boxelements = varray;
309 0 : boxes[0].creator = GHVGroupCreate;
310 :
311 0 : gcd[5].gd.pos.x = 2; gcd[5].gd.pos.y = 2;
312 0 : gcd[5].gd.pos.width = pos.width-4; gcd[5].gd.pos.height = pos.height-4;
313 0 : gcd[5].gd.flags = gg_enabled | gg_visible | gg_pos_in_pixels;
314 0 : gcd[5].creator = GGroupCreate;
315 :
316 0 : GGadgetsCreate(gw,boxes);
317 0 : GGadgetSetUserData(gcd[2].ret,gcd[0].ret);
318 0 : GHVBoxSetExpandableRow(boxes[0].ret,0);
319 0 : GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);
320 0 : GHVBoxFitWindow(boxes[0].ret);
321 :
322 0 : GFileChooserConnectButtons(gcd[0].ret,gcd[1].ret,gcd[2].ret);
323 0 : GFileChooserSetFilterText(gcd[0].ret,initial_filter);
324 0 : GFileChooserSetFilterFunc(gcd[0].ret,filter);
325 0 : GFileChooserSetInputFilenameFunc(gcd[0].ret, filenamefunc);
326 0 : GFileChooserSetMimetypes(gcd[0].ret,mimetypes);
327 0 : GFileChooserSetFilename(gcd[0].ret,defaultfile);
328 : // GGadgetSetTitle(gcd[0].ret,defaultfile);
329 0 : GFileChooserGetChildren(gcd[0].ret,&pulldown,&files,&tf);
330 0 : GWidgetIndicateFocusGadget(tf);
331 :
332 0 : memset(&d,'\0',sizeof(d));
333 0 : d.gfc = gcd[0].ret;
334 :
335 :
336 0 : GWidgetHidePalettes();
337 0 : GDrawSetVisible(gw,true);
338 0 : while ( !d.done )
339 0 : GDrawProcessOneEvent(NULL);
340 0 : GDrawDestroyWindow(gw);
341 0 : GProgressResumeTimer();
342 0 : return(d.ret);
343 : }
344 :
345 0 : unichar_t *GWidgetSaveAsFile(const unichar_t *title, const unichar_t *defaultfile,
346 : const unichar_t *initial_filter, unichar_t **mimetypes,
347 : GFileChooserFilterType filter) {
348 0 : return( GWidgetSaveAsFileWithGadget(title,defaultfile,initial_filter,mimetypes,
349 : filter, NULL, NULL ));
350 : }
351 :
352 0 : char *GWidgetSaveAsFileWithGadget8(const char *title, const char *defaultfile,
353 : const char *initial_filter, char **mimetypes,
354 : GFileChooserFilterType filter,
355 : GFileChooserInputFilenameFuncType filenamefunc,
356 : GGadgetCreateData *optional_gcd) {
357 0 : unichar_t *tit=NULL, *def=NULL, *filt=NULL, **mimes=NULL, *ret;
358 : char *utf8_ret;
359 : int i;
360 :
361 0 : if ( title!=NULL )
362 0 : tit = utf82u_copy(title);
363 0 : if ( defaultfile!=NULL )
364 0 : def = utf82u_copy(defaultfile);
365 0 : if ( initial_filter!=NULL )
366 0 : filt = utf82u_copy(initial_filter);
367 0 : if ( mimetypes!=NULL ) {
368 0 : for ( i=0; mimetypes[i]!=NULL; ++i );
369 0 : mimes = malloc((i+1)*sizeof(unichar_t *));
370 0 : for ( i=0; mimetypes[i]!=NULL; ++i )
371 0 : mimes[i] = utf82u_copy(mimetypes[i]);
372 0 : mimes[i] = NULL;
373 : }
374 0 : ret = GWidgetSaveAsFileWithGadget(tit,def,filt,mimes,filter,filenamefunc,optional_gcd);
375 0 : if ( mimes!=NULL ) {
376 0 : for ( i=0; mimes[i]!=NULL; ++i )
377 0 : free(mimes[i]);
378 0 : free(mimes);
379 : }
380 0 : free(filt); free(def); free(tit);
381 0 : utf8_ret = u2utf8_copy(ret);
382 0 : free(ret);
383 0 : return( utf8_ret );
384 : }
385 :
386 0 : char *GWidgetSaveAsFile8(const char *title, const char *defaultfile,
387 : const char *initial_filter, char **mimetypes,
388 : GFileChooserFilterType filter) {
389 0 : return( GWidgetSaveAsFileWithGadget8(title,defaultfile,initial_filter,mimetypes,
390 : filter, NULL, NULL ));
391 : }
|