home *** CD-ROM | disk | FTP | other *** search
- /*
- * fchooser.c : Xarchie interface to the FileChooser
- *
- * The FileChooser enforces very little policy. This wrapper adds
- * the following:
- * - The FileChooser is created with several other widgets: a Text
- * widget, and OK button, and a cancel button. These are created in
- * the sameparent, but other widgets can also be there.
- * - Selecting a file in the FileChooser just puts the string in the
- * Text widget. You have to hit Ok to use it.
- * - When ok is clicked or Return typed, the directory from the fileChooser
- * and the file from the Text are concatenated. If the result is a
- * directory, the fileChooser is reset to that directory. Otherwise
- * the callback is called with the filename as call_data.
- * - Leading tildes are expanded in directories entered in the Text widget.
- *
- * Oh yeah, if FILECHOOSER is not defined, ignore all that about it. In that
- * case we just have a Text and two buttons.
- *
- * George Ferguson, ferguson@cs.rochester.edu, 23 Apr 1993.
- *
- */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <X11/Intrinsic.h>
- #include <X11/StringDefs.h>
- #include <X11/keysym.h>
- #include <X11/Xaw/Form.h>
- #include <X11/Xaw/Label.h>
- #include <X11/Xaw/AsciiText.h>
- #include <X11/Xaw/Command.h>
- #ifdef FILECHOOSER
- #include <FChooser.h>
- #endif
- #include "fchooser.h"
- #include "xarchie.h"
- #include "xutil.h"
- #include "tilde.h"
- #include "status.h"
- #include "alert.h"
- #include "debug.h"
-
- /*
- * Functions defined here:
- */
- FileChooserInfo *createFileChooser(
- #if NeedFunctionPrototypes
- Widget shell,
- Widget parent,
- char *basename,
- FileChooserOkProc okCallback,
- FileChooserCancelProc cancelCallback,
- XtPointer client_data
- #endif
- );
-
- static void fileChooserCallback(),okButtonCallback(),cancelButtonCallback();
- static void keyPressEventHandler(),nonmaskableEventHandler();
-
- /* - - - - - - - - */
-
- FileChooserInfo *
- createFileChooser(shell,parent,basename,okCallback,cancelCallback,client_data)
- Widget shell,parent;
- char *basename;
- FileChooserOkProc okCallback;
- FileChooserCancelProc cancelCallback;
- XtPointer client_data;
- {
- FileChooserInfo *info;
- char name[64];
- Arg args[1];
-
- info = XtNew(FileChooserInfo);
- info->shell = shell;
- info->okCallback = okCallback;
- info->cancelCallback = cancelCallback;
- info->client_data = client_data;
- #ifdef FILECHOOSER
- status0("Initializing File Selector...");
- sprintf(name,"%sFileChooser",basename);
- info->fcw =
- XtCreateManagedWidget(name,xfwfFileChooserWidgetClass,parent,NULL,0);
- XtAddCallback(info->fcw,XtNcallback,fileChooserCallback,(XtPointer)info);
- status0("Done.");
- XtSetArg(args[0],XtNfromVert,info->fcw);
- #else
- XtSetArg(args[0],XtNfromVert,NULL);
- #endif
- sprintf(name,"%sTextLabel",basename);
- (void)XtCreateManagedWidget(name,labelWidgetClass,parent,args,1);
- sprintf(name,"%sText",basename);
- info->text =
- XtCreateManagedWidget(name,asciiTextWidgetClass,parent,args,1);
- sprintf(name,"%sOkButton",basename);
- info->okButton =
- XtCreateManagedWidget(name,commandWidgetClass,parent,NULL,0);
- XtAddCallback(info->okButton,XtNcallback,okButtonCallback,(XtPointer)info);
- /* Allow Return in the Text to be Ok */
- XtAddEventHandler(info->text,KeyPressMask,False,
- keyPressEventHandler,(XtPointer)info);
- sprintf(name,"%sCancelButton",basename);
- info->cancelButton =
- XtCreateManagedWidget(name,commandWidgetClass,parent,NULL,0);
- XtAddCallback(info->cancelButton,XtNcallback,
- cancelButtonCallback,(XtPointer)info);
- /* Allow WM_DELETE_WINDOW to the Shell to be Cancel */
- if (info->shell != NULL)
- XtAddEventHandler(info->shell,NoEventMask,True,
- nonmaskableEventHandler,(XtPointer)info);
- return(info);
- }
-
- /*
- * When a selection is made, put the string in the Text item. If background
- * selected, clear the Text item.
- */
- /*ARGSUSED*/
- static void
- fileChooserCallback(w,client_data,call_data)
- Widget w;
- XtPointer client_data; /* info */
- XtPointer call_data; /* return struct */
- {
- FileChooserInfo *fcinfo = (FileChooserInfo *)client_data;
- XfwfFileChooserReturnStruct *ret =
- (XfwfFileChooserReturnStruct *)call_data;
- Arg args[1];
-
- DEBUG1("fileChooserCallback: fcinfo=0x%lx\n",fcinfo);
- if (fcinfo == NULL || fcinfo->text == NULL) /* creating */
- return;
- if (ret->file == NULL) {
- XtSetArg(args[0],XtNstring,"");
- } else {
- XtSetArg(args[0],XtNstring,ret->file);
- }
- XtSetValues(fcinfo->text,args,1);
- DEBUG0("fileChooserCallback: done\n");
- }
-
- /*
- * If Ok is clicked, get the directory from the FileChooser (if FILECHOOSER)
- * and get the filename from the Text. Do tilde expansion. If result is
- * a directory, use it in the FileChooser, otherwise invoke the callback
- * passing filename and client_data. Finally free the info.
- */
- /*ARGSUSED*/
- static void
- okButtonCallback(w,client_data,call_data)
- Widget w;
- XtPointer client_data; /* info */
- XtPointer call_data; /* not used */
- {
- FileChooserInfo *fcinfo = (FileChooserInfo *)client_data;
- static char filename[MAXPATHLEN];
- struct stat statbuf;
- char *dir,*file;
-
- DEBUG1("okButtonCallback: fcinfo=0x%lx\n",fcinfo);
- filename[0] = '\0';
- #ifdef FILECHOOSER
- dir = XfwfFileChooserCurrentDirectory((XfwfFileChooserWidget)(fcinfo->fcw));
- DEBUG1("okButtonCallback: dir=\"%s\"\n",dir);
- #endif
- file = getWidgetString(fcinfo->text);
- if (file == NULL || *file == '\0') {
- alert0("No filename specified!");
- return;
- }
- DEBUG1("okButtonCallback: file=\"%s\"\n",file);
- if (*file == '/') { /* absolute path */
- strcpy(filename,file);
- } else if (*file == '~') { /* tilde path */
- strcpy(filename,tildeExpand(file));
- } else { /* relative to fcw */
- sprintf(filename,"%s%s",dir,file);
- }
- DEBUG1("okButtonCallback: filename=\"%s\"\n",filename);
- #ifdef FILECHOOSER
- /* If we got a directory, go open it rather than use it */
- if (stat(filename,&statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
- XfwfFileChooserChangeDirectory((XfwfFileChooserWidget)fcinfo->fcw,
- filename);
- return;
- }
- #endif
- if (fcinfo->okCallback != NULL) {
- DEBUG0("okButtonCallback: calling okCallback...\n");
- (*(fcinfo->okCallback))(fcinfo,filename,fcinfo->client_data);
- }
- DEBUG0("okButtonCallback: done\n");
- }
-
- /*
- * If Cancel is clicked, invoke the callback passing client_data.
- * Finally free the info.
- */
- /*ARGSUSED*/
- static void
- cancelButtonCallback(w,client_data,call_data)
- Widget w;
- XtPointer client_data; /* fcinfo */
- XtPointer call_data; /* not used */
- {
- FileChooserInfo *fcinfo = (FileChooserInfo *)client_data;
-
- DEBUG1("cancelButtonCallback: fcinfo=0x%lx\n",fcinfo);
- if (fcinfo->cancelCallback != NULL) {
- DEBUG0("cancelButtonCallback: calling cancelCallback\n");
- (*(fcinfo->cancelCallback))(fcinfo,fcinfo->client_data);
- }
- DEBUG0("cancelButtonCallback: done\n");
- }
-
- /*
- * KeyPress event handler for Text item: When Return is typed, act as if
- * OK had been clicked. If this event isn't Return, just let it be
- * dispatched normally.
- */
- static void
- keyPressEventHandler(w,client_data,event,continue_to_dispatch)
- Widget w;
- XtPointer client_data;
- XEvent *event;
- Boolean *continue_to_dispatch;
- {
- KeySym keysym;
- char str[8];
-
- DEBUG1("keyPressHandler: w=0x%x\n",w);
- (void)XLookupString((XKeyEvent*)event,str,sizeof(str),&keysym,NULL);
- if (keysym == XK_Return) {
- DEBUG0("keyPressHandler: calling okButtonCallback...\n");
- okButtonCallback(NULL,client_data,NULL);
- }
- DEBUG0("keyPressHandler: done\n");
- }
-
- /*
- * Nonmaskable event handler for Shell: If the event is a ClientMessage
- * of WM_PROTOCOLS then act as if Cancel had been clicked.
- */
- static void
- nonmaskableEventHandler(w,client_data,event,continue_to_dispatch)
- Widget w;
- XtPointer client_data;
- XEvent *event;
- Boolean *continue_to_dispatch;
- {
- DEBUG1("nonmaskableHandler: w=0x%x\n",w);
- if (event->type == ClientMessage &&
- event->xclient.data.l[0] == WM_DELETE_WINDOW) {
- DEBUG0("nonmaskableHandler: calling cancelButtonCallback\n");
- cancelButtonCallback(NULL,client_data,NULL);
- }
- DEBUG0("nonmaskableHandler: done\n");
- }
-