2 * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
4 * Permission to use, copy, modify, and distribute this software and its
5 * documentation for any purpose and without fee is hereby granted, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Software Research Associates not be used
9 * in advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. Software Research Associates
11 * makes no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
14 * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
16 * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
17 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
18 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
19 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
22 * Author: Erik M. van der Poel
23 * Software Research Associates, Inc., Tokyo, Japan
32 * erik%sra.co.jp@uunet.uu.net
34 * erik%sra.co.jp@mcvax.uucp
36 * try junet instead of co.jp
38 * Erik M. van der Poel
39 * Software Research Associates, Inc.
40 * 1-1-1 Hirakawa-cho, Chiyoda-ku
41 * Tokyo 102 Japan. TEL +81-3-234-2692
46 /* BSD 4.3 errno.h does not declare errno */
48 //extern int sys_nerr;
49 //extern char *sys_errlist[]; // [HGM] this produced a compile error in Ubuntu 8.04
51 #include <sys/param.h>
52 #include <X11/cursorfont.h>
53 #include <X11/Intrinsic.h>
54 #include <X11/StringDefs.h>
55 #include <X11/Composite.h>
56 #include <X11/Shell.h>
57 #include <X11/Xaw/Form.h>
58 #include <X11/Xaw/Command.h>
59 #include <X11/Xaw/Scrollbar.h>
60 #include <X11/Xaw/Label.h>
61 #include <X11/Xaw/Cardinals.h>
65 #include "../gettext.h"
68 #define MAXPATHLEN 1024
69 #endif /* ndef MAXPATHLEN */
71 #if !defined(SVR4) && !defined(SYSV) && !defined(USG)
73 #endif /* !defined(SVR4) && !defined(SYSV) && !defined(USG) */
76 # define _(s) gettext (s)
77 # define N_(s) gettext_noop (s)
84 int SFstatus = SEL_FILE_NULL;
87 SFstartDir[MAXPATHLEN+1],
88 SFcurrentPath[MAXPATHLEN+1],
89 SFlastPath[MAXPATHLEN+1],
90 SFcurrentDir[MAXPATHLEN+1];
108 Pixel SFfore, SFback;
110 Atom SFwmDeleteWindow;
112 XSegment SFsegs[2], SFcompletionSegs[2];
114 XawTextPosition SFtextPos;
116 int SFupperX, SFlowerY, SFupperY;
118 int SFtextX, SFtextYoffset;
120 int SFentryWidth, SFentryHeight;
122 int SFlineToTextH = 3;
124 int SFlineToTextV = 3;
126 int SFbesideText = 3;
128 int SFaboveAndBelowText = 2;
130 int SFcharsPerEntry = 15;
134 int SFworkProcAdded = 0;
138 int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
140 char SFtextBuffer[MAXPATHLEN+1];
142 char SFfilterBuffer[MAXPATHLEN+1];
144 XtIntervalId SFdirModTimerId;
148 Boolean SFpathFlag; // [HGM]
150 static char *oneLineTextEditTranslations = "\
151 <Key>Return: redraw-display()\n\
152 Ctrl<Key>M: redraw-display()\n\
157 SFexposeList(w, n, event, cont)
163 if ((event->type == NoExpose) || event->xexpose.count) {
167 SFdrawList((int)(intptr_t)n, SF_DO_NOT_SCROLL);
173 if(SFdirs) XtFree((XtPointer) SFdirs);
174 SFdirs = NULL; // kludge to throw away all cached info
179 SFmodVerifyCallback(w, client_data, event, cont)
181 XtPointer client_data;
188 (XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) &&
189 ((*buf) == '\r' || *buf == 033)
192 Arg args[10]; char *p;
193 if(*buf == 033) { // [HGM] esc in filter: restore and give focus to path
194 XtSetArg(args[0], XtNstring, SFfilterBuffer);
195 XtSetValues(filterField, args, 1);
196 XtSetKeyboardFocus(selFileForm, selFileField);
197 SFstatus = SEL_FILE_TEXT;
200 if(!SFpathFlag) // [HGM] cr: fetch current extenson filter
202 XtSetArg(args[0], XtNstring, &p);
203 XtGetValues(filterField, args, 1);
204 if(strcmp(SFfilterBuffer, p)) SFpurge();
205 strncpy(SFfilterBuffer, p, 40);
206 SFstatus = SEL_FILE_TEXT;
210 SFstatus = (*buf == 033 ? SEL_FILE_CANCEL : SEL_FILE_OK);
212 if(!client_data) SFstatus = SEL_FILE_TEXT;
218 SFokCallback(w, cl, cd)
222 SFstatus = SEL_FILE_OK;
225 static XtCallbackRec SFokSelect[] = {
226 { SFokCallback, (XtPointer) NULL },
227 { NULL, (XtPointer) NULL },
232 SFcancelCallback(w, cl, cd)
236 SFstatus = SEL_FILE_CANCEL;
239 static XtCallbackRec SFcancelSelect[] = {
240 { SFcancelCallback, (XtPointer) NULL },
241 { NULL, (XtPointer) NULL },
246 SFdismissAction(w, event, params, num_params)
250 Cardinal *num_params;
252 if (event->type == ClientMessage &&
253 event->xclient.data.l[0] != SFwmDeleteWindow) return;
255 SFstatus = SEL_FILE_CANCEL;
258 static char *wmDeleteWindowTranslation = "\
259 <Message>WM_PROTOCOLS: SelFileDismiss()\n\
262 static XtActionsRec actions[] = {
263 {"SelFileDismiss", SFdismissAction},
266 void SFsetFocus(Widget w, XtPointer data, XEvent *event, Boolean *b)
268 XtSetKeyboardFocus((Widget) data, w);
271 void SFwheelProc(Widget w, XtPointer data, XEvent *event, Boolean *b)
272 { // [HGM] mouse-wheel callback scrolls lists
273 int dir, n = (intptr_t) data;
274 if(event->xbutton.button == Button4) dir = -2; // kludge to indicate relative motion
275 if(event->xbutton.button == Button5) dir = -1;
276 SFvSliderMovedCallback(w, n, dir);
280 SFcreateWidgets(toplevel, prompt, ok, cancel)
287 int listWidth, listHeight;
288 int listSpacing = 10;
289 int scrollThickness = 15;
290 int hScrollX, hScrollY;
291 int vScrollX, vScrollY;
299 XtSetArg(arglist[i], XtNtransientFor, toplevel); i++;
301 selFile = XtAppCreateShell(_("Browse"), "SelFile",
302 transientShellWidgetClass, SFdisplay, arglist, i);
304 /* Add WM_DELETE_WINDOW protocol */
305 XtAppAddActions(XtWidgetToApplicationContext(selFile),
306 actions, XtNumber(actions));
307 XtOverrideTranslations(selFile,
308 XtParseTranslationTable(wmDeleteWindowTranslation));
311 XtSetArg(arglist[i], XtNdefaultDistance, 30); i++;
312 selFileForm = XtCreateManagedWidget("selFileForm",
313 formWidgetClass, selFile, arglist, i);
316 XtSetArg(arglist[i], XtNlabel, prompt); i++;
317 XtSetArg(arglist[i], XtNresizable, True); i++;
318 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
319 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
320 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
321 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
322 XtSetArg(arglist[i], XtNborderWidth, 0); i++;
323 selFilePrompt = XtCreateManagedWidget("selFilePrompt",
324 labelWidgetClass, selFileForm, arglist, i);
327 XtSetArg(arglist[i], XtNforeground, &SFfore); i++;
328 XtSetArg(arglist[i], XtNbackground, &SFback); i++;
329 XtGetValues(selFilePrompt, arglist, i);
333 SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth +
335 SFentryHeight = SFaboveAndBelowText + SFcharHeight +
338 listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
340 listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
341 SFlineToTextV + SFlistSize * SFentryHeight +
342 SFlineToTextV + 1 + scrollThickness;
344 SFpathScrollWidth = NR * listWidth + (NR-1) * listSpacing + 4;
347 hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
348 SFlineToTextV + SFlistSize * SFentryHeight +
350 SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
352 vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
353 vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
354 SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
357 SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
358 SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
360 SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
361 SFlineToTextV + SFlistSize * SFentryHeight - 1;
363 SFtextX = SFlineToTextH + SFbesideText;
364 SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
367 SFsegs[0].y1 = vScrollY;
368 SFsegs[0].x2 = vScrollX - 1;
369 SFsegs[0].y2 = vScrollY;
370 SFsegs[1].x1 = vScrollX;
372 SFsegs[1].x2 = vScrollX;
373 SFsegs[1].y2 = vScrollY - 1;
375 SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
376 SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
377 SFlineToTextH + SFentryWidth - 1;
380 XtSetArg(arglist[i], XtNwidth, NR * listWidth + (NR - 1) * listSpacing + 4);
382 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
384 XtSetArg(arglist[i], XtNfromVert, selFilePrompt); i++;
385 XtSetArg(arglist[i], XtNvertDistance, 5); i++;
386 XtSetArg(arglist[i], XtNresizable, True); i++;
387 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
388 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
389 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
390 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
391 XtSetArg(arglist[i], XtNstring, SFtextBuffer); i++;
392 XtSetArg(arglist[i], XtNlength, MAXPATHLEN); i++;
393 XtSetArg(arglist[i], XtNeditType, XawtextEdit); i++;
394 XtSetArg(arglist[i], XtNwrap, XawtextWrapWord); i++;
395 XtSetArg(arglist[i], XtNresize, XawtextResizeHeight); i++;
396 selFileField = XtCreateManagedWidget("selFileField",
397 asciiTextWidgetClass, selFileForm, arglist, i);
399 XtOverrideTranslations(selFileField,
400 XtParseTranslationTable(oneLineTextEditTranslations));
401 XtAddEventHandler(selFileField, ButtonPressMask, False, SFsetFocus, (XtPointer) selFileForm);
404 XtSetArg(arglist[i], XtNlabel, _("Filter on extensions:")); i++;
405 XtSetArg(arglist[i], XtNvertDistance, 5); i++;
406 XtSetArg(arglist[i], XtNfromVert, selFileField); i++;
407 XtSetArg(arglist[i], XtNresizable, True); i++;
408 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
409 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
410 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
411 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
412 XtSetArg(arglist[i], XtNborderWidth, 0); i++;
413 selFileMess = XtCreateManagedWidget("selFileMess",
414 labelWidgetClass, selFileForm, arglist, i);
417 XtSetArg(arglist[i], XtNwidth, NR * listWidth + (NR - 1) * listSpacing + 4);
419 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
420 XtSetArg(arglist[i], XtNvertDistance, 5); i++;
421 XtSetArg(arglist[i], XtNfromVert, selFileMess); i++;
422 XtSetArg(arglist[i], XtNresizable, True); i++;
423 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
424 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
425 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
426 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
427 XtSetArg(arglist[i], XtNlength, MAXPATHLEN); i++;
428 XtSetArg(arglist[i], XtNeditType, XawtextEdit); i++;
429 XtSetArg(arglist[i], XtNwrap, XawtextWrapWord); i++;
430 XtSetArg(arglist[i], XtNresize, XawtextResizeHeight); i++;
431 XtSetArg(arglist[i], XtNuseStringInPlace, False); i++;
432 filterField = XtCreateManagedWidget("filterField",
433 asciiTextWidgetClass, selFileForm, arglist, i);
435 XtOverrideTranslations(filterField,
436 XtParseTranslationTable(oneLineTextEditTranslations));
437 XtAddEventHandler(filterField, ButtonPressMask, False, SFsetFocus, (XtPointer) selFileForm);
440 XtSetArg(arglist[i], XtNorientation, XtorientHorizontal); i++;
441 XtSetArg(arglist[i], XtNwidth, SFpathScrollWidth); i++;
442 XtSetArg(arglist[i], XtNheight, scrollThickness); i++;
443 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
444 XtSetArg(arglist[i], XtNfromVert, filterField); i++;
445 XtSetArg(arglist[i], XtNvertDistance, 10); i++;
446 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
447 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
448 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
449 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
450 selFileHScroll = XtCreateManagedWidget("selFileHScroll",
451 scrollbarWidgetClass, selFileForm, arglist, i);
453 XtAddCallback(selFileHScroll, XtNjumpProc,
454 SFpathSliderMovedCallback, (XtPointer) NULL);
455 XtAddCallback(selFileHScroll, XtNscrollProc,
456 SFpathAreaSelectedCallback, (XtPointer) NULL);
459 XtSetArg(arglist[i], XtNwidth, listWidth); i++;
460 XtSetArg(arglist[i], XtNheight, listHeight); i++;
461 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
462 XtSetArg(arglist[i], XtNfromVert, selFileHScroll); i++;
463 XtSetArg(arglist[i], XtNvertDistance, 10); i++;
464 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
465 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
466 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
467 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
468 selFileLists[0] = XtCreateManagedWidget("selFileList1",
469 compositeWidgetClass, selFileForm, arglist, i);
472 XtSetArg(arglist[i], XtNwidth, listWidth); i++;
473 XtSetArg(arglist[i], XtNheight, listHeight); i++;
474 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
475 XtSetArg(arglist[i], XtNfromHoriz, selFileLists[0]); i++;
476 XtSetArg(arglist[i], XtNfromVert, selFileHScroll); i++;
477 XtSetArg(arglist[i], XtNhorizDistance, listSpacing); i++;
478 XtSetArg(arglist[i], XtNvertDistance, 10); i++;
479 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
480 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
481 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
482 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
483 selFileLists[1] = XtCreateManagedWidget("selFileList2",
484 compositeWidgetClass, selFileForm, arglist, i);
487 XtSetArg(arglist[i], XtNwidth, listWidth); i++;
488 XtSetArg(arglist[i], XtNheight, listHeight); i++;
489 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
490 XtSetArg(arglist[i], XtNfromHoriz, selFileLists[1]); i++;
491 XtSetArg(arglist[i], XtNfromVert, selFileHScroll); i++;
492 XtSetArg(arglist[i], XtNhorizDistance, listSpacing); i++;
493 XtSetArg(arglist[i], XtNvertDistance, 10); i++;
494 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
495 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
496 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
497 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
498 selFileLists[2] = XtCreateManagedWidget("selFileList3",
499 compositeWidgetClass, selFileForm, arglist, i);
501 for (n = 0; n < NR; n++) {
504 XtSetArg(arglist[i], XtNx, vScrollX); i++;
505 XtSetArg(arglist[i], XtNy, vScrollY); i++;
506 XtSetArg(arglist[i], XtNwidth, scrollThickness); i++;
507 XtSetArg(arglist[i], XtNheight, SFvScrollHeight); i++;
508 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
509 selFileVScrolls[n] = XtCreateManagedWidget("selFileVScroll",
510 scrollbarWidgetClass, selFileLists[n], arglist, i);
512 XtAddCallback(selFileVScrolls[n], XtNjumpProc,
513 SFvFloatSliderMovedCallback, (XtPointer)(intptr_t) n);
514 XtAddCallback(selFileVScrolls[n], XtNscrollProc,
515 SFvAreaSelectedCallback, (XtPointer)(intptr_t) n);
519 XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);
521 XtSetArg(arglist[i], XtNx, hScrollX); i++;
522 XtSetArg(arglist[i], XtNy, hScrollY); i++;
523 XtSetArg(arglist[i], XtNwidth, SFhScrollWidth); i++;
524 XtSetArg(arglist[i], XtNheight, scrollThickness); i++;
525 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
526 selFileHScrolls[n] = XtCreateManagedWidget("selFileHScroll",
527 scrollbarWidgetClass, selFileLists[n], arglist, i);
529 XtAddCallback(selFileHScrolls[n], XtNjumpProc,
530 SFhSliderMovedCallback, (XtPointer)(intptr_t) n);
531 XtAddCallback(selFileHScrolls[n], XtNscrollProc,
532 SFhAreaSelectedCallback, (XtPointer)(intptr_t) n);
534 XtAddEventHandler(selFileVScrolls[n], ButtonPressMask, False,
535 SFwheelProc, (XtPointer)(intptr_t) n); // [HGM] couplemouse wheel to v-scroll
539 XtSetArg(arglist[i], XtNlabel, ok); i++;
540 XtSetArg(arglist[i], XtNresizable, True); i++;
541 XtSetArg(arglist[i], XtNcallback, SFokSelect); i++;
542 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
543 XtSetArg(arglist[i], XtNfromVert, selFileLists[0]); i++;
544 XtSetArg(arglist[i], XtNvertDistance, 30); i++;
545 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
546 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
547 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
548 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
549 selFileOK = XtCreateManagedWidget("selFileOK", commandWidgetClass,
550 selFileForm, arglist, i);
553 XtSetArg(arglist[i], XtNlabel, cancel); i++;
554 XtSetArg(arglist[i], XtNresizable, True); i++;
555 XtSetArg(arglist[i], XtNcallback, SFcancelSelect); i++;
556 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
557 XtSetArg(arglist[i], XtNfromHoriz, selFileOK); i++;
558 XtSetArg(arglist[i], XtNfromVert, selFileLists[0]); i++;
559 XtSetArg(arglist[i], XtNhorizDistance, 30); i++;
560 XtSetArg(arglist[i], XtNvertDistance, 30); i++;
561 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
562 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
563 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
564 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
565 selFileCancel = XtCreateManagedWidget("selFileCancel",
566 commandWidgetClass, selFileForm, arglist, i);
568 XtSetMappedWhenManaged(selFile, False);
569 XtRealizeWidget(selFile);
571 /* Add WM_DELETE_WINDOW protocol */
572 SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
573 XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);
577 xtermCursor = XCreateFontCursor(SFdisplay, XC_xterm);
579 sbRightArrowCursor = XCreateFontCursor(SFdisplay, XC_sb_right_arrow);
580 dotCursor = XCreateFontCursor(SFdisplay, XC_dot);
582 XDefineCursor(SFdisplay, XtWindow(selFileForm), xtermCursor);
583 XDefineCursor(SFdisplay, XtWindow(selFileField), xtermCursor);
584 XDefineCursor(SFdisplay, XtWindow(filterField), xtermCursor);
586 for (n = 0; n < NR; n++) {
587 XDefineCursor(SFdisplay, XtWindow(selFileLists[n]),
590 XDefineCursor(SFdisplay, XtWindow(selFileOK), dotCursor);
591 XDefineCursor(SFdisplay, XtWindow(selFileCancel), dotCursor);
593 for (n = 0; n < NR; n++) {
594 XtAddEventHandler(selFileLists[n], ExposureMask, True,
595 SFexposeList, (XtPointer)(intptr_t) n);
596 XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
597 SFenterList, (XtPointer)(intptr_t) n);
598 XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
599 SFleaveList, (XtPointer)(intptr_t) n);
600 XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
601 (XtEventHandler) SFmotionList, (XtPointer)(intptr_t) n);
602 XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
603 SFbuttonPressList, (XtPointer)(intptr_t) n);
604 XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
605 SFbuttonReleaseList, (XtPointer)(intptr_t) n);
608 XtAddEventHandler(selFileField, KeyPressMask, False,
609 SFmodVerifyCallback, (XtPointer) NULL);
610 XtAddEventHandler(filterField, KeyReleaseMask, False,
611 SFmodVerifyCallback, (XtPointer) 1);
612 XtSetKeyboardFocus(selFileForm, selFileField);
614 SFapp = XtWidgetToApplicationContext(selFile);
618 /* position widget under the cursor */
625 Dimension width, height, b_width;
626 int x, y, max_x, max_y;
629 unsigned int dummymask;
631 XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &x, &y,
632 &dummyx, &dummyy, &dummymask);
634 XtSetArg(args[num_args], XtNwidth, &width); num_args++;
635 XtSetArg(args[num_args], XtNheight, &height); num_args++;
636 XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
637 XtGetValues(w, args, num_args);
639 width += 2 * b_width;
640 height += 2 * b_width;
642 x -= ( (Position) width/2 );
644 if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x;
646 y -= ( (Position) height/2 );
648 if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y;
651 XtSetArg(args[num_args], XtNx, x); num_args++;
652 XtSetArg(args[num_args], XtNy, y); num_args++;
653 XtSetValues(w, args, num_args);
657 SFopenFile(name, mode, prompt, failed)
667 if ((fp = fopen(name, mode)) == NULL) {
669 if (1) { // [HGM] always use strerror
670 buf = XtMalloc(strlen(failed) + strlen(strerror(errno)) +
673 strcat(buf, strerror(errno));
677 buf = XtMalloc(strlen(failed) + strlen(prompt) + 2);
682 XtSetArg(args[0], XtNlabel, buf);
683 XtSetValues(selFilePrompt, args, ONE);
698 XtSetArg(arglist[i], XtNstring, &v); i++;
699 XtGetValues(selFileField, arglist, i);
700 strncpy(SFtextBuffer, v, MAXPATHLEN);
711 XtSetArg(arglist[i], XtNstring, path); i++;
712 XtSetValues(selFileField, arglist, i);
713 XawTextSetInsertionPoint(selFileField, strlen(path));
719 SFupdateTextBuffer();
721 if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~')) {
722 (void) strncpy(SFcurrentPath, SFtextBuffer, MAXPATHLEN);
724 SFtextPos = XawTextGetInsertionPoint(selFileField);
726 (void) strcat(strncpy(SFcurrentPath, SFstartDir, MAXPATHLEN), SFtextBuffer);
728 SFtextPos = XawTextGetInsertionPoint(selFileField) +
732 if (!SFworkProcAdded) {
733 (void) XtAppAddWorkProc(SFapp, SFworkProc, NULL);
744 return strcpy(XtMalloc((unsigned) (strlen(SFtextBuffer) + 1)),
751 SFstatus = SEL_FILE_NULL;
752 XtRemoveGrab(selFile);
753 XtUnmapWidget(selFile);
754 XtRemoveTimeOut(SFdirModTimerId);
755 if (SFchdir(SFstartDir)) {
758 "XsraSelFile: can't return to current directory"
765 XsraSelFile(toplevel, prompt, ok, cancel, failed,
766 init_path, filter, mode, show_entry, name_return)
778 static int firstTime = 1;
785 prompt = _("Pathname:");
793 cancel = _("Cancel");
796 if(SFpathFlag != (mode && mode[0] == 'p') || strcmp(SFfilterBuffer, filter)) {
798 SFpathFlag = (mode && mode[0] == 'p'); // [HGM] ignore everything that is not a directory
803 SFdisplay = XtDisplay(toplevel);
804 SFcreateWidgets(toplevel, prompt, ok, cancel);
808 XtSetArg(arglist[i], XtNlabel, prompt); i++;
809 XtSetValues(selFilePrompt, arglist, i);
812 XtSetArg(arglist[i], XtNlabel, ok); i++;
813 XtSetValues(selFileOK, arglist, i);
816 XtSetArg(arglist[i], XtNlabel, cancel); i++;
817 XtSetValues(selFileCancel, arglist, i);
821 XtSetArg(arglist[i], XtNstring, filter); i++;
822 XtSetValues(filterField, arglist, i);
824 strncpy(SFfilterBuffer, filter, MAXPATHLEN-1);
825 SFupdateTextBuffer();
826 strncpy(SFlastPath, SFtextBuffer, MAXPATHLEN-1); // remember for cancel
828 SFpositionWidget(selFile);
829 XtMapWidget(selFile);
831 #if defined(SVR4) || defined(SYSV) || defined(USG) || 1
832 if (!getcwd(SFstartDir, MAXPATHLEN)) { // [HGM] always do this, as I do not know when exactly to do it
833 #else /* defined(SVR4) || defined(SYSV) || defined(USG) */
834 if (!getwd(SFstartDir)) {
835 #endif /* defined(SVR4) || defined(SYSV) || defined(USG) */
837 XtAppError(SFapp, _("XsraSelFile: can't get current directory"));
839 (void) strcat(SFstartDir, "/");
840 (void) strncpy(SFcurrentDir, SFstartDir, MAXPATHLEN);
843 if (init_path[0] == '/') {
844 (void) strncpy(SFcurrentPath, init_path, MAXPATHLEN);
850 SFsetText(SFcurrentPath);
852 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
855 (void) strcat(strncpy(SFcurrentPath, SFstartDir, MAXPATHLEN),
857 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
860 (void) strncpy(SFcurrentPath, SFstartDir, MAXPATHLEN);
867 XtAddGrab(selFile, True, True);
869 SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
870 SFdirModTimer, (XtPointer) NULL);
873 XtAppNextEvent(SFapp, &event);
874 XtDispatchEvent(&event);
877 SFstatus = SEL_FILE_NULL;
881 *name_return = SFgetText();
882 if(mode && (mode[0] == 'p' || mode[0] == 'f')) { // [HGM] for use in file-option browse button
886 if ((!(*name_return)[0] || (*name_return)[strlen(*name_return)-1] != '/') && // [HGM] refuse directories
887 (fp = SFopenFile(*name_return, mode, prompt, failed))) {
891 SFstatus = SEL_FILE_NULL;
893 case SEL_FILE_CANCEL:
895 SFsetText(SFlastPath);