1 /*
2 * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
3 *
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.
13 *
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.
21 *
22 * Author: Erik M. van der Poel
23 * Software Research Associates, Inc., Tokyo, Japan
24 * erik@sra.co.jp
25 */
26
27 /*
28 * Author's address:
29 *
30 * erik@sra.co.jp
31 * OR
32 * erik%sra.co.jp@uunet.uu.net
33 * OR
34 * erik%sra.co.jp@mcvax.uucp
35 * OR
36 * try junet instead of co.jp
37 * OR
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
42 */
43
44 #include <stdio.h>
45 #include <errno.h>
46
47 #include <sys/param.h>
48 #include <X11/cursorfont.h>
49 #include <X11/Intrinsic.h>
50 #include <X11/StringDefs.h>
51 #include <X11/Composite.h>
52 #include <X11/Shell.h>
53 #include <X11/Xaw/Form.h>
54 #include <X11/Xaw/Command.h>
55 #include <X11/Xaw/Scrollbar.h>
56 #include <X11/Xaw/Label.h>
57
58 #include "SFinternal.h"
59
60 #ifndef MAXPATHLEN
61 #define MAXPATHLEN 1024
62 #endif /* ndef MAXPATHLEN */
63
64 int SFstatus = SEL_FILE_NULL;
65
66 char
67 SFstartDir[MAXPATHLEN],
68 SFcurrentPath[MAXPATHLEN],
69 SFcurrentDir[MAXPATHLEN];
70
71 Widget
72 selFile,
73 selFileCancel,
74 selFileField,
75 selFileForm,
76 selFileHScroll,
77 selFileHScrolls[3],
78 selFileLists[3],
79 selFileOK,
80 selFilePrompt,
81 selFileVScrolls[3];
82
83 Display *SFdisplay;
84
85 Pixel SFfore, SFback;
86
87 Atom SFwmDeleteWindow;
88
89 XSegment SFsegs[2], SFcompletionSegs[2];
90
91 XawTextPosition SFtextPos;
92
93 int SFupperX, SFlowerY, SFupperY;
94
95 int SFtextX, SFtextYoffset;
96
97 int SFentryWidth, SFentryHeight;
98
99 int SFlineToTextH = 3;
100
101 int SFlineToTextV = 3;
102
103 int SFbesideText = 3;
104
105 int SFaboveAndBelowText = 2;
106
107 int SFcharsPerEntry = 15;
108
109 int SFlistSize = 10;
110
111 int SFworkProcAdded = 0;
112
113 XtAppContext SFapp;
114
115 int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
116
117 char SFtextBuffer[MAXPATHLEN];
118
119 XtIntervalId SFdirModTimerId;
120
121 int (*SFfunc)();
122
123 static char *oneLineTextEditTranslations = "\
124 <Key>Return: redraw-display()\n\
125 Ctrl<Key>M: redraw-display()\n\
126 ";
127
128 /* ARGSUSED */
129 static void
SFexposeList(w,n,event)130 SFexposeList(w, n, event)
131 Widget w;
132 int n;
133 XExposeEvent *event;
134 {
135 if ((event->type == NoExpose) || event->count) {
136 return;
137 }
138
139 SFdrawList(n, SF_DO_NOT_SCROLL);
140 }
141
142 /* ARGSUSED */
143 static void
SFmodVerifyCallback(w,client_data,event)144 SFmodVerifyCallback(w, client_data, event)
145 Widget w;
146 XtPointer client_data;
147 XKeyPressedEvent *event;
148 {
149 char buf[2];
150
151 if (
152 (XLookupString(event, buf, 2, NULL, NULL) == 1) &&
153 ((*buf) == '\r')
154 ) {
155 SFstatus = SEL_FILE_OK;
156 } else {
157 SFstatus = SEL_FILE_TEXT;
158 }
159 }
160
161 /* ARGSUSED */
162 static void
SFokCallback(w)163 SFokCallback(w)
164 Widget w;
165 {
166 SFstatus = SEL_FILE_OK;
167 }
168
169 static XtCallbackRec SFokSelect[] = {
170 { SFokCallback, (XtPointer) NULL },
171 { NULL, (XtPointer) NULL },
172 };
173
174 /* ARGSUSED */
175 static void
SFcancelCallback(w)176 SFcancelCallback(w)
177 Widget w;
178 {
179 SFstatus = SEL_FILE_CANCEL;
180 }
181
182 static XtCallbackRec SFcancelSelect[] = {
183 { SFcancelCallback, (XtPointer) NULL },
184 { NULL, (XtPointer) NULL },
185 };
186
187 /* ARGSUSED */
188 static void
SFdismissAction(w,event,params,num_params)189 SFdismissAction(w, event, params, num_params)
190 Widget w;
191 XEvent *event;
192 String *params;
193 Cardinal *num_params;
194 {
195 if (event->type == ClientMessage &&
196 event->xclient.data.l[0] != SFwmDeleteWindow) return;
197
198 SFstatus = SEL_FILE_CANCEL;
199 }
200
201 static char *wmDeleteWindowTranslation = "\
202 <Message>WM_PROTOCOLS: SelFileDismiss()\n\
203 ";
204
205 static XtActionsRec actions[] = {
206 {"SelFileDismiss", SFdismissAction},
207 };
208
209 static void
SFcreateWidgets(toplevel,prompt,ok,cancel)210 SFcreateWidgets(toplevel, prompt, ok, cancel)
211 Widget toplevel;
212 char *prompt;
213 char *ok;
214 char *cancel;
215 {
216 int i, n;
217 int listWidth, listHeight;
218 int listSpacing = 10;
219 int scrollThickness = 15;
220 int hScrollX, hScrollY;
221 int vScrollX, vScrollY;
222 Cursor
223 xtermCursor,
224 sbRightArrowCursor,
225 dotCursor;
226 Arg arglist[20];
227
228 i = 0;
229 XtSetArg(arglist[i], XtNtransientFor, toplevel); i++;
230
231 selFile = XtAppCreateShell("selFile", "SelFile",
232 transientShellWidgetClass, SFdisplay, arglist, i);
233
234 /* Add WM_DELETE_WINDOW protocol */
235 XtAppAddActions(XtWidgetToApplicationContext(selFile),
236 actions, XtNumber(actions));
237 XtOverrideTranslations(selFile,
238 XtParseTranslationTable(wmDeleteWindowTranslation));
239
240 i = 0;
241 XtSetArg(arglist[i], XtNdefaultDistance, 30); i++;
242 selFileForm = XtCreateManagedWidget("selFileForm",
243 formWidgetClass, selFile, arglist, i);
244
245 i = 0;
246 XtSetArg(arglist[i], XtNlabel, prompt); i++;
247 XtSetArg(arglist[i], XtNresizable, True); i++;
248 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
249 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
250 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
251 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
252 XtSetArg(arglist[i], XtNborderWidth, 0); i++;
253 selFilePrompt = XtCreateManagedWidget("selFilePrompt",
254 labelWidgetClass, selFileForm, arglist, i);
255
256 i = 0;
257 XtSetArg(arglist[i], XtNforeground, &SFfore); i++;
258 XtSetArg(arglist[i], XtNbackground, &SFback); i++;
259 XtGetValues(selFilePrompt, arglist, i);
260
261 SFinitFont();
262
263 SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth +
264 SFbesideText;
265 SFentryHeight = SFaboveAndBelowText + SFcharHeight +
266 SFaboveAndBelowText;
267
268 listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
269 scrollThickness;
270 listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
271 SFlineToTextV + SFlistSize * SFentryHeight +
272 SFlineToTextV + 1 + scrollThickness;
273
274 SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4;
275
276 hScrollX = -1;
277 hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
278 SFlineToTextV + SFlistSize * SFentryHeight +
279 SFlineToTextV;
280 SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
281
282 vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
283 vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
284 SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
285 SFlineToTextV;
286
287 SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
288 SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
289 SFlineToTextV;
290 SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
291 SFlineToTextV + SFlistSize * SFentryHeight - 1;
292
293 SFtextX = SFlineToTextH + SFbesideText;
294 SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
295
296 SFsegs[0].x1 = 0;
297 SFsegs[0].y1 = vScrollY;
298 SFsegs[0].x2 = vScrollX - 1;
299 SFsegs[0].y2 = vScrollY;
300 SFsegs[1].x1 = vScrollX;
301 SFsegs[1].y1 = 0;
302 SFsegs[1].x2 = vScrollX;
303 SFsegs[1].y2 = vScrollY - 1;
304
305 SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
306 SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
307 SFlineToTextH + SFentryWidth - 1;
308
309 i = 0;
310 XtSetArg(arglist[i], XtNwidth, 3 * listWidth + 2 * listSpacing + 4);
311 i++;
312 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
313
314 XtSetArg(arglist[i], XtNfromVert, selFilePrompt); i++;
315 XtSetArg(arglist[i], XtNvertDistance, 10); i++;
316 XtSetArg(arglist[i], XtNresizable, True); i++;
317 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
318 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
319 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
320 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
321 XtSetArg(arglist[i], XtNstring, SFtextBuffer); i++;
322 XtSetArg(arglist[i], XtNlength, MAXPATHLEN); i++;
323 XtSetArg(arglist[i], XtNeditType, XawtextEdit); i++;
324 XtSetArg(arglist[i], XtNwrap, XawtextWrapWord); i++;
325 XtSetArg(arglist[i], XtNresize, XawtextResizeHeight); i++;
326 XtSetArg(arglist[i], XtNuseStringInPlace, True); i++;
327 selFileField = XtCreateManagedWidget("selFileField",
328 asciiTextWidgetClass, selFileForm, arglist, i);
329
330 XtOverrideTranslations(selFileField,
331 XtParseTranslationTable(oneLineTextEditTranslations));
332 XtSetKeyboardFocus(selFileForm, selFileField);
333
334 i = 0;
335 XtSetArg(arglist[i], XtNorientation, XtorientHorizontal); i++;
336 XtSetArg(arglist[i], XtNwidth, SFpathScrollWidth); i++;
337 XtSetArg(arglist[i], XtNheight, scrollThickness); i++;
338 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
339 XtSetArg(arglist[i], XtNfromVert, selFileField); i++;
340 XtSetArg(arglist[i], XtNvertDistance, 30); i++;
341 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
342 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
343 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
344 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
345 selFileHScroll = XtCreateManagedWidget("selFileHScroll",
346 scrollbarWidgetClass, selFileForm, arglist, i);
347
348 XtAddCallback(selFileHScroll, XtNjumpProc,
349 SFpathSliderMovedCallback, (XtPointer) NULL);
350 XtAddCallback(selFileHScroll, XtNscrollProc,
351 SFpathAreaSelectedCallback, (XtPointer) NULL);
352
353 i = 0;
354 XtSetArg(arglist[i], XtNwidth, listWidth); i++;
355 XtSetArg(arglist[i], XtNheight, listHeight); i++;
356 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
357 XtSetArg(arglist[i], XtNfromVert, selFileHScroll); i++;
358 XtSetArg(arglist[i], XtNvertDistance, 10); i++;
359 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
360 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
361 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
362 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
363 selFileLists[0] = XtCreateManagedWidget("selFileList1",
364 compositeWidgetClass, selFileForm, arglist, i);
365
366 i = 0;
367 XtSetArg(arglist[i], XtNwidth, listWidth); i++;
368 XtSetArg(arglist[i], XtNheight, listHeight); i++;
369 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
370 XtSetArg(arglist[i], XtNfromHoriz, selFileLists[0]); i++;
371 XtSetArg(arglist[i], XtNfromVert, selFileHScroll); i++;
372 XtSetArg(arglist[i], XtNhorizDistance, listSpacing); i++;
373 XtSetArg(arglist[i], XtNvertDistance, 10); i++;
374 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
375 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
376 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
377 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
378 selFileLists[1] = XtCreateManagedWidget("selFileList2",
379 compositeWidgetClass, selFileForm, arglist, i);
380
381 i = 0;
382 XtSetArg(arglist[i], XtNwidth, listWidth); i++;
383 XtSetArg(arglist[i], XtNheight, listHeight); i++;
384 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
385 XtSetArg(arglist[i], XtNfromHoriz, selFileLists[1]); i++;
386 XtSetArg(arglist[i], XtNfromVert, selFileHScroll); i++;
387 XtSetArg(arglist[i], XtNhorizDistance, listSpacing); i++;
388 XtSetArg(arglist[i], XtNvertDistance, 10); i++;
389 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
390 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
391 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
392 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
393 selFileLists[2] = XtCreateManagedWidget("selFileList3",
394 compositeWidgetClass, selFileForm, arglist, i);
395
396 for (n = 0; n < 3; n++) {
397
398 i = 0;
399 XtSetArg(arglist[i], XtNx, vScrollX); i++;
400 XtSetArg(arglist[i], XtNy, vScrollY); i++;
401 XtSetArg(arglist[i], XtNwidth, scrollThickness); i++;
402 XtSetArg(arglist[i], XtNheight, SFvScrollHeight); i++;
403 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
404 selFileVScrolls[n] = XtCreateManagedWidget("selFileVScroll",
405 scrollbarWidgetClass, selFileLists[n], arglist, i);
406
407 XtAddCallback(selFileVScrolls[n], XtNjumpProc,
408 SFvFloatSliderMovedCallback, (XtPointer) n);
409 XtAddCallback(selFileVScrolls[n], XtNscrollProc,
410 SFvAreaSelectedCallback, (XtPointer) n);
411
412 i = 0;
413
414 XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);
415 i++;
416 XtSetArg(arglist[i], XtNx, hScrollX); i++;
417 XtSetArg(arglist[i], XtNy, hScrollY); i++;
418 XtSetArg(arglist[i], XtNwidth, SFhScrollWidth); i++;
419 XtSetArg(arglist[i], XtNheight, scrollThickness); i++;
420 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
421 selFileHScrolls[n] = XtCreateManagedWidget("selFileHScroll",
422 scrollbarWidgetClass, selFileLists[n], arglist, i);
423
424 XtAddCallback(selFileHScrolls[n], XtNjumpProc,
425 SFhSliderMovedCallback, (XtPointer) n);
426 XtAddCallback(selFileHScrolls[n], XtNscrollProc,
427 SFhAreaSelectedCallback, (XtPointer) n);
428 }
429
430 i = 0;
431 XtSetArg(arglist[i], XtNlabel, ok); i++;
432 XtSetArg(arglist[i], XtNresizable, True); i++;
433 XtSetArg(arglist[i], XtNcallback, SFokSelect); i++;
434 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
435 XtSetArg(arglist[i], XtNfromVert, selFileLists[0]); i++;
436 XtSetArg(arglist[i], XtNvertDistance, 30); i++;
437 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
438 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
439 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
440 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
441 selFileOK = XtCreateManagedWidget("selFileOK", commandWidgetClass,
442 selFileForm, arglist, i);
443
444 i = 0;
445 XtSetArg(arglist[i], XtNlabel, cancel); i++;
446 XtSetArg(arglist[i], XtNresizable, True); i++;
447 XtSetArg(arglist[i], XtNcallback, SFcancelSelect); i++;
448 XtSetArg(arglist[i], XtNborderColor, SFfore); i++;
449 XtSetArg(arglist[i], XtNfromHoriz, selFileOK); i++;
450 XtSetArg(arglist[i], XtNfromVert, selFileLists[0]); i++;
451 XtSetArg(arglist[i], XtNhorizDistance, 30); i++;
452 XtSetArg(arglist[i], XtNvertDistance, 30); i++;
453 XtSetArg(arglist[i], XtNtop, XtChainTop); i++;
454 XtSetArg(arglist[i], XtNbottom, XtChainTop); i++;
455 XtSetArg(arglist[i], XtNleft, XtChainLeft); i++;
456 XtSetArg(arglist[i], XtNright, XtChainLeft); i++;
457 selFileCancel = XtCreateManagedWidget("selFileCancel",
458 commandWidgetClass, selFileForm, arglist, i);
459
460 XtSetMappedWhenManaged(selFile, False);
461 XtRealizeWidget(selFile);
462
463 /* Add WM_DELETE_WINDOW protocol */
464 SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
465 XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);
466
467 SFcreateGC();
468
469 xtermCursor = XCreateFontCursor(SFdisplay, XC_xterm);
470
471 sbRightArrowCursor = XCreateFontCursor(SFdisplay, XC_sb_right_arrow);
472 dotCursor = XCreateFontCursor(SFdisplay, XC_dot);
473
474 XDefineCursor(SFdisplay, XtWindow(selFileForm), xtermCursor);
475 XDefineCursor(SFdisplay, XtWindow(selFileField), xtermCursor);
476
477 for (n = 0; n < 3; n++) {
478 XDefineCursor(SFdisplay, XtWindow(selFileLists[n]),
479 sbRightArrowCursor);
480 }
481 XDefineCursor(SFdisplay, XtWindow(selFileOK), dotCursor);
482 XDefineCursor(SFdisplay, XtWindow(selFileCancel), dotCursor);
483
484 for (n = 0; n < 3; n++) {
485 XtAddEventHandler(selFileLists[n], ExposureMask, True,
486 SFexposeList, (XtPointer) n);
487 XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
488 SFenterList, (XtPointer) n);
489 XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
490 SFleaveList, (XtPointer) n);
491 XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
492 SFmotionList, (XtPointer) n);
493 XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
494 SFbuttonPressList, (XtPointer) n);
495 XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
496 SFbuttonReleaseList, (XtPointer) n);
497 }
498
499 XtAddEventHandler(selFileField, KeyPressMask, False,
500 SFmodVerifyCallback, (XtPointer) NULL);
501
502 SFapp = XtWidgetToApplicationContext(selFile);
503
504 }
505
506 /* position widget under the cursor */
507 void
SFpositionWidget(w)508 SFpositionWidget(w)
509 Widget w;
510 {
511 Arg args[3];
512 Cardinal num_args;
513 Dimension width, height, b_width;
514 int x, y, max_x, max_y;
515 Window root, child;
516 int dummyx, dummyy;
517 unsigned int dummymask;
518
519 XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &x, &y,
520 &dummyx, &dummyy, &dummymask);
521 num_args = 0;
522 XtSetArg(args[num_args], XtNwidth, &width); num_args++;
523 XtSetArg(args[num_args], XtNheight, &height); num_args++;
524 XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
525 XtGetValues(w, args, num_args);
526
527 width += 2 * b_width;
528 height += 2 * b_width;
529
530 x -= ( (Position) width/2 );
531 if (x < 0) x = 0;
532 if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x;
533
534 y -= ( (Position) height/2 );
535 if (y < 0) y = 0;
536 if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y;
537
538 num_args = 0;
539 XtSetArg(args[num_args], XtNx, x); num_args++;
540 XtSetArg(args[num_args], XtNy, y); num_args++;
541 XtSetValues(w, args, num_args);
542 }
543
544 FILE *
SFopenFile(name,mode,prompt,failed)545 SFopenFile(name, mode, prompt, failed)
546 char *name;
547 char *mode;
548 char *prompt;
549 char *failed;
550 {
551 Arg args[1];
552 FILE *fp;
553
554 SFchdir(SFstartDir);
555 if ((fp = fopen(name, mode)) == NULL) {
556 char *buf;
557 buf = XtMalloc(strlen(failed) + strlen(strerror(errno))
558 + strlen(prompt) + 2);
559 strcpy(buf, failed);
560 strcat(buf, strerror(errno));
561 strcat(buf, "\n");
562 strcat(buf, prompt);
563
564 XtSetArg(args[0], XtNlabel, buf);
565 XtSetValues(selFilePrompt, args, 1);
566 XtFree(buf);
567 return NULL;
568 }
569 return fp;
570 }
571
SFtextChanged()572 SFtextChanged()
573 {
574
575 if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~')) {
576 (void) strcpy(SFcurrentPath, SFtextBuffer);
577
578 SFtextPos = XawTextGetInsertionPoint(selFileField);
579 } else {
580 (void) strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer);
581
582 SFtextPos = XawTextGetInsertionPoint(selFileField) +
583 strlen(SFstartDir);
584 }
585
586 if (!SFworkProcAdded) {
587 (void) XtAppAddWorkProc(SFapp, SFworkProc, NULL);
588 SFworkProcAdded = 1;
589 }
590
591 SFupdatePath();
592 }
593
594 static char *
SFgetText()595 SFgetText()
596 {
597 return strcpy(XtMalloc((unsigned) (strlen(SFtextBuffer) + 1)),
598 SFtextBuffer);
599 }
600
601 static
SFprepareToReturn()602 SFprepareToReturn()
603 {
604 SFstatus = SEL_FILE_NULL;
605 XtRemoveGrab(selFile);
606 XtUnmapWidget(selFile);
607 XtRemoveTimeOut(SFdirModTimerId);
608 if (SFchdir(SFstartDir)) {
609 XtAppError(
610 SFapp,
611 "XsraSelFile: can't return to current directory"
612 );
613 }
614 }
615
616 FILE *
XsraSelFile(toplevel,prompt,ok,cancel,failed,init_path,mode,show_entry,name_return)617 XsraSelFile(toplevel, prompt, ok, cancel, failed,
618 init_path, mode, show_entry, name_return)
619 Widget toplevel;
620 char *prompt;
621 char *ok;
622 char *cancel;
623 char *failed;
624 char *init_path;
625 char *mode;
626 int (*show_entry)();
627 char **name_return;
628 {
629 static int firstTime = 1;
630 int i;
631 Arg arglist[20];
632 XEvent event;
633 FILE *fp;
634
635 if (!prompt) {
636 prompt = "Pathname:";
637 }
638
639 if (!ok) {
640 ok = "OK";
641 }
642
643 if (!cancel) {
644 cancel = "Cancel";
645 }
646
647 if (firstTime) {
648 firstTime = 0;
649 SFdisplay = XtDisplay(toplevel);
650 SFcreateWidgets(toplevel, prompt, ok, cancel);
651 } else {
652 i = 0;
653
654 XtSetArg(arglist[i], XtNlabel, prompt); i++;
655 XtSetValues(selFilePrompt, arglist, i);
656
657 i = 0;
658 XtSetArg(arglist[i], XtNlabel, ok); i++;
659 XtSetValues(selFileOK, arglist, i);
660
661 i = 0;
662 XtSetArg(arglist[i], XtNlabel, cancel); i++;
663 XtSetValues(selFileCancel, arglist, i);
664 }
665
666 SFpositionWidget(selFile);
667 XtMapWidget(selFile);
668
669 if (!getcwd(SFstartDir, MAXPATHLEN)) {
670 XtAppError(SFapp, "XsraSelFile: can't get current directory");
671 }
672 (void) strcat(SFstartDir, "/");
673 (void) strcpy(SFcurrentDir, SFstartDir);
674
675 if (init_path) {
676 if (init_path[0] == '/') {
677 (void) strcpy(SFcurrentPath, init_path);
678 if (strncmp(
679 SFcurrentPath,
680 SFstartDir,
681 strlen(SFstartDir)
682 )) {
683 SFsetText(SFcurrentPath);
684 } else {
685 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
686 }
687 } else {
688 (void) strcat(strcpy(SFcurrentPath, SFstartDir),
689 init_path);
690 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
691 }
692 } else {
693 (void) strcpy(SFcurrentPath, SFstartDir);
694 }
695
696 SFfunc = show_entry;
697
698 SFtextChanged();
699
700 XtAddGrab(selFile, True, True);
701
702 SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
703 SFdirModTimer, (XtPointer) NULL);
704
705 while (1) {
706 XtAppNextEvent(SFapp, &event);
707 XtDispatchEvent(&event);
708 switch (SFstatus) {
709 case SEL_FILE_TEXT:
710 SFstatus = SEL_FILE_NULL;
711 SFtextChanged();
712 break;
713 case SEL_FILE_OK:
714 *name_return = SFgetText();
715 if (fp = SFopenFile(*name_return, mode,
716 prompt, failed)) {
717 SFprepareToReturn();
718 return fp;
719 }
720 SFstatus = SEL_FILE_NULL;
721 break;
722 case SEL_FILE_CANCEL:
723 SFprepareToReturn();
724 return NULL;
725 case SEL_FILE_NULL:
726 break;
727 }
728 }
729 }
730