#include <X11/Xaw/Label.h>
#include <X11/Xaw/Cardinals.h>
-#include "selfile.h"
#include "xstat.h"
-
-/* added missing prototypes */
-extern void SFdrawList(int,int);
-extern void SFinitFont();
-extern void SFcreateGC();
-extern int SFchdir(char *);
-extern void SFupdatePath();
-extern void SFsetText(char *);
-extern char SFstatChar(struct stat*);
+#include "selfile.h"
#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
int SFstatus = SEL_FILE_NULL;
char
- SFstartDir[MAXPATHLEN],
- SFcurrentPath[MAXPATHLEN],
- SFcurrentDir[MAXPATHLEN];
+ SFstartDir[MAXPATHLEN+1],
+ SFcurrentPath[MAXPATHLEN+1],
+ SFlastPath[MAXPATHLEN+1],
+ SFcurrentDir[MAXPATHLEN+1];
Widget
selFile,
selFileCancel,
selFileField,
+ selFileMess,
+ filterField,
selFileForm,
selFileHScroll,
selFileHScrolls[3],
int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
-char SFtextBuffer[MAXPATHLEN];
+char SFtextBuffer[MAXPATHLEN+1];
+
+char SFfilterBuffer[MAXPATHLEN+1];
XtIntervalId SFdirModTimerId;
int (*SFfunc)();
+Boolean SFpathFlag; // [HGM]
+
static char *oneLineTextEditTranslations = "\
<Key>Return: redraw-display()\n\
Ctrl<Key>M: redraw-display()\n\
return;
}
- SFdrawList((int)n, SF_DO_NOT_SCROLL);
+ SFdrawList((int)(intptr_t)n, SF_DO_NOT_SCROLL);
+}
+
+void
+SFpurge()
+{
+ if(SFdirs) XtFree((XtPointer) SFdirs);
+ SFdirs = NULL; // kludge to throw away all cached info
}
/* ARGSUSED */
if (
(XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) &&
- ((*buf) == '\r')
+ ((*buf) == '\r' || *buf == 033)
) {
- SFstatus = SEL_FILE_OK;
+ if(client_data) {
+ Arg args[10]; char *p;
+ if(*buf == 033) { // [HGM] esc in filter: restore and give focus to path
+ XtSetArg(args[0], XtNstring, SFfilterBuffer);
+ XtSetValues(filterField, args, 1);
+ XtSetKeyboardFocus(selFileForm, selFileField);
+ SFstatus = SEL_FILE_TEXT;
+ return;
+ } else
+ if(!SFpathFlag) // [HGM] cr: fetch current extenson filter
+ {
+ XtSetArg(args[0], XtNstring, &p);
+ XtGetValues(filterField, args, 1);
+ if(strcmp(SFfilterBuffer, p)) SFpurge();
+ strncpy(SFfilterBuffer, p, 40);
+ SFstatus = SEL_FILE_TEXT;
+ }
+ return;
+ }
+ SFstatus = (*buf == 033 ? SEL_FILE_CANCEL : SEL_FILE_OK);
} else {
- SFstatus = SEL_FILE_TEXT;
+ if(!client_data) SFstatus = SEL_FILE_TEXT;
}
}
{"SelFileDismiss", SFdismissAction},
};
+void SFsetFocus(Widget w, XtPointer data, XEvent *event, Boolean *b)
+{
+ XtSetKeyboardFocus((Widget) data, w);
+}
+
+void SFwheelProc(Widget w, XtPointer data, XEvent *event, Boolean *b)
+{ // [HGM] mouse-wheel callback scrolls lists
+ int dir, n = (intptr_t) data;
+ if(event->xbutton.button == Button4) dir = -2; // kludge to indicate relative motion
+ if(event->xbutton.button == Button5) dir = -1;
+ SFvSliderMovedCallback(w, n, dir);
+}
+
static void
SFcreateWidgets(toplevel, prompt, ok, cancel)
Widget toplevel;
XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
XtSetArg(arglist[i], XtNfromVert, selFilePrompt); i++;
- XtSetArg(arglist[i], XtNvertDistance, 10); i++;
+ XtSetArg(arglist[i], XtNvertDistance, 5); i++;
XtSetArg(arglist[i], XtNresizable, True); i++;
XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
XtSetArg(arglist[i], XtNeditType, XawtextEdit); i++;
XtSetArg(arglist[i], XtNwrap, XawtextWrapWord); i++;
XtSetArg(arglist[i], XtNresize, XawtextResizeHeight); i++;
- XtSetArg(arglist[i], XtNuseStringInPlace, True); i++;
selFileField = XtCreateManagedWidget("selFileField",
asciiTextWidgetClass, selFileForm, arglist, i);
XtOverrideTranslations(selFileField,
XtParseTranslationTable(oneLineTextEditTranslations));
- XtSetKeyboardFocus(selFileForm, selFileField);
+ XtAddEventHandler(selFileField, ButtonPressMask, False, SFsetFocus, (XtPointer) selFileForm);
+
+ i = 0;
+ XtSetArg(arglist[i], XtNlabel, "Filter on extensions:"); i++;
+ XtSetArg(arglist[i], XtNvertDistance, 5); i++;
+ XtSetArg(arglist[i], XtNfromVert, selFileField); i++;
+ XtSetArg(arglist[i], XtNresizable, True); i++;
+ XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
+ XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
+ XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
+ XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
+ XtSetArg(arglist[i], XtNborderWidth, 0); i++;
+ selFileMess = XtCreateManagedWidget("selFileMess",
+ labelWidgetClass, selFileForm, arglist, i);
+
+ i = 0;
+ XtSetArg(arglist[i], XtNwidth, NR * listWidth + (NR - 1) * listSpacing + 4);
+ i++;
+ XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
+ XtSetArg(arglist[i], XtNvertDistance, 5); i++;
+ XtSetArg(arglist[i], XtNfromVert, selFileMess); i++;
+ XtSetArg(arglist[i], XtNresizable, True); i++;
+ XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
+ XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
+ XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
+ XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
+ XtSetArg(arglist[i], XtNlength, MAXPATHLEN); i++;
+ XtSetArg(arglist[i], XtNeditType, XawtextEdit); i++;
+ XtSetArg(arglist[i], XtNwrap, XawtextWrapWord); i++;
+ XtSetArg(arglist[i], XtNresize, XawtextResizeHeight); i++;
+ XtSetArg(arglist[i], XtNuseStringInPlace, False); i++;
+ filterField = XtCreateManagedWidget("filterField",
+ asciiTextWidgetClass, selFileForm, arglist, i);
+
+ XtOverrideTranslations(filterField,
+ XtParseTranslationTable(oneLineTextEditTranslations));
+ XtAddEventHandler(filterField, ButtonPressMask, False, SFsetFocus, (XtPointer) selFileForm);
i = 0;
XtSetArg(arglist[i], XtNorientation, XtorientHorizontal); i++;
XtSetArg(arglist[i], XtNwidth, SFpathScrollWidth); i++;
XtSetArg(arglist[i], XtNheight, scrollThickness); i++;
XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
- XtSetArg(arglist[i], XtNfromVert, selFileField); i++;
- XtSetArg(arglist[i], XtNvertDistance, 30); i++;
+ XtSetArg(arglist[i], XtNfromVert, filterField); i++;
+ XtSetArg(arglist[i], XtNvertDistance, 10); i++;
XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
scrollbarWidgetClass, selFileLists[n], arglist, i);
XtAddCallback(selFileVScrolls[n], XtNjumpProc,
- SFvFloatSliderMovedCallback, (XtPointer) n);
+ SFvFloatSliderMovedCallback, (XtPointer)(intptr_t) n);
XtAddCallback(selFileVScrolls[n], XtNscrollProc,
- SFvAreaSelectedCallback, (XtPointer) n);
+ SFvAreaSelectedCallback, (XtPointer)(intptr_t) n);
i = 0;
scrollbarWidgetClass, selFileLists[n], arglist, i);
XtAddCallback(selFileHScrolls[n], XtNjumpProc,
- SFhSliderMovedCallback, (XtPointer) n);
+ SFhSliderMovedCallback, (XtPointer)(intptr_t) n);
XtAddCallback(selFileHScrolls[n], XtNscrollProc,
- SFhAreaSelectedCallback, (XtPointer) n);
+ SFhAreaSelectedCallback, (XtPointer)(intptr_t) n);
+
+ XtAddEventHandler(selFileVScrolls[n], ButtonPressMask, False,
+ SFwheelProc, (XtPointer)(intptr_t) n); // [HGM] couplemouse wheel to v-scroll
}
i = 0;
XDefineCursor(SFdisplay, XtWindow(selFileForm), xtermCursor);
XDefineCursor(SFdisplay, XtWindow(selFileField), xtermCursor);
+ XDefineCursor(SFdisplay, XtWindow(filterField), xtermCursor);
for (n = 0; n < NR; n++) {
XDefineCursor(SFdisplay, XtWindow(selFileLists[n]),
for (n = 0; n < NR; n++) {
XtAddEventHandler(selFileLists[n], ExposureMask, True,
- SFexposeList, (XtPointer) n);
+ SFexposeList, (XtPointer)(intptr_t) n);
XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
- SFenterList, (XtPointer) n);
+ SFenterList, (XtPointer)(intptr_t) n);
XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
- SFleaveList, (XtPointer) n);
+ SFleaveList, (XtPointer)(intptr_t) n);
XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
- SFmotionList, (XtPointer) n);
+ (XtEventHandler) SFmotionList, (XtPointer)(intptr_t) n);
XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
- SFbuttonPressList, (XtPointer) n);
+ SFbuttonPressList, (XtPointer)(intptr_t) n);
XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
- SFbuttonReleaseList, (XtPointer) n);
+ SFbuttonReleaseList, (XtPointer)(intptr_t) n);
}
XtAddEventHandler(selFileField, KeyPressMask, False,
SFmodVerifyCallback, (XtPointer) NULL);
+ XtAddEventHandler(filterField, KeyReleaseMask, False,
+ SFmodVerifyCallback, (XtPointer) 1);
+ XtSetKeyboardFocus(selFileForm, selFileField);
SFapp = XtWidgetToApplicationContext(selFile);
}
void
+SFupdateTextBuffer()
+{
+ Arg arglist[2];
+ int i;
+ char *v;
+
+ i = 0;
+ XtSetArg(arglist[i], XtNstring, &v); i++;
+ XtGetValues(selFileField, arglist, i);
+ strncpy(SFtextBuffer, v, MAXPATHLEN);
+}
+
+void
+SFsetText(path)
+ char *path;
+{
+ Arg arglist[2];
+ int i;
+
+ i = 0;
+ XtSetArg(arglist[i], XtNstring, path); i++;
+ XtSetValues(selFileField, arglist, i);
+ XawTextSetInsertionPoint(selFileField, strlen(path));
+}
+
+void
SFtextChanged()
{
+ SFupdateTextBuffer();
if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~')) {
(void) strncpy(SFcurrentPath, SFtextBuffer, MAXPATHLEN);
FILE *
XsraSelFile(toplevel, prompt, ok, cancel, failed,
- init_path, mode, show_entry, name_return)
+ init_path, filter, mode, show_entry, name_return)
Widget toplevel;
char *prompt;
char *ok;
char *cancel;
char *failed;
char *init_path;
+ char *filter;
char *mode;
int (*show_entry)();
char **name_return;
cancel = "Cancel";
}
+ if(SFpathFlag != (mode && mode[0] == 'p') || strcmp(SFfilterBuffer, filter)) {
+ SFpurge();
+ SFpathFlag = (mode && mode[0] == 'p'); // [HGM] ignore everything that is not a directory
+ }
+
if (firstTime) {
firstTime = 0;
SFdisplay = XtDisplay(toplevel);
XtSetValues(selFileCancel, arglist, i);
}
+ i = 0;
+ XtSetArg(arglist[i], XtNstring, filter); i++;
+ XtSetValues(filterField, arglist, i);
+
+ strncpy(SFfilterBuffer, filter, MAXPATHLEN-1);
+ SFupdateTextBuffer();
+ strncpy(SFlastPath, SFtextBuffer, MAXPATHLEN-1); // remember for cancel
+
SFpositionWidget(selFile);
XtMapWidget(selFile);
break;
case SEL_FILE_OK:
*name_return = SFgetText();
- if (fp = SFopenFile(*name_return, mode,
- prompt, failed)) {
+ if(mode && (mode[0] == 'p' || mode[0] == 'f')) { // [HGM] for use in file-option browse button
+ SFprepareToReturn();
+ return stderr;
+ }
+ if ((*name_return)[strlen(*name_return)-1] != '/' && // [HGM] refuse directories
+ (fp = SFopenFile(*name_return, mode, prompt, failed))) {
SFprepareToReturn();
return fp;
}
break;
case SEL_FILE_CANCEL:
SFprepareToReturn();
+ SFsetText(SFlastPath);
return NULL;
case SEL_FILE_NULL:
break;
}
}
+
}