1 /*----------------------------------------------------------------------------
2 --
3 --  Module:           xitFileSel
4 --
5 --  Project:          Xtools
6 --  System:           <>
7 --    Subsystem:      <>
8 --    Function block: <>
9 --
10 --  Description:
11 --    Display a file selection dialog and let the user select a file.
12 --
13 --  Filename:         xitFileSel.c
14 --
15 --  Authors:          Roger Larsson, Ulrika Bornetun
16 --  Creation date:    1992-05-18
17 --
18 --
19 --  (C) Copyright Ulrika Bornetun, Roger Larsson (1995)
20 --      All rights reserved
21 --
22 --  Permission to use, copy, modify, and distribute this software and its
23 --  documentation for any purpose and without fee is hereby granted,
24 --  provided that the above copyright notice appear in all copies. Ulrika
25 --  Bornetun and Roger Larsson make no representations about the usability
26 --  of this software for any purpose. It is provided "as is" without express
27 --  or implied warranty.
28 ----------------------------------------------------------------------------*/
29 
30 /* SCCS module identifier. */
31 static char SCCSID[] = "@(#) Module: xitFileSel.c, Version: 1.1, Date: 95/02/18 15:10:31";
32 
33 
34 /*----------------------------------------------------------------------------
35 --  Include files
36 ----------------------------------------------------------------------------*/
37 
38 #include <stdio.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 
44 #include <X11/Intrinsic.h>
45 
46 #include <Xm/Xm.h>
47 #include <Xm/FileSB.h>
48 
49 #include "System.h"
50 
51 #include "xitError.h"
52 #include "xitTools.h"
53 
54 
55 /*----------------------------------------------------------------------------
56 --  Macro definitions
57 ----------------------------------------------------------------------------*/
58 
59 
60 /*----------------------------------------------------------------------------
61 --  Type declarations
62 ----------------------------------------------------------------------------*/
63 
64 /* Internal data to use. */
65 typedef struct {
66 
67   /* Flags. */
68   UINT32  flags;
69 
70   /* Messages to use. */
71   char  *no_file_sel_msg;
72   char  *cannot_read_file_msg;
73 
74   /* The file selection window. */
75   Widget  mainW;
76 
77   /* User data and use callback. */
78   XIT_FILE_SEL_CB  actionCB;
79   void             *user_data;
80 
81 } SELECT_INFO, *SELECT_INFO_REF;
82 
83 
84 /*----------------------------------------------------------------------------
85 --  Global definitions
86 ----------------------------------------------------------------------------*/
87 
88 /* Name of module. */
89 static char  *module_name = "xitFileSel";
90 
91 
92 /*----------------------------------------------------------------------------
93 --  Function prototypes
94 ----------------------------------------------------------------------------*/
95 
96 static void
97   cancelCB( Widget           widget,
98             SELECT_INFO_REF  sel_ref,
99             XtPointer        call_data );
100 
101 static void
102   destroyCB( Widget           widget,
103              SELECT_INFO_REF  sel_ref,
104              XtPointer        call_data );
105 
106 static void
107   okCB( Widget                            widget,
108         SELECT_INFO_REF                   sel_ref,
109         XmFileSelectionBoxCallbackStruct  *call_data );
110 
111 
112 
113 /*----------------------------------------------------------------------------
114 --  Functions
115 ----------------------------------------------------------------------------*/
116 
117 Widget
xitCreateFileSelect(Widget parent,char * name,UINT32 flags,char * source_dir,XIT_FILE_SEL_LABELS * labels,XIT_FILE_SEL_CB actionCB,void * user_data)118   xitCreateFileSelect( Widget               parent,
119                        char                 *name,
120                        UINT32               flags,
121                        char                 *source_dir,
122                        XIT_FILE_SEL_LABELS  *labels,
123                        XIT_FILE_SEL_CB      actionCB,
124                        void                 *user_data )
125 {
126 
127   /* Variables. */
128   Arg              args[ 10 ];
129   Cardinal         n;
130   Widget           fileSelW;
131   Widget           tempW;
132   XmString         xstr;
133   SELECT_INFO_REF  sel_ref;
134 
135 
136   /* Code. */
137 
138   /* Only directories? */
139   if( flagIsSet( flags, XIT_FILE_SELECT_ONLY_DIRS ) )
140     flagSet( flags, XIT_FILE_SELECT_DIRS_OK );
141 
142 
143   n = 0;
144 
145   /* This window is always deleted. */
146   XtSetArg( args[ n ], XmNdeleteResponse, XmDESTROY ); n++;
147 
148   /* Create and initialize our private data. */
149   sel_ref = SysNew( SELECT_INFO );
150   if( sel_ref == NULL )
151     return( NULL );
152 
153   sel_ref -> flags                = flags;
154   sel_ref -> no_file_sel_msg      = labels -> no_file_sel_msg;
155   sel_ref -> cannot_read_file_msg = labels -> cannot_read_file_msg;
156 
157   sel_ref -> actionCB  = actionCB;
158   sel_ref -> user_data = user_data;
159 
160 
161   /* Create the file selection dialog. */
162   fileSelW = XmCreateFileSelectionDialog( parent, name, args, n );
163 
164   sel_ref -> mainW = fileSelW;
165 
166   XtAddCallback( fileSelW, XmNokCallback,
167                  (XtCallbackProc) okCB, (XtPointer) sel_ref );
168   XtAddCallback( fileSelW, XmNcancelCallback,
169                  (XtCallbackProc) cancelCB, (XtPointer) sel_ref );
170   XtAddCallback( fileSelW, XmNdestroyCallback,
171                  (XtCallbackProc) destroyCB, (XtPointer) sel_ref );
172 
173 
174   /* The labels. */
175   if( strlen( labels -> filter_label ) > 0 ) {
176     xstr = XmStringCreate( labels -> filter_label, CS );
177 
178     XtSetArg( args[ 0 ], XmNfilterLabelString, xstr );
179     XtSetValues( fileSelW, args, 1 );
180 
181     XmStringFree( xstr );
182   }
183 
184   if( strlen( labels -> dir_list_label ) > 0 ) {
185     xstr = XmStringCreate( labels -> dir_list_label, CS );
186 
187     XtSetArg( args[ 0 ], XmNdirListLabelString, xstr );
188     XtSetValues( fileSelW, args, 1 );
189 
190     XmStringFree( xstr );
191   }
192 
193   if( strlen( labels -> file_list_label ) > 0 ) {
194     xstr = XmStringCreate( labels -> file_list_label, CS );
195 
196     XtSetArg( args[ 0 ], XmNfileListLabelString, xstr );
197     XtSetValues( fileSelW, args, 1 );
198 
199     XmStringFree( xstr );
200   }
201 
202   if( strlen( labels -> selection_label ) > 0 ) {
203     xstr = XmStringCreate( labels -> selection_label, CS );
204 
205     XtSetArg( args[ 0 ], XmNselectionLabelString, xstr );
206     XtSetValues( fileSelW, args, 1 );
207 
208     XmStringFree( xstr );
209   }
210 
211   /* The action buttons. */
212   if( strlen( labels -> ok_button ) > 0 ) {
213     xstr = XmStringCreate( labels -> ok_button, CS );
214 
215     XtSetArg( args[ 0 ], XmNokLabelString, xstr );
216     XtSetValues( fileSelW, args, 1 );
217 
218     XmStringFree( xstr );
219   }
220 
221   if( strlen( labels -> filter_button ) > 0 ) {
222     xstr = XmStringCreate( labels -> filter_button, CS );
223 
224     XtSetArg( args[ 0 ], XmNapplyLabelString, xstr );
225     XtSetValues( fileSelW, args, 1 );
226 
227     XmStringFree( xstr );
228   }
229 
230   if( strlen( labels -> cancel_button ) > 0 ) {
231     xstr = XmStringCreate( labels -> cancel_button, CS );
232 
233     XtSetArg( args[ 0 ], XmNcancelLabelString, xstr );
234     XtSetValues( fileSelW, args, 1 );
235 
236     XmStringFree( xstr );
237   }
238 
239 
240   /* We don't use the Help button. */
241   tempW = XmFileSelectionBoxGetChild( fileSelW, XmDIALOG_HELP_BUTTON );
242   XtUnmanageChild( tempW );
243 
244 
245   /* No title. */
246   n = 0;
247   XtSetArg( args[ n ], XmNtitle, " " ); n++;
248   XtSetValues( XtParent( fileSelW ), args, n );
249 
250 
251   return( fileSelW );
252 
253 } /* xitCreateFileSelect */
254 
255 
256 /*----------------------------------------------------------------------*/
257 
258 void
xitFileSelectDisplay(Widget widget)259   xitFileSelectDisplay( Widget  widget )
260 {
261 
262   /* Code. */
263 
264   if( widget == NULL )
265     return;
266 
267 
268   /* Make sure the file selection window is visable. */
269   XtManageChild( widget );
270 
271   XtPopup( XtParent( widget ), XtGrabNone );
272 
273   XRaiseWindow( XtDisplay( widget ), XtWindow( widget ) );
274   XtMapWidget(  widget );
275 
276 
277   return;
278 
279 } /* xitFileSelectDisplay */
280 
281 
282 /*----------------------------------------------------------------------*/
283 
284 static void
cancelCB(Widget widget,SELECT_INFO_REF sel_ref,XtPointer call_data)285   cancelCB( Widget           widget,
286             SELECT_INFO_REF  sel_ref,
287             XtPointer        call_data )
288 {
289 
290   /* Code. */
291 
292   /* User callback? */
293   if( sel_ref -> actionCB != NULL )
294     (* sel_ref -> actionCB)( XIT_FILE_SELECT_CANCEL, NULL,
295                              sel_ref -> user_data );
296 
297   /* Remove the window. */
298   XtUnmanageChild( sel_ref -> mainW );
299 
300 
301   return;
302 
303 } /* cancelCB */
304 
305 
306 /*----------------------------------------------------------------------*/
307 
308 static void
destroyCB(Widget widget,SELECT_INFO_REF sel_ref,XtPointer call_data)309   destroyCB( Widget           widget,
310              SELECT_INFO_REF  sel_ref,
311              XtPointer        call_data )
312 {
313 
314   /* Code. */
315 
316   /* Free the internal data. */
317   if( sel_ref != NULL )
318     SysFree( sel_ref );
319 
320 
321   return;
322 
323 } /* destroyCB */
324 
325 
326 /*----------------------------------------------------------------------*/
327 
328 static void
okCB(Widget widget,SELECT_INFO_REF sel_ref,XmFileSelectionBoxCallbackStruct * call_data)329   okCB( Widget                            widget,
330         SELECT_INFO_REF                   sel_ref,
331         XmFileSelectionBoxCallbackStruct  *call_data )
332 {
333 
334   /* Variables. */
335   int          status;
336   char         *file_name;
337   struct stat  file_info;
338 
339 
340   /* Code. */
341 
342   /* The selected file name. */
343   file_name = xitStringGetString( call_data -> value, CS );
344 
345 
346   /* Only directory? */
347   if( flagIsSet( sel_ref -> flags, XIT_FILE_SELECT_ONLY_DIRS ) ) {
348     SysFree( file_name );
349 
350     file_name = xitStringGetString( call_data -> dir, CS );
351   }
352 
353 
354   /* No file selected? */
355   if( file_name == NULL || *file_name == '\0' ) {
356     xitErMessage( sel_ref -> mainW, XIT_ER_ERROR,
357                   module_name, "okCB",
358                   sel_ref -> no_file_sel_msg );
359 
360     SysFree( file_name );
361     return;
362   }
363 
364   /* Is the file a normal file and can it be read? */
365   status = stat( file_name, &file_info );
366 
367   if( status != 0 ) {
368     xitErMessage( sel_ref -> mainW, XIT_ER_ERROR,
369                   module_name, "okCB",
370                   sel_ref -> cannot_read_file_msg );
371 
372     SysFree( file_name );
373     return;
374   }
375 
376   if( S_ISDIR( file_info.st_mode ) &&
377       flagIsClear( sel_ref -> flags, XIT_FILE_SELECT_DIRS_OK ) ) {
378     xitErMessage( sel_ref -> mainW, XIT_ER_ERROR,
379                   module_name, "okCB",
380                   sel_ref -> cannot_read_file_msg );
381 
382     SysFree( file_name );
383     return;
384   }
385 
386 
387   status = access( file_name, (F_OK | R_OK) );
388 
389   if( status != 0 ) {
390     xitErMessage( sel_ref -> mainW, XIT_ER_ERROR,
391                   module_name, "okCB",
392                   sel_ref -> cannot_read_file_msg );
393 
394     SysFree( file_name );
395     return;
396   }
397 
398 
399   /* User callback? */
400   if( sel_ref -> actionCB != NULL )
401     (* sel_ref -> actionCB)( XIT_FILE_SELECT_OK, file_name,
402                              sel_ref -> user_data );
403 
404 
405   /* Remove the window. */
406   XtUnmanageChild( sel_ref -> mainW );
407 
408   SysFree( file_name );
409 
410 
411   return;
412 
413 } /* okCB */
414