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