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>
66 /* added missing prototypes */
67 extern void SFdrawList(int,int);
68 extern void SFinitFont();
69 extern void SFcreateGC();
70 extern int SFchdir(char *);
71 extern void SFupdatePath();
72 extern void SFsetText(char *);
73 extern char SFstatChar(struct stat*);
76 #define MAXPATHLEN 1024
77 #endif /* ndef MAXPATHLEN */
79 #if !defined(SVR4) && !defined(SYSV) && !defined(USG)
81 #endif /* !defined(SVR4) && !defined(SYSV) && !defined(USG) */
83 int SFstatus = SEL_FILE_NULL;
86 SFstartDir[MAXPATHLEN],
87 SFcurrentPath[MAXPATHLEN],
88 SFlastPath[MAXPATHLEN],
89 SFcurrentDir[MAXPATHLEN];
107 Pixel SFfore, SFback;
109 Atom SFwmDeleteWindow;
111 XSegment SFsegs[2], SFcompletionSegs[2];
113 XawTextPosition SFtextPos;
115 int SFupperX, SFlowerY, SFupperY;
117 int SFtextX, SFtextYoffset;
119 int SFentryWidth, SFentryHeight;
121 int SFlineToTextH = 3;
123 int SFlineToTextV = 3;
125 int SFbesideText = 3;
127 int SFaboveAndBelowText = 2;
129 int SFcharsPerEntry = 15;
133 int SFworkProcAdded = 0;
137 int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
139 char SFtextBuffer[MAXPATHLEN];
141 char SFfilterBuffer[MAXPATHLEN];
143 XtIntervalId SFdirModTimerId;
147 Boolean SFpathFlag; // [HGM]
149 static char *oneLineTextEditTranslations = "\
150 <Key>Return: redraw-display()\n\
151 Ctrl<Key>M: redraw-display()\n\
156 SFexposeList(w, n, event, cont)
162 if ((event->type == NoExpose) || event->xexpose.count) {
166 SFdrawList((int)(intptr_t)n, SF_DO_NOT_SCROLL);
172 if(SFdirs) XtFree((XtPointer) SFdirs);
173 SFdirs = NULL; // kludge to throw away all cached info
178 SFmodVerifyCallback(w, client_data, event, cont)
180 XtPointer client_data;
187 (XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) &&
188 ((*buf) == '\r' || *buf == 033)
191 Arg args[10]; char *p;
192 if(*buf == 033) { // [HGM] esc in filter: restore and give focus to path
193 XtSetArg(args[0], XtNstring, SFfilterBuffer);
194 XtSetValues(filterField, args, 1);
195 XtSetKeyboardFocus(selFileForm, selFileField);
196 SFstatus = SEL_FILE_TEXT;
199 if(!SFpathFlag) // [HGM] cr: fetch current extenson filter
201 XtSetArg(args[0], XtNstring, &p);
202 XtGetValues(filterField, args, 1);
203 if(strcmp(SFfilterBuffer, p)) SFpurge();
204 strncpy(SFfilterBuffer, p, 40);
205 SFstatus = SEL_FILE_TEXT;
209 SFstatus = (*buf == 033 ? SEL_FILE_CANCEL : SEL_FILE_OK);
211 if(!client_data) SFstatus = SEL_FILE_TEXT;
217 SFokCallback(w, cl, cd)
221 SFstatus = SEL_FILE_OK;
224 static XtCallbackRec SFokSelect[] = {
225 { SFokCallback, (XtPointer) NULL },
226 { NULL, (XtPointer) NULL },
231 SFcancelCallback(w, cl, cd)
235 SFstatus = SEL_FILE_CANCEL;
238 static XtCallbackRec SFcancelSelect[] = {
239 { SFcancelCallback, (XtPointer) NULL },
240 { NULL, (XtPointer) NULL },
245 SFdismissAction(w, event, params, num_params)
249 Cardinal *num_params;
251 if (event->type == ClientMessage &&
252 event->xclient.data.l[0] != SFwmDeleteWindow) return;
254 SFstatus = SEL_FILE_CANCEL;
257 static char *wmDeleteWindowTranslation = "\
258 <Message>WM_PROTOCOLS: SelFileDismiss()\n\
261 static XtActionsRec actions[] = {
262 {"SelFileDismiss", SFdismissAction},
265 void SFsetFocus(Widget w, XtPointer data, XEvent *event, Boolean *b)
267 XtSetKeyboardFocus((Widget) data, w);
271 SFcreateWidgets(toplevel, prompt, ok, cancel)
278 int listWidth, listHeight;
279 int listSpacing = 10;
280 int scrollThickness = 15;
281 int hScrollX, hScrollY;
282 int vScrollX, vScrollY;
290 XtSetArg(arglist[i], XtNtransientFor, toplevel); i++;
292 selFile = XtAppCreateShell("Browse", "SelFile",
293 transientShellWidgetClass, SFdisplay, arglist, i);
295 /* Add WM_DELETE_WINDOW protocol */
296 XtAppAddActions(XtWidgetToApplicationContext(selFile),
297 actions, XtNumber(actions));
298 XtOverrideTranslations(selFile,
299 XtParseTranslationTable(wmDeleteWindowTranslation));
302 XtSetArg(arglist[i], XtNdefaultDistance, 30); i++;
303 selFileForm = XtCreateManagedWidget("selFileForm",
304 formWidgetClass, selFile, arglist, i);
307 XtSetArg(arglist[i], XtNlabel, prompt); i++;
308 XtSetArg(arglist[i], XtNresizable, True); i++;
309 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
310 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
311 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
312 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
313 XtSetArg(arglist[i], XtNborderWidth, 0); i++;
314 selFilePrompt = XtCreateManagedWidget("selFilePrompt",
315 labelWidgetClass, selFileForm, arglist, i);
318 XtSetArg(arglist[i], XtNforeground, &SFfore); i++;
319 XtSetArg(arglist[i], XtNbackground, &SFback); i++;
320 XtGetValues(selFilePrompt, arglist, i);
324 SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth +
326 SFentryHeight = SFaboveAndBelowText + SFcharHeight +
329 listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
331 listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
332 SFlineToTextV + SFlistSize * SFentryHeight +
333 SFlineToTextV + 1 + scrollThickness;
335 SFpathScrollWidth = NR * listWidth + (NR-1) * listSpacing + 4;
338 hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
339 SFlineToTextV + SFlistSize * SFentryHeight +
341 SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
343 vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
344 vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
345 SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
348 SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
349 SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
351 SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
352 SFlineToTextV + SFlistSize * SFentryHeight - 1;
354 SFtextX = SFlineToTextH + SFbesideText;
355 SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
358 SFsegs[0].y1 = vScrollY;
359 SFsegs[0].x2 = vScrollX - 1;
360 SFsegs[0].y2 = vScrollY;
361 SFsegs[1].x1 = vScrollX;
363 SFsegs[1].x2 = vScrollX;
364 SFsegs[1].y2 = vScrollY - 1;
366 SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
367 SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
368 SFlineToTextH + SFentryWidth - 1;
371 XtSetArg(arglist[i], XtNwidth, NR * listWidth + (NR - 1) * listSpacing + 4);
373 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
375 XtSetArg(arglist[i], XtNfromVert, selFilePrompt); i++;
376 XtSetArg(arglist[i], XtNvertDistance, 5); i++;
377 XtSetArg(arglist[i], XtNresizable, True); i++;
378 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
379 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
380 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
381 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
382 XtSetArg(arglist[i], XtNstring, SFtextBuffer); i++;
383 XtSetArg(arglist[i], XtNlength, MAXPATHLEN); i++;
384 XtSetArg(arglist[i], XtNeditType, XawtextEdit); i++;
385 XtSetArg(arglist[i], XtNwrap, XawtextWrapWord); i++;
386 XtSetArg(arglist[i], XtNresize, XawtextResizeHeight); i++;
387 XtSetArg(arglist[i], XtNuseStringInPlace, True); i++;
388 selFileField = XtCreateManagedWidget("selFileField",
389 asciiTextWidgetClass, selFileForm, arglist, i);
391 XtOverrideTranslations(selFileField,
392 XtParseTranslationTable(oneLineTextEditTranslations));
393 XtAddEventHandler(selFileField, ButtonPressMask, False, SFsetFocus, (XtPointer) selFileForm);
396 XtSetArg(arglist[i], XtNlabel, "Filter on extensions:"); i++;
397 XtSetArg(arglist[i], XtNvertDistance, 5); i++;
398 XtSetArg(arglist[i], XtNfromVert, selFileField); i++;
399 XtSetArg(arglist[i], XtNresizable, True); i++;
400 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
401 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
402 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
403 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
404 XtSetArg(arglist[i], XtNborderWidth, 0); i++;
405 selFileMess = XtCreateManagedWidget("selFileMess",
406 labelWidgetClass, selFileForm, arglist, i);
409 XtSetArg(arglist[i], XtNwidth, NR * listWidth + (NR - 1) * listSpacing + 4);
411 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
412 XtSetArg(arglist[i], XtNvertDistance, 5); i++;
413 XtSetArg(arglist[i], XtNfromVert, selFileMess); i++;
414 XtSetArg(arglist[i], XtNresizable, True); i++;
415 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
416 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
417 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
418 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
419 XtSetArg(arglist[i], XtNlength, MAXPATHLEN); i++;
420 XtSetArg(arglist[i], XtNeditType, XawtextEdit); i++;
421 XtSetArg(arglist[i], XtNwrap, XawtextWrapWord); i++;
422 XtSetArg(arglist[i], XtNresize, XawtextResizeHeight); i++;
423 XtSetArg(arglist[i], XtNuseStringInPlace, False); i++;
424 filterField = XtCreateManagedWidget("filterField",
425 asciiTextWidgetClass, selFileForm, arglist, i);
427 XtOverrideTranslations(filterField,
428 XtParseTranslationTable(oneLineTextEditTranslations));
429 XtAddEventHandler(filterField, ButtonPressMask, False, SFsetFocus, (XtPointer) selFileForm);
432 XtSetArg(arglist[i], XtNorientation, XtorientHorizontal); i++;
433 XtSetArg(arglist[i], XtNwidth, SFpathScrollWidth); i++;
434 XtSetArg(arglist[i], XtNheight, scrollThickness); i++;
435 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
436 XtSetArg(arglist[i], XtNfromVert, filterField); i++;
437 XtSetArg(arglist[i], XtNvertDistance, 10); i++;
438 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
439 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
440 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
441 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
442 selFileHScroll = XtCreateManagedWidget("selFileHScroll",
443 scrollbarWidgetClass, selFileForm, arglist, i);
445 XtAddCallback(selFileHScroll, XtNjumpProc,
446 SFpathSliderMovedCallback, (XtPointer) NULL);
447 XtAddCallback(selFileHScroll, XtNscrollProc,
448 SFpathAreaSelectedCallback, (XtPointer) NULL);
451 XtSetArg(arglist[i], XtNwidth, listWidth); i++;
452 XtSetArg(arglist[i], XtNheight, listHeight); i++;
453 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
454 XtSetArg(arglist[i], XtNfromVert, selFileHScroll); i++;
455 XtSetArg(arglist[i], XtNvertDistance, 10); i++;
456 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
457 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
458 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
459 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
460 selFileLists[0] = XtCreateManagedWidget("selFileList1",
461 compositeWidgetClass, selFileForm, arglist, i);
464 XtSetArg(arglist[i], XtNwidth, listWidth); i++;
465 XtSetArg(arglist[i], XtNheight, listHeight); i++;
466 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
467 XtSetArg(arglist[i], XtNfromHoriz, selFileLists[0]); i++;
468 XtSetArg(arglist[i], XtNfromVert, selFileHScroll); i++;
469 XtSetArg(arglist[i], XtNhorizDistance, listSpacing); i++;
470 XtSetArg(arglist[i], XtNvertDistance, 10); i++;
471 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
472 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
473 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
474 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
475 selFileLists[1] = XtCreateManagedWidget("selFileList2",
476 compositeWidgetClass, selFileForm, arglist, i);
479 XtSetArg(arglist[i], XtNwidth, listWidth); i++;
480 XtSetArg(arglist[i], XtNheight, listHeight); i++;
481 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
482 XtSetArg(arglist[i], XtNfromHoriz, selFileLists[1]); i++;
483 XtSetArg(arglist[i], XtNfromVert, selFileHScroll); i++;
484 XtSetArg(arglist[i], XtNhorizDistance, listSpacing); i++;
485 XtSetArg(arglist[i], XtNvertDistance, 10); i++;
486 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
487 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
488 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
489 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
490 selFileLists[2] = XtCreateManagedWidget("selFileList3",
491 compositeWidgetClass, selFileForm, arglist, i);
493 for (n = 0; n < NR; n++) {
496 XtSetArg(arglist[i], XtNx, vScrollX); i++;
497 XtSetArg(arglist[i], XtNy, vScrollY); i++;
498 XtSetArg(arglist[i], XtNwidth, scrollThickness); i++;
499 XtSetArg(arglist[i], XtNheight, SFvScrollHeight); i++;
500 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
501 selFileVScrolls[n] = XtCreateManagedWidget("selFileVScroll",
502 scrollbarWidgetClass, selFileLists[n], arglist, i);
504 XtAddCallback(selFileVScrolls[n], XtNjumpProc,
505 SFvFloatSliderMovedCallback, (XtPointer)(intptr_t) n);
506 XtAddCallback(selFileVScrolls[n], XtNscrollProc,
507 SFvAreaSelectedCallback, (XtPointer)(intptr_t) n);
511 XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);
513 XtSetArg(arglist[i], XtNx, hScrollX); i++;
514 XtSetArg(arglist[i], XtNy, hScrollY); i++;
515 XtSetArg(arglist[i], XtNwidth, SFhScrollWidth); i++;
516 XtSetArg(arglist[i], XtNheight, scrollThickness); i++;
517 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
518 selFileHScrolls[n] = XtCreateManagedWidget("selFileHScroll",
519 scrollbarWidgetClass, selFileLists[n], arglist, i);
521 XtAddCallback(selFileHScrolls[n], XtNjumpProc,
522 SFhSliderMovedCallback, (XtPointer)(intptr_t) n);
523 XtAddCallback(selFileHScrolls[n], XtNscrollProc,
524 SFhAreaSelectedCallback, (XtPointer)(intptr_t) n);
528 XtSetArg(arglist[i], XtNlabel, ok); i++;
529 XtSetArg(arglist[i], XtNresizable, True); i++;
530 XtSetArg(arglist[i], XtNcallback, SFokSelect); i++;
531 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
532 XtSetArg(arglist[i], XtNfromVert, selFileLists[0]); i++;
533 XtSetArg(arglist[i], XtNvertDistance, 30); i++;
534 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
535 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
536 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
537 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
538 selFileOK = XtCreateManagedWidget("selFileOK", commandWidgetClass,
539 selFileForm, arglist, i);
542 XtSetArg(arglist[i], XtNlabel, cancel); i++;
543 XtSetArg(arglist[i], XtNresizable, True); i++;
544 XtSetArg(arglist[i], XtNcallback, SFcancelSelect); i++;
545 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
546 XtSetArg(arglist[i], XtNfromHoriz, selFileOK); i++;
547 XtSetArg(arglist[i], XtNfromVert, selFileLists[0]); i++;
548 XtSetArg(arglist[i], XtNhorizDistance, 30); i++;
549 XtSetArg(arglist[i], XtNvertDistance, 30); i++;
550 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
551 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
552 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
553 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
554 selFileCancel = XtCreateManagedWidget("selFileCancel",
555 commandWidgetClass, selFileForm, arglist, i);
557 XtSetMappedWhenManaged(selFile, False);
558 XtRealizeWidget(selFile);
560 /* Add WM_DELETE_WINDOW protocol */
561 SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
562 XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);
566 xtermCursor = XCreateFontCursor(SFdisplay, XC_xterm);
568 sbRightArrowCursor = XCreateFontCursor(SFdisplay, XC_sb_right_arrow);
569 dotCursor = XCreateFontCursor(SFdisplay, XC_dot);
571 XDefineCursor(SFdisplay, XtWindow(selFileForm), xtermCursor);
572 XDefineCursor(SFdisplay, XtWindow(selFileField), xtermCursor);
573 XDefineCursor(SFdisplay, XtWindow(filterField), xtermCursor);
575 for (n = 0; n < NR; n++) {
576 XDefineCursor(SFdisplay, XtWindow(selFileLists[n]),
579 XDefineCursor(SFdisplay, XtWindow(selFileOK), dotCursor);
580 XDefineCursor(SFdisplay, XtWindow(selFileCancel), dotCursor);
582 for (n = 0; n < NR; n++) {
583 XtAddEventHandler(selFileLists[n], ExposureMask, True,
584 SFexposeList, (XtPointer)(intptr_t) n);
585 XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
586 SFenterList, (XtPointer)(intptr_t) n);
587 XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
588 SFleaveList, (XtPointer)(intptr_t) n);
589 XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
590 SFmotionList, (XtPointer)(intptr_t) n);
591 XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
592 SFbuttonPressList, (XtPointer)(intptr_t) n);
593 XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
594 SFbuttonReleaseList, (XtPointer)(intptr_t) n);
597 XtAddEventHandler(selFileField, KeyPressMask, False,
598 SFmodVerifyCallback, (XtPointer) NULL);
599 XtAddEventHandler(filterField, KeyReleaseMask, False,
600 SFmodVerifyCallback, (XtPointer) 1);
601 XtSetKeyboardFocus(selFileForm, selFileField);
603 SFapp = XtWidgetToApplicationContext(selFile);
607 /* position widget under the cursor */
614 Dimension width, height, b_width;
615 int x, y, max_x, max_y;
618 unsigned int dummymask;
620 XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &x, &y,
621 &dummyx, &dummyy, &dummymask);
623 XtSetArg(args[num_args], XtNwidth, &width); num_args++;
624 XtSetArg(args[num_args], XtNheight, &height); num_args++;
625 XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
626 XtGetValues(w, args, num_args);
628 width += 2 * b_width;
629 height += 2 * b_width;
631 x -= ( (Position) width/2 );
633 if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x;
635 y -= ( (Position) height/2 );
637 if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y;
640 XtSetArg(args[num_args], XtNx, x); num_args++;
641 XtSetArg(args[num_args], XtNy, y); num_args++;
642 XtSetValues(w, args, num_args);
646 SFopenFile(name, mode, prompt, failed)
656 if ((fp = fopen(name, mode)) == NULL) {
658 if (1) { // [HGM] always use strerror
659 buf = XtMalloc(strlen(failed) + strlen(strerror(errno)) +
662 strcat(buf, strerror(errno));
666 buf = XtMalloc(strlen(failed) + strlen(prompt) + 2);
671 XtSetArg(args[0], XtNlabel, buf);
672 XtSetValues(selFilePrompt, args, ONE);
683 if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~')) {
684 (void) strncpy(SFcurrentPath, SFtextBuffer, MAXPATHLEN);
686 SFtextPos = XawTextGetInsertionPoint(selFileField);
688 (void) strcat(strncpy(SFcurrentPath, SFstartDir, MAXPATHLEN), SFtextBuffer);
690 SFtextPos = XawTextGetInsertionPoint(selFileField) +
694 if (!SFworkProcAdded) {
695 (void) XtAppAddWorkProc(SFapp, SFworkProc, NULL);
706 return strcpy(XtMalloc((unsigned) (strlen(SFtextBuffer) + 1)),
713 SFstatus = SEL_FILE_NULL;
714 XtRemoveGrab(selFile);
715 XtUnmapWidget(selFile);
716 XtRemoveTimeOut(SFdirModTimerId);
717 if (SFchdir(SFstartDir)) {
720 "XsraSelFile: can't return to current directory"
727 XsraSelFile(toplevel, prompt, ok, cancel, failed,
728 init_path, filter, mode, show_entry, name_return)
740 static int firstTime = 1;
747 prompt = "Pathname:";
758 if(SFpathFlag != (mode && mode[0] == 'p') || strcmp(SFfilterBuffer, filter)) {
760 SFpathFlag = (mode && mode[0] == 'p'); // [HGM] ignore everything that is not a directory
765 SFdisplay = XtDisplay(toplevel);
766 SFcreateWidgets(toplevel, prompt, ok, cancel);
770 XtSetArg(arglist[i], XtNlabel, prompt); i++;
771 XtSetValues(selFilePrompt, arglist, i);
774 XtSetArg(arglist[i], XtNlabel, ok); i++;
775 XtSetValues(selFileOK, arglist, i);
778 XtSetArg(arglist[i], XtNlabel, cancel); i++;
779 XtSetValues(selFileCancel, arglist, i);
783 XtSetArg(arglist[i], XtNstring, filter); i++;
784 XtSetValues(filterField, arglist, i);
786 safeStrCpy(SFfilterBuffer, filter, MAXPATHLEN);
787 safeStrCpy(SFlastPath, SFtextBuffer, MAXPATHLEN); // remember for cancel
789 SFpositionWidget(selFile);
790 XtMapWidget(selFile);
792 #if defined(SVR4) || defined(SYSV) || defined(USG) || 1
793 if (!getcwd(SFstartDir, MAXPATHLEN)) { // [HGM] always do this, as I do not know when exactly to do it
794 #else /* defined(SVR4) || defined(SYSV) || defined(USG) */
795 if (!getwd(SFstartDir)) {
796 #endif /* defined(SVR4) || defined(SYSV) || defined(USG) */
798 XtAppError(SFapp, "XsraSelFile: can't get current directory");
800 (void) strcat(SFstartDir, "/");
801 (void) strncpy(SFcurrentDir, SFstartDir, MAXPATHLEN);
804 if (init_path[0] == '/') {
805 (void) strncpy(SFcurrentPath, init_path, MAXPATHLEN);
811 SFsetText(SFcurrentPath);
813 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
816 (void) strcat(strncpy(SFcurrentPath, SFstartDir, MAXPATHLEN),
818 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
821 (void) strncpy(SFcurrentPath, SFstartDir, MAXPATHLEN);
828 XtAddGrab(selFile, True, True);
830 SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
831 SFdirModTimer, (XtPointer) NULL);
834 XtAppNextEvent(SFapp, &event);
835 XtDispatchEvent(&event);
838 SFstatus = SEL_FILE_NULL;
842 *name_return = SFgetText();
843 if(mode && (mode[0] == 'p' || mode[0] == 'f')) { // [HGM] for use in file-option browse button
847 if (fp = SFopenFile(*name_return, mode,
852 SFstatus = SEL_FILE_NULL;
854 case SEL_FILE_CANCEL:
856 SFsetText(SFlastPath);