1 /*
2 * imgsav_dlg.c
3 *
4 * Code for the image save parameters dialog
5 *
6 * (C) 1997 Randall Hopper
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met: 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 2.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 */
29
30 /* ******************** Include Files ************** */
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include <X11/Intrinsic.h>
36 #include <X11/StringDefs.h>
37 #include <X11/Shell.h>
38 #include <X11/Xaw/AsciiText.h>
39 #include <X11/Xaw/Box.h>
40 #include <X11/Xaw/Command.h>
41 #include <X11/Xaw/Label.h>
42 #include <X11/Xaw/AsciiText.h>
43 #include <X11/Xaw/Form.h>
44 #include <X11/Xaw/MenuButton.h>
45 #include <X11/Xaw/SimpleMenu.h>
46 #include <X11/Xaw/SmeBSB.h>
47 #include <X11/Xaw/Toggle.h>
48 #include "tvdefines.h"
49 #include "glob.h"
50 #include "actions.h"
51 #include "xutil.h"
52 #include "imgsav_dlg.h"
53
54 /* ******************** Local defines ************** */
55
56 #define PIX_FNAME_SELECT "tickbox_on.xbm"
57 #define PIX_FNAME_UNSELECT "tickbox_off.xbm"
58
59 /* ******************** Private variables ************** */
60
61 static Widget Dialog_wgt = NULL,
62 Text_wgt = NULL,
63 Suffix_wgt = NULL,
64 Menu_btn = NULL;
65 /*
66 static Pixmap Select_pixmap = None,
67 Unselect_pixmap = None;
68 */
69
70 static TV_IFILEFMT_ITEM_DEF Fmtitem_def[] = {
71 { TV_STILL_FMT_TIFF , "tiff", "tiffCmd" },
72 { TV_STILL_FMT_PPM , "ppm" , "ppmCmd" }
73 };
74
75 #define FBTEXT_ACCEPT_ACTION "tv-freezefilebase-accept"
76
77 static void FileBaseTextAcceptAction( Widget, XEvent *, String *, Cardinal *);
78
79 static XtActionsRec Tool_actions[1] = {
80 { FBTEXT_ACCEPT_ACTION, FileBaseTextAcceptAction }
81 };
82
83 static char Filebase_text_transl[] = "\
84 <Key>Return: select-all() beginning-of-line() "FBTEXT_ACCEPT_ACTION"()\n\
85 <Key>KP_Enter: select-all() beginning-of-line() "FBTEXT_ACCEPT_ACTION"()\n\
86 <Key>Linefeed: select-all() beginning-of-line() "FBTEXT_ACCEPT_ACTION"()\n\
87 Ctrl<Key>J: select-all() beginning-of-line() "FBTEXT_ACCEPT_ACTION"()\n\
88 Ctrl<Key>M: select-all() beginning-of-line() "FBTEXT_ACCEPT_ACTION"()\n\
89 ";
90 /* ******************** Forward declarations ************** */
91 /* ******************** Function Definitions ************** */
92
93 #ifdef OLDSTUFF
94
LoadRadioPixmaps(void)95 static void LoadRadioPixmaps( void )
96 {
97 /* Load select/unselect pixmaps if we haven't already */
98 if ( Select_pixmap == None ) {
99 if ( !XUTILBitmapLoad( PIX_FNAME_SELECT, TVTOPLEVEL,
100 &Select_pixmap ) ) {
101 fprintf( stderr, "Can't load '%s' pixmap\n", PIX_FNAME_SELECT );
102 exit(1);
103 }
104 if ( !XUTILBitmapLoad( PIX_FNAME_UNSELECT, TVTOPLEVEL,
105 &Unselect_pixmap ) ) {
106 fprintf( stderr, "Can't load '%s' pixmap\n", PIX_FNAME_UNSELECT );
107 exit(1);
108 }
109 }
110 }
111
112 #endif
113
114
SetToggleState(Widget toggle_wgt,TV_BOOL state)115 static void SetToggleState( Widget toggle_wgt, TV_BOOL state )
116 {
117 /*Pixmap pix = state ? Select_pixmap : Unselect_pixmap;*/
118
119 /*LoadRadioPixmaps();*/
120
121 XtVaSetValues( toggle_wgt, /*XtNbitmap, pix,*/
122 XtNstate, state,
123 NULL);
124 }
125
126
127 /* OkCmdCB - Dismiss the dialog */
OkCmdCB(Widget w,XtPointer cl,XtPointer cb)128 static void OkCmdCB( Widget w, XtPointer cl, XtPointer cb )
129 {
130 TV_DISK *d = &G_glob.disk;
131 Boolean state;
132 String fn_base;
133 TV_BOOL ok = TRUE;
134 TV_INT32 i;
135 String fmt_label,
136 fmt_label2;
137
138 if ( Dialog_wgt == NULL )
139 return;
140
141 /* Grab values off dialog */
142
143 /* ...Filename base */
144 XtVaGetValues( Text_wgt, XtNstring, &fn_base,
145 NULL );
146 if ( fn_base == NULL )
147 fn_base = "";
148 if ( strlen( fn_base ) == 0 )
149 ok = FALSE;
150
151 d->fn_freeze_base[0] = '\0';
152 strncat( d->fn_freeze_base, fn_base, sizeof( d->fn_freeze_base ) - 1 );
153
154 /* ...Do Suffix Y/N */
155 XtVaGetValues( Suffix_wgt, XtNstate, &state,
156 NULL);
157 d->freeze_use_suffix = state;
158
159 /* ...File Format */
160 XtVaGetValues( Menu_btn, XtNlabel, &fmt_label,
161 NULL );
162 for ( i = 0; i < XtNumber( Fmtitem_def ); i++ ) {
163 XtVaGetValues( Fmtitem_def[i].wgt, XtNlabel, &fmt_label2,
164 NULL );
165 if ( strcmp( fmt_label, fmt_label2 ) == 0 )
166 break;
167 }
168 if ( i >= XtNumber( Fmtitem_def ) ) {
169 fprintf( stderr,
170 "TVIMGSAV:OkCmdCB: Format string not found '%s'\n",
171 fmt_label ? fmt_label : "" );
172 exit(1);
173 }
174 d->freeze_fmt = Fmtitem_def[i].fmt;
175
176 /* Reset suffix number */
177 d->freeze_next_suffix = 1;
178
179 /* Get rid of dialog */
180 XtPopdown( Dialog_wgt );
181
182 /* And save the image (or just beep if no filename) */
183 if ( ok )
184 TVActionSaveImage();
185 else
186 XBell( TVDISPLAY, 100 );
187 }
188
189
190 /* FileBaseTextAcceptAction - Action rtn to accept new Text wgt file base */
FileBaseTextAcceptAction(Widget wgt,XEvent * xevent,String * params,Cardinal * num_params)191 static void FileBaseTextAcceptAction(
192 Widget wgt,
193 XEvent *xevent,
194 String *params,
195 Cardinal *num_params )
196 {
197 /* Treat this as a dialog dismiss */
198 OkCmdCB( NULL, NULL, NULL );
199 }
200
TextValUpdate(Widget text_wgt,char * str)201 static void TextValUpdate( Widget text_wgt, char *str )
202 {
203 XawTextBlock tblk;
204 char *old_str;
205 int old_len;
206
207 assert( text_wgt != NULL );
208
209 memset( &tblk, '\0', sizeof( tblk ) );
210 tblk.firstPos = 0;
211 tblk.length = strlen( str );
212 tblk.ptr = str;
213 tblk.format = XawFmt8Bit;
214
215 XtVaGetValues( text_wgt, XtNstring, &old_str,
216 NULL );
217 old_len = (old_str == NULL) ? 0 : strlen( old_str );
218 XawTextReplace( text_wgt, 0, old_len, &tblk );
219 }
220
221 /* FmtMenuCB - Update menu button text */
FmtMenuItemCB(Widget w,XtPointer cl,XtPointer cb)222 static void FmtMenuItemCB( Widget w, XtPointer cl, XtPointer cb )
223 {
224 TV_INT32 i;
225 String label,
226 fn_base,
227 p;
228 char path[ MAXPATHLEN ];
229
230 for ( i = 0; i < XtNumber( Fmtitem_def ); i++ )
231 if ( Fmtitem_def[i].wgt == w )
232 break;
233 if ( i >= XtNumber( Fmtitem_def ) ) {
234 fprintf( stderr,
235 "TVIMGSAV:FmtMenuItemCB: Can't find widget\n" );
236 exit(1);
237 }
238
239 XtVaGetValues( Fmtitem_def[i].wgt, XtNlabel, &label,
240 NULL );
241 XtVaSetValues( Menu_btn, XtNlabel, label,
242 NULL );
243
244 /* Tweak the extension of the on-dialog filename, as a convenience */
245 XtVaGetValues( Text_wgt, XtNstring, &fn_base,
246 NULL );
247 if ( fn_base == NULL )
248 fn_base = "";
249 if ( (p = strrchr( fn_base, '/' )) == NULL )
250 p = fn_base;
251 if ( (p = strchr( p, '.' )) != NULL ) {
252 path[0] = '\0';
253 strncat( path, fn_base, MIN( sizeof(path)-1, p-fn_base+1 ) );
254 strncat( path, Fmtitem_def[i].file_ext,
255 sizeof(path)-1 - strlen(path) );
256 TextValUpdate( Text_wgt, path );
257 }
258 }
259
TVImgSavDialogBuild(Widget * dialog_wgt)260 static void TVImgSavDialogBuild( Widget *dialog_wgt )
261 {
262 Position x, y;
263 Dimension width;
264 Widget w, box, gbox, cbox, form, menu_shell;
265 TV_INT32 i;
266 XtTranslations transl;
267
268 /* Create the dialog widgets */
269 *dialog_wgt = XtVaCreatePopupShell( "imageSaveDialog",
270 transientShellWidgetClass, TVTOPLEVEL,
271 NULL );
272
273 box = XtVaCreateManagedWidget( "mainBox", boxWidgetClass, *dialog_wgt,
274 XtNorientation, XtorientVertical,
275 NULL );
276
277 gbox = XtVaCreateManagedWidget( "groupBox", boxWidgetClass, box,
278 XtNorientation, XtorientVertical,
279 NULL );
280
281 cbox = XtVaCreateManagedWidget( "fnameBox", boxWidgetClass, gbox,
282 XtNorientation, XtorientHorizontal,
283 NULL );
284
285 w = XtVaCreateManagedWidget( "fileBaseLabel", labelWidgetClass, cbox,
286 NULL );
287
288 Text_wgt = XtVaCreateManagedWidget( "fileBaseText", asciiTextWidgetClass,
289 cbox,
290 XtNtype , XawAsciiString,
291 XtNuseStringInPlace, False,
292 XtNscrollHorizontal, XawtextScrollNever,
293 XtNscrollVertical , XawtextScrollNever,
294 XtNdisplayCaret , False,
295 XtNeditType , XawtextEdit,
296 XtNresize , XawtextResizeNever,
297 NULL );
298
299 /* Text widget translation overrides */
300 XtAppAddActions( TVAPPCTX, Tool_actions, XtNumber( Tool_actions ) );
301 transl = XtParseTranslationTable( G_transl_ovr_ascii_text );
302 XtOverrideTranslations( Text_wgt, transl );
303 transl = XtParseTranslationTable( G_transl_ovr_ascii_text_1line );
304 XtOverrideTranslations( Text_wgt, transl );
305 transl = XtParseTranslationTable( Filebase_text_transl );
306 XtOverrideTranslations( Text_wgt, transl );
307
308 form = XtVaCreateManagedWidget( "suffixForm", formWidgetClass, gbox,
309 XtNorientation, XtorientHorizontal,
310 NULL );
311
312 w = XtVaCreateManagedWidget( "spacerLabel", labelWidgetClass, form,
313 XtNlabel, " ",
314 XtNresize, False,
315 XtNencoding, XawTextEncoding8bit,
316 XtNwidth, 70,
317 NULL );
318
319 Suffix_wgt = XtVaCreateManagedWidget( "suffixToggle", toggleWidgetClass,
320 form,
321 XtNfromHoriz, w,
322 XtNlabel, " ",
323 NULL );
324
325 w = XtVaCreateManagedWidget( "suffixLabel", labelWidgetClass, form,
326 XtNresize, False,
327 XtNfromHoriz, Suffix_wgt,
328 XtNencoding, XawTextEncoding8bit,
329 NULL );
330
331 cbox = XtVaCreateManagedWidget( "formatBox", boxWidgetClass, gbox,
332 XtNorientation, XtorientHorizontal,
333 NULL );
334
335
336 w = XtVaCreateManagedWidget( "spacerLabel", labelWidgetClass, cbox,
337 XtNlabel, " ",
338 XtNresize, False,
339 XtNencoding, XawTextEncoding8bit,
340 XtNwidth, 43,
341 NULL );
342
343 w = XtVaCreateManagedWidget( "formatLabel", labelWidgetClass, cbox,
344 XtNresize, False,
345 XtNencoding, XawTextEncoding8bit,
346 NULL );
347
348 w = XtVaCreateManagedWidget( "formatMenuBox", boxWidgetClass, cbox,
349 XtNorientation, XtorientHorizontal,
350 NULL );
351
352 Menu_btn = XtVaCreateManagedWidget( "formatMenu",
353 menuButtonWidgetClass, w,
354 XtNresize, XawtextResizeNever,
355 NULL );
356
357 menu_shell = XtVaCreatePopupShell( "menu",
358 simpleMenuWidgetClass, Menu_btn,
359 NULL );
360
361 /* Create all format items for this menu */
362 for ( i = 0; i < XtNumber( Fmtitem_def ); i++ ) {
363 Widget item;
364
365 item = XtVaCreateManagedWidget( Fmtitem_def[i].wgt_name,
366 smeBSBObjectClass,
367 menu_shell,
368 NULL );
369 Fmtitem_def[i].wgt = item;
370
371 XtAddCallback( item, XtNcallback, FmtMenuItemCB,
372 (XtPointer) Fmtitem_def[i].fmt );
373 }
374
375 form = XtVaCreateManagedWidget( "actionForm", formWidgetClass, box,
376 NULL );
377
378 w = XtVaCreateManagedWidget( "spacerLabel", labelWidgetClass, form,
379 XtNlabel, " ",
380 XtNresize, False,
381 XtNencoding, XawTextEncoding8bit,
382 XtNwidth, 54,
383 NULL );
384
385 w = XtVaCreateManagedWidget( "okCmd", commandWidgetClass, form,
386 XtNfromHoriz, w,
387 NULL );
388 XtAddCallback( w, XtNcallback, OkCmdCB, NULL );
389
390 /* By default, position dialog just to right of main TV window */
391 XtVaGetValues( TVTOPLEVEL, XtNwidth, &width,
392 NULL);
393
394 XtTranslateCoords( TVTOPLEVEL, width, 0, &x, &y );
395
396 XtVaSetValues( *dialog_wgt, XtNx, x,
397 XtNy, y,
398 NULL );
399 }
400
401
TVIMGSAVDIALOGPopUp()402 void TVIMGSAVDIALOGPopUp()
403 {
404 TV_DISPLAY *dpy = &G_glob.display;
405
406 /* If we don't have a frozen img to save, this is pointless */
407 if ( dpy->image.buf == NULL ) {
408 XUTILDialogPause( TVTOPLEVEL, "Error", "No frozen image to save.",
409 TV_DIALOG_TYPE_OK );
410 return;
411 }
412
413 /* Do dialog */
414 if ( Dialog_wgt == NULL )
415 TVImgSavDialogBuild( &Dialog_wgt );
416
417 TVIMGSAVDIALOGResync();
418
419 XUTILXtPopup( Dialog_wgt, XtGrabNonexclusive, TVTOPLEVEL );
420 }
421
TVIMGSAVDIALOGResync()422 void TVIMGSAVDIALOGResync()
423 {
424 TV_DISK *d = &G_glob.disk;
425 String label;
426 TV_INT32 i;
427
428 /* FIXME: Also install EnterNotify handler for this dialog to */
429 /* resync values on entry of it's shell. */
430
431 if ( Dialog_wgt == NULL )
432 return;
433
434 /* Set text field to current base filename */
435 TextValUpdate( Text_wgt, d->fn_freeze_base );
436
437 /* Set suffix toggle state */
438 SetToggleState( Suffix_wgt, d->freeze_use_suffix );
439
440 /* Set active format box label based on active still image format */
441 for ( i = 0; i < XtNumber( Fmtitem_def ); i++ )
442 if ( Fmtitem_def[i].fmt == d->freeze_fmt )
443 break;
444 if ( i >= XtNumber( Fmtitem_def ) ) {
445 fprintf( stderr,
446 "TVIMGSAVDIALOGResync: Unsupported fmt %d\n", d->freeze_fmt );
447 exit(1);
448 }
449
450 XtVaGetValues( Fmtitem_def[i].wgt, XtNlabel, &label,
451 NULL );
452 XtVaSetValues( Menu_btn, XtNlabel, label,
453 NULL );
454 }
455
456