PageRenderTime 57ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/texlive-2007/texk/xdvik/gui/sfSelFile.c

#
C | 1071 lines | 841 code | 137 blank | 93 comment | 110 complexity | 13c4aa5974608d940d10245b149670d1 MD5 | raw file
Possible License(s): AGPL-1.0, BSD-3-Clause, LGPL-3.0, GPL-2.0, CPL-1.0, LGPL-2.1, LGPL-2.0
  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. #include "xdvi-config.h"
  27. #include "xdvi.h"
  28. #include "dvi-init.h" /* for dviErrFlagT */
  29. #include "message-window.h"
  30. #include "kpathsea/c-stat.h"
  31. #include <string.h>
  32. #include "sfDir.h"
  33. #include "sfPath.h"
  34. #include "sfDraw.h"
  35. #include "sfSelFile.h"
  36. #include "util.h"
  37. #include <ctype.h>
  38. #include "kpathsea/c-fopen.h"
  39. #include "kpathsea/c-stat.h"
  40. #if !defined(MOTIF) /* entire file */
  41. #include <errno.h>
  42. #ifdef X_NOT_STDC_ENV
  43. extern int errno;
  44. #endif
  45. #define SEL_FILE_CANCEL -1
  46. #define SEL_FILE_OK 0
  47. #define SEL_FILE_NULL 1
  48. #define SEL_FILE_TEXT 2
  49. /*
  50. * Author's address:
  51. *
  52. * erik@sra.co.jp
  53. * OR
  54. * erik%sra.co.jp@uunet.uu.net
  55. * OR
  56. * erik%sra.co.jp@mcvax.uucp
  57. * OR
  58. * try junet instead of co.jp
  59. * OR
  60. * Erik M. van der Poel
  61. * Software Research Associates, Inc.
  62. * 1-1-1 Hirakawa-cho, Chiyoda-ku
  63. * Tokyo 102 Japan. TEL +81-3-234-2692
  64. */
  65. #include <sys/param.h>
  66. #include <X11/cursorfont.h>
  67. #include <X11/Intrinsic.h>
  68. #include <X11/StringDefs.h>
  69. #include <X11/Composite.h>
  70. #include <X11/Shell.h>
  71. #include <X11/Xaw/Paned.h>
  72. #include <X11/Xaw/Text.h>
  73. #include <X11/Xaw/AsciiText.h>
  74. #include <X11/Xaw/Form.h>
  75. #include <X11/Xaw/Command.h>
  76. #include <X11/Xaw/Scrollbar.h>
  77. #include <X11/Xaw/Label.h>
  78. #include <X11/Xaw/Cardinals.h>
  79. #ifndef MAXPATHLEN
  80. #define MAXPATHLEN 1024
  81. #endif /* ndef MAXPATHLEN */
  82. /* global vars for communication with sfDraw.c */
  83. char SFstartDir[MAXPATHLEN], SFcurrentPath[MAXPATHLEN], SFcurrentDir[MAXPATHLEN];
  84. Widget selFileField, selFileForm, selFileHScroll, selFileHScrolls[3], selFileLists[3], selFileVScrolls[3];
  85. Display *SFdisplay;
  86. Pixel SFfore, SFback;
  87. XSegment SFsegs[2], SFcompletionSegs[2];
  88. XawTextPosition SFtextPos;
  89. int SFupperX, SFlowerY, SFupperY;
  90. int SFtextX, SFtextYoffset;
  91. int SFentryWidth, SFentryHeight;
  92. int SFlineToTextH = 3;
  93. int SFlineToTextV = 3;
  94. int SFbesideText = 3;
  95. int SFaboveAndBelowText = 2;
  96. int SFcharsPerEntry = 15;
  97. int SFlistSize = 10;
  98. int SFworkProcAdded = 0;
  99. XtAppContext SFapp;
  100. int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
  101. char SFtextBuffer[MAXPATHLEN];
  102. XtIntervalId SFdirModTimerId;
  103. int (*SFfunc) ();
  104. static int SFstatus = SEL_FILE_NULL;
  105. static Widget selFile, selFileCancel, selFileOK, selFilePrompt;
  106. /* For file filter. */
  107. static Widget selFileLabel, selFileMask, selFileHide;
  108. #define MASKWIDTH 16
  109. static char fileMask[MASKWIDTH + 2] = "*.dvi";
  110. static Atom SFwmDeleteWindow;
  111. static char *oneLineTextEditTranslations =
  112. "<Key>Return: redraw-display()\n"
  113. "Ctrl<Key>M: redraw-display()\n";
  114. #if !defined (HAVE_STRERROR) && !defined (strerror)
  115. static char *
  116. strerror(int errnum)
  117. {
  118. return 0 < errnum && errnum <= sys_nerr
  119. ? sys_errlist[errnum] : "Unknown system error";
  120. }
  121. #endif /* not HAVE_STRERROR && not strerror */
  122. void
  123. raise_file_selector(void)
  124. {
  125. if (selFile != 0) {
  126. XRaiseWindow(DISP, XtWindow(selFile));
  127. }
  128. }
  129. static void
  130. SFexposeList(Widget w, XtPointer n, XEvent *event, Boolean *cont)
  131. {
  132. UNUSED(w);
  133. UNUSED(cont);
  134. if ((event->type == NoExpose) || event->xexpose.count) {
  135. return;
  136. }
  137. SFdrawList((int)n, SF_DO_NOT_SCROLL);
  138. }
  139. static void
  140. SFmodVerifyCallback(Widget w, XtPointer client_data, XEvent *event, Boolean *cont)
  141. {
  142. char buf[2];
  143. UNUSED(w);
  144. UNUSED(client_data);
  145. UNUSED(cont);
  146. if ((XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) &&
  147. ((*buf) == '\r')) {
  148. SFstatus = SEL_FILE_OK;
  149. }
  150. else {
  151. SFstatus = SEL_FILE_TEXT;
  152. }
  153. }
  154. static void
  155. SFokCallback(Widget w, XtPointer cl, XtPointer cd)
  156. {
  157. UNUSED(w);
  158. UNUSED(cl);
  159. UNUSED(cd);
  160. SFstatus = SEL_FILE_OK;
  161. }
  162. static XtCallbackRec SFokSelect[] = {
  163. {SFokCallback, (XtPointer) NULL},
  164. {NULL, (XtPointer) NULL},
  165. };
  166. static void
  167. SFcancelCallback(Widget w, XtPointer cl, XtPointer cd)
  168. {
  169. UNUSED(w);
  170. UNUSED(cl);
  171. UNUSED(cd);
  172. SFstatus = SEL_FILE_CANCEL;
  173. }
  174. static XtCallbackRec SFcancelSelect[] = {
  175. {SFcancelCallback, (XtPointer) NULL},
  176. {NULL, (XtPointer) NULL},
  177. };
  178. static void
  179. SFdismissAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
  180. {
  181. UNUSED(w);
  182. UNUSED(params);
  183. UNUSED(num_params);
  184. if (event->type == ClientMessage && (unsigned)(event->xclient.data.l[0]) != SFwmDeleteWindow)
  185. return;
  186. SFstatus = SEL_FILE_CANCEL;
  187. }
  188. static char *wmDeleteWindowTranslation = "<Message>WM_PROTOCOLS: SelFileDismiss()\n";
  189. static XtActionsRec sf_actions[] = {
  190. {"SelFileDismiss", SFdismissAction},
  191. };
  192. /* Don't show files that don't get through the filter. */
  193. /* return 1 if file is masked (mask does not match filename), 0 otherwise */
  194. static int
  195. maskFile(const char *mask, char *filename)
  196. {
  197. int c, c1;
  198. while ((c = *mask++)) {
  199. if (c == '*') {
  200. while ((c1 = *mask++)) {
  201. if (c1 != '*') {
  202. if (!(*filename))
  203. return 1;
  204. if (c1 != '?') {
  205. while ((filename = strchr(filename, c1))) {
  206. if (!maskFile(mask, ++filename))
  207. return 0;
  208. }
  209. return 1;
  210. }
  211. else
  212. filename++;
  213. }
  214. }
  215. return 0;
  216. }
  217. if (c == '?') {
  218. if (!*filename)
  219. return 1;
  220. }
  221. else if (c != *filename)
  222. return 1;
  223. filename++;
  224. }
  225. return (*filename) ? 1 : 0;
  226. }
  227. Boolean hideFlag = False;
  228. static int
  229. showEntry(char *entryReal, char **entryShown, struct stat *statBuf)
  230. {
  231. UNUSED(entryShown);
  232. if ((hideFlag && entryReal[0] == '.') || (!S_ISDIR(statBuf->st_mode) && maskFile(fileMask, entryReal)))
  233. return 0;
  234. entryReal[strlen(entryReal)] = SFstatChar(statBuf);
  235. return 1;
  236. }
  237. static void
  238. maskChanged(Widget w, XtPointer client_data, XEvent *call_data, Boolean *cont)
  239. {
  240. char buf[2];
  241. SFDir *dir;
  242. UNUSED(w);
  243. UNUSED(client_data);
  244. UNUSED(cont);
  245. if ((XLookupString((XKeyPressedEvent *)call_data, buf, 2, NULL, NULL) == 1) && ((*buf) == '\r')) {
  246. for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
  247. *(dir->dir) = 0; /* force a re-read */
  248. SFupdatePath();
  249. }
  250. }
  251. static void
  252. hideFiles(Widget w, XtPointer client_data, XtPointer call_data)
  253. {
  254. SFDir *dir;
  255. SFEntry *entry;
  256. UNUSED(client_data);
  257. UNUSED(call_data);
  258. hideFlag = !hideFlag;
  259. if (hideFlag) {
  260. XtVaSetValues(w, XtNlabel, "hidden", NULL);
  261. for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) {
  262. if (!(dir->nEntries))
  263. continue;
  264. dir->vOrigin = 0;
  265. for (entry = &(dir->entries[dir->nEntries - 1]);
  266. entry >= dir->entries; entry--)
  267. entry->statDone = 0;
  268. SFdrawLists(SF_DO_SCROLL);
  269. }
  270. }
  271. else {
  272. XtVaSetValues(w, XtNlabel, "shown", NULL);
  273. for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
  274. *(dir->dir) = 0; /* force a re-read */
  275. SFupdatePath();
  276. }
  277. }
  278. static Widget
  279. SFcreateWidgets(Widget parent, const char *title, const char *prompt, const char *ok, const char *cancel)
  280. {
  281. Cardinal i, n;
  282. int listWidth, listHeight;
  283. int listSpacing = 10;
  284. int scrollThickness = 15;
  285. int hScrollX, hScrollY;
  286. int vScrollX, vScrollY;
  287. Cursor xtermCursor, sbRightArrowCursor, arrowCursor;
  288. Arg arglist[20];
  289. Widget paned, box;
  290. i = 0;
  291. XtSetArg(arglist[i], XtNtransientFor, parent);
  292. XtSetArg(arglist[i], XtNtitle, title);
  293. i++;
  294. selFile = XtAppCreateShell("xdviSelFile", "XdviSelFile",
  295. transientShellWidgetClass, SFdisplay,
  296. arglist, i);
  297. /* Add WM_DELETE_WINDOW protocol */
  298. XtAppAddActions(XtWidgetToApplicationContext(selFile),
  299. sf_actions, XtNumber(sf_actions));
  300. XtOverrideTranslations(selFile,
  301. XtParseTranslationTable(wmDeleteWindowTranslation));
  302. paned = XtVaCreateManagedWidget("paned", panedWidgetClass, selFile, NULL);
  303. i = 0;
  304. XtSetArg(arglist[i], XtNdefaultDistance, 6);
  305. i++;
  306. selFileForm = XtCreateManagedWidget("selFileForm",
  307. formWidgetClass, paned, arglist, i);
  308. i = 0;
  309. XtSetArg(arglist[i], XtNlabel, prompt);
  310. i++;
  311. XtSetArg(arglist[i], XtNresizable, True);
  312. i++;
  313. XtSetArg(arglist[i], XtNtop, XtChainTop);
  314. i++;
  315. XtSetArg(arglist[i], XtNbottom, XtChainTop);
  316. i++;
  317. XtSetArg(arglist[i], XtNleft, XtChainLeft);
  318. i++;
  319. XtSetArg(arglist[i], XtNright, XtChainLeft);
  320. i++;
  321. XtSetArg(arglist[i], XtNborderWidth, 0);
  322. i++;
  323. XtSetArg(arglist[i], XtNvertDistance, 20);
  324. i++;
  325. selFilePrompt = XtCreateManagedWidget("selFilePrompt",
  326. labelWidgetClass, selFileForm,
  327. arglist, i);
  328. #if 1
  329. i = 0;
  330. XtSetArg(arglist[i], XtNforeground, &SFfore);
  331. i++;
  332. XtSetArg(arglist[i], XtNbackground, &SFback);
  333. i++;
  334. XtGetValues(selFilePrompt, arglist, i);
  335. #endif
  336. SFinitFont();
  337. SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth + SFbesideText;
  338. SFentryHeight = SFaboveAndBelowText + SFcharHeight + SFaboveAndBelowText;
  339. listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
  340. scrollThickness;
  341. listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  342. SFlineToTextV + SFlistSize * SFentryHeight +
  343. SFlineToTextV + 1 + scrollThickness;
  344. SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4;
  345. hScrollX = -1;
  346. hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  347. SFlineToTextV + SFlistSize * SFentryHeight + SFlineToTextV;
  348. SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
  349. vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
  350. vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
  351. SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
  352. SFlineToTextV;
  353. SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
  354. SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  355. SFlineToTextV;
  356. SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  357. SFlineToTextV + SFlistSize * SFentryHeight - 1;
  358. SFtextX = SFlineToTextH + SFbesideText;
  359. SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
  360. SFsegs[0].x1 = 0;
  361. SFsegs[0].y1 = vScrollY;
  362. SFsegs[0].x2 = vScrollX - 1;
  363. SFsegs[0].y2 = vScrollY;
  364. SFsegs[1].x1 = vScrollX;
  365. SFsegs[1].y1 = 0;
  366. SFsegs[1].x2 = vScrollX;
  367. SFsegs[1].y2 = vScrollY - 1;
  368. SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
  369. SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
  370. SFlineToTextH + SFentryWidth - 1;
  371. i = 0;
  372. /* XtSetArg(arglist[i], XtNwidth, 3 * listWidth + 2 * listSpacing + 4 - w - 10); */
  373. XtSetArg(arglist[i], XtNwidth, 3 * listWidth + 2 * listSpacing + 4);
  374. i++;
  375. /* XtSetArg(arglist[i], XtNborderColor, SFfore); */
  376. /* i++; */
  377. /* XtSetArg(arglist[i], XtNfromHoriz, selFilePrompt); */
  378. /* i++; */
  379. /* XtSetArg(arglist[i], XtNhorizDistance, 10); */
  380. XtSetArg(arglist[i], XtNfromVert, selFilePrompt);
  381. i++;
  382. /* XtSetArg(arglist[i], XtNvertDistance, 0); */
  383. /* i++; */
  384. XtSetArg(arglist[i], XtNresizable, True);
  385. i++;
  386. XtSetArg(arglist[i], XtNtop, XtChainTop);
  387. i++;
  388. XtSetArg(arglist[i], XtNbottom, XtChainTop);
  389. i++;
  390. XtSetArg(arglist[i], XtNleft, XtChainLeft);
  391. i++;
  392. XtSetArg(arglist[i], XtNright, XtChainLeft);
  393. i++;
  394. XtSetArg(arglist[i], XtNstring, SFtextBuffer);
  395. i++;
  396. XtSetArg(arglist[i], XtNlength, MAXPATHLEN);
  397. i++;
  398. XtSetArg(arglist[i], XtNeditType, XawtextEdit);
  399. i++;
  400. XtSetArg(arglist[i], XtNwrap, XawtextWrapWord);
  401. i++;
  402. XtSetArg(arglist[i], XtNresize, XawtextResizeHeight);
  403. i++;
  404. XtSetArg(arglist[i], XtNuseStringInPlace, True);
  405. i++;
  406. XtSetArg(arglist[i], XtNvertDistance, 5);
  407. i++;
  408. selFileField = XtCreateManagedWidget("selFileField",
  409. asciiTextWidgetClass, selFileForm,
  410. arglist, i);
  411. XtOverrideTranslations(selFileField,
  412. XtParseTranslationTable
  413. (oneLineTextEditTranslations));
  414. /* XtSetKeyboardFocus(selFileForm, selFileField);
  415. need focus for selFileMask widget to set the filter */
  416. i = 0;
  417. XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);
  418. i++;
  419. XtSetArg(arglist[i], XtNwidth, SFpathScrollWidth);
  420. i++;
  421. XtSetArg(arglist[i], XtNheight, scrollThickness);
  422. i++;
  423. /* XtSetArg(arglist[i], XtNborderColor, SFfore); */
  424. /* i++; */
  425. XtSetArg(arglist[i], XtNfromVert, selFileField);
  426. i++;
  427. XtSetArg(arglist[i], XtNvertDistance, 30);
  428. i++;
  429. XtSetArg(arglist[i], XtNtop, XtChainTop);
  430. i++;
  431. XtSetArg(arglist[i], XtNbottom, XtChainTop);
  432. i++;
  433. XtSetArg(arglist[i], XtNleft, XtChainLeft);
  434. i++;
  435. XtSetArg(arglist[i], XtNright, XtChainLeft);
  436. i++;
  437. selFileHScroll = XtCreateManagedWidget("selFileHScroll",
  438. scrollbarWidgetClass, selFileForm,
  439. arglist, i);
  440. XtAddCallback(selFileHScroll, XtNjumpProc,
  441. (XtCallbackProc)SFpathSliderMovedCallback, (XtPointer) NULL);
  442. XtAddCallback(selFileHScroll, XtNscrollProc,
  443. (XtCallbackProc)SFpathAreaSelectedCallback, (XtPointer) NULL);
  444. i = 0;
  445. XtSetArg(arglist[i], XtNwidth, listWidth);
  446. i++;
  447. XtSetArg(arglist[i], XtNheight, listHeight);
  448. i++;
  449. /* XtSetArg(arglist[i], XtNborderColor, SFfore); */
  450. /* i++; */
  451. XtSetArg(arglist[i], XtNfromVert, selFileHScroll);
  452. i++;
  453. XtSetArg(arglist[i], XtNvertDistance, 10);
  454. i++;
  455. XtSetArg(arglist[i], XtNtop, XtChainTop);
  456. i++;
  457. XtSetArg(arglist[i], XtNbottom, XtChainTop);
  458. i++;
  459. XtSetArg(arglist[i], XtNleft, XtChainLeft);
  460. i++;
  461. XtSetArg(arglist[i], XtNright, XtChainLeft);
  462. i++;
  463. selFileLists[0] = XtCreateManagedWidget("selFileList1",
  464. compositeWidgetClass, selFileForm,
  465. arglist, i);
  466. i = 0;
  467. XtSetArg(arglist[i], XtNwidth, listWidth);
  468. i++;
  469. XtSetArg(arglist[i], XtNheight, listHeight);
  470. i++;
  471. /* XtSetArg(arglist[i], XtNborderColor, SFfore); */
  472. /* i++; */
  473. XtSetArg(arglist[i], XtNfromHoriz, selFileLists[0]);
  474. i++;
  475. XtSetArg(arglist[i], XtNfromVert, selFileHScroll);
  476. i++;
  477. XtSetArg(arglist[i], XtNhorizDistance, listSpacing);
  478. i++;
  479. XtSetArg(arglist[i], XtNvertDistance, 10);
  480. i++;
  481. XtSetArg(arglist[i], XtNtop, XtChainTop);
  482. i++;
  483. XtSetArg(arglist[i], XtNbottom, XtChainTop);
  484. i++;
  485. XtSetArg(arglist[i], XtNleft, XtChainLeft);
  486. i++;
  487. XtSetArg(arglist[i], XtNright, XtChainLeft);
  488. i++;
  489. selFileLists[1] = XtCreateManagedWidget("selFileList2",
  490. compositeWidgetClass, selFileForm,
  491. arglist, i);
  492. i = 0;
  493. XtSetArg(arglist[i], XtNwidth, listWidth);
  494. i++;
  495. XtSetArg(arglist[i], XtNheight, listHeight);
  496. i++;
  497. /* XtSetArg(arglist[i], XtNborderColor, SFfore); */
  498. /* i++; */
  499. XtSetArg(arglist[i], XtNfromHoriz, selFileLists[1]);
  500. i++;
  501. XtSetArg(arglist[i], XtNfromVert, selFileHScroll);
  502. i++;
  503. XtSetArg(arglist[i], XtNhorizDistance, listSpacing);
  504. i++;
  505. XtSetArg(arglist[i], XtNvertDistance, 10);
  506. i++;
  507. XtSetArg(arglist[i], XtNtop, XtChainTop);
  508. i++;
  509. XtSetArg(arglist[i], XtNbottom, XtChainTop);
  510. i++;
  511. XtSetArg(arglist[i], XtNleft, XtChainLeft);
  512. i++;
  513. XtSetArg(arglist[i], XtNright, XtChainLeft);
  514. i++;
  515. selFileLists[2] = XtCreateManagedWidget("selFileList3",
  516. compositeWidgetClass, selFileForm,
  517. arglist, i);
  518. for (n = 0; n < 3; n++) {
  519. i = 0;
  520. XtSetArg(arglist[i], XtNx, vScrollX);
  521. i++;
  522. XtSetArg(arglist[i], XtNy, vScrollY);
  523. i++;
  524. XtSetArg(arglist[i], XtNwidth, scrollThickness);
  525. i++;
  526. XtSetArg(arglist[i], XtNheight, SFvScrollHeight);
  527. i++;
  528. /* XtSetArg(arglist[i], XtNborderColor, SFfore); */
  529. /* i++; */
  530. selFileVScrolls[n] = XtCreateManagedWidget("selFileVScroll",
  531. scrollbarWidgetClass,
  532. selFileLists[n], arglist, i);
  533. XtAddCallback(selFileVScrolls[n], XtNjumpProc,
  534. (XtCallbackProc)SFvFloatSliderMovedCallback, (XtPointer) n);
  535. XtAddCallback(selFileVScrolls[n], XtNscrollProc,
  536. (XtCallbackProc)SFvAreaSelectedCallback, (XtPointer) n);
  537. i = 0;
  538. XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);
  539. i++;
  540. XtSetArg(arglist[i], XtNx, hScrollX);
  541. i++;
  542. XtSetArg(arglist[i], XtNy, hScrollY);
  543. i++;
  544. XtSetArg(arglist[i], XtNwidth, SFhScrollWidth);
  545. i++;
  546. XtSetArg(arglist[i], XtNheight, scrollThickness);
  547. i++;
  548. /* XtSetArg(arglist[i], XtNborderColor, SFfore); */
  549. /* i++; */
  550. selFileHScrolls[n] = XtCreateManagedWidget("selFileHScroll",
  551. scrollbarWidgetClass,
  552. selFileLists[n], arglist, i);
  553. XtAddCallback(selFileHScrolls[n], XtNjumpProc,
  554. (XtCallbackProc)SFhSliderMovedCallback, (XtPointer) n);
  555. XtAddCallback(selFileHScrolls[n], XtNscrollProc,
  556. (XtCallbackProc)SFhAreaSelectedCallback, (XtPointer) n);
  557. }
  558. /* Do the file filter stuff. */
  559. selFileLabel = XtVaCreateManagedWidget("selFileLabel",
  560. labelWidgetClass, selFileForm,
  561. XtNfromVert, selFileLists[0],
  562. XtNvertDistance, 30,
  563. /* XtNfromHoriz, selFileCancel, */
  564. /* XtNhorizDistance, 60, */
  565. XtNlabel, "File Mask:",
  566. XtNborderWidth, 0,
  567. XtNtop, XtChainTop,
  568. XtNbottom, XtChainTop, NULL);
  569. selFileMask = XtVaCreateManagedWidget("selFileMask",
  570. asciiTextWidgetClass, selFileForm,
  571. XtNwidth, MASKWIDTH / 2 * SFcharWidth,
  572. XtNfromVert, selFileLists[0],
  573. XtNvertDistance, 30,
  574. XtNfromHoriz, selFileLabel,
  575. XtNhorizDistance, 0,
  576. XtNtop, XtChainTop,
  577. XtNbottom, XtChainTop,
  578. XtNstring, fileMask,
  579. XtNlength, MASKWIDTH,
  580. XtNeditType, XawtextEdit,
  581. XtNwrap, XawtextWrapNever,
  582. XtNuseStringInPlace, True, NULL);
  583. for (i = 0; i < 3; i++)
  584. XtSetKeyboardFocus(selFileLists[i], selFileField);
  585. XtOverrideTranslations(selFileMask,
  586. XtParseTranslationTable
  587. (oneLineTextEditTranslations));
  588. XtAddEventHandler(selFileMask, KeyPressMask, False,
  589. (XtEventHandler)maskChanged, (XtPointer) NULL);
  590. selFileLabel = XtVaCreateManagedWidget("selFileLabel",
  591. labelWidgetClass, selFileForm,
  592. XtNfromVert, selFileLists[0],
  593. XtNvertDistance, 30,
  594. XtNfromHoriz, selFileMask,
  595. XtNhorizDistance, 40,
  596. XtNlabel, "Dot files are:",
  597. XtNborderWidth, 0,
  598. XtNtop, XtChainTop,
  599. XtNbottom, XtChainTop, NULL);
  600. selFileHide = XtVaCreateManagedWidget("selFileHide",
  601. commandWidgetClass, selFileForm,
  602. /* XtNwidth, 7 * SFcharWidth, */
  603. XtNfromVert, selFileLists[0],
  604. XtNvertDistance, 30,
  605. XtNfromHoriz, selFileLabel,
  606. XtNhorizDistance, 2,
  607. XtNlabel, hideFlag ? "hidden" : "shown",
  608. /* XtNborderWidth, 1, */
  609. XtNtop, XtChainTop,
  610. /* XtNjustify, XtJustifyLeft, */
  611. XtNbottom, XtChainTop,
  612. NULL);
  613. XtAddCallback(selFileHide, XtNcallback, (XtCallbackProc)hideFiles, NULL);
  614. box = XtVaCreateManagedWidget("box", formWidgetClass,
  615. paned,
  616. XtNshowGrip, False,
  617. XtNdefaultDistance, 6,
  618. XtNskipAdjust, True,
  619. XtNaccelerators, G_accels_cr,
  620. NULL);
  621. selFileOK = XtVaCreateManagedWidget("selFileOK", commandWidgetClass,
  622. box,
  623. XtNlabel, ok,
  624. XtNcallback, SFokSelect,
  625. XtNtop, XtChainTop,
  626. XtNbottom, XtChainBottom,
  627. XtNleft, XtChainLeft,
  628. XtNright, XtChainLeft,
  629. NULL);
  630. selFileCancel = XtVaCreateManagedWidget("selFileCancel", commandWidgetClass,
  631. box,
  632. XtNlabel, cancel,
  633. XtNcallback, SFcancelSelect,
  634. /* XtNborderColor, SFfore, */
  635. XtNfromHoriz, selFileOK,
  636. XtNbottom, XtChainBottom,
  637. XtNleft, XtChainRight,
  638. XtNright, XtChainRight,
  639. NULL);
  640. XtSetMappedWhenManaged(selFile, False);
  641. XtRealizeWidget(selFile);
  642. /* Add WM_DELETE_WINDOW protocol */
  643. SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
  644. XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);
  645. SFcreateGC();
  646. xtermCursor = XCreateFontCursor(SFdisplay, XC_xterm);
  647. sbRightArrowCursor = XCreateFontCursor(SFdisplay, XC_sb_right_arrow);
  648. arrowCursor = XCreateFontCursor(SFdisplay, XC_left_ptr);
  649. XDefineCursor(SFdisplay, XtWindow(selFileForm), arrowCursor);
  650. XDefineCursor(SFdisplay, XtWindow(selFileField), xtermCursor);
  651. for (n = 0; n < 3; n++) {
  652. XDefineCursor(SFdisplay, XtWindow(selFileLists[n]), sbRightArrowCursor);
  653. }
  654. XDefineCursor(SFdisplay, XtWindow(selFileOK), arrowCursor);
  655. XDefineCursor(SFdisplay, XtWindow(selFileCancel), arrowCursor);
  656. for (n = 0; n < 3; n++) {
  657. XtAddEventHandler(selFileLists[n], ExposureMask, True,
  658. (XtEventHandler)SFexposeList, (XtPointer) n);
  659. XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
  660. (XtEventHandler)SFenterList, (XtPointer) n);
  661. XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
  662. (XtEventHandler)SFleaveList, (XtPointer) n);
  663. XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
  664. (XtEventHandler)SFmotionList, (XtPointer) n);
  665. XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
  666. (XtEventHandler)SFbuttonPressList, (XtPointer) n);
  667. XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
  668. (XtEventHandler)SFbuttonReleaseList, (XtPointer) n);
  669. }
  670. XtAddEventHandler(selFileField, KeyPressMask, False,
  671. (XtEventHandler)SFmodVerifyCallback, (XtPointer) NULL);
  672. SFapp = XtWidgetToApplicationContext(selFile);
  673. return selFile;
  674. }
  675. /* position widget under the cursor */
  676. void
  677. SFpositionWidget(Widget w)
  678. {
  679. Arg args[3];
  680. Cardinal num_args;
  681. Dimension width, height, b_width;
  682. int x, y, max_x, max_y;
  683. Window root, child;
  684. int dummyx, dummyy;
  685. unsigned int dummymask;
  686. XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &x, &y,
  687. &dummyx, &dummyy, &dummymask);
  688. num_args = 0;
  689. XtSetArg(args[num_args], XtNwidth, &width);
  690. num_args++;
  691. XtSetArg(args[num_args], XtNheight, &height);
  692. num_args++;
  693. XtSetArg(args[num_args], XtNborderWidth, &b_width);
  694. num_args++;
  695. XtGetValues(w, args, num_args);
  696. width += 2 * b_width;
  697. height += 2 * b_width;
  698. x -= ((Position) width / 2);
  699. if (x < 0)
  700. x = 0;
  701. if (x > (max_x = (Position) (XtScreen(w)->width - width)))
  702. x = max_x;
  703. y -= ((Position) height / 2);
  704. if (y < 0)
  705. y = 0;
  706. if (y > (max_y = (Position) (XtScreen(w)->height - height)))
  707. y = max_y;
  708. num_args = 0;
  709. XtSetArg(args[num_args], XtNx, x);
  710. num_args++;
  711. XtSetArg(args[num_args], XtNy, y);
  712. num_args++;
  713. XtSetValues(w, args, num_args);
  714. }
  715. FILE *
  716. SFopenFile(const char *name, const char *mode, const char *prompt, const char *failed)
  717. {
  718. Arg args[1];
  719. FILE *fp;
  720. UNUSED(args);
  721. UNUSED(prompt);
  722. UNUSED(failed);
  723. SFchdir(SFstartDir);
  724. errno = 0;
  725. if (!name || *name == 0 || (fp = XFOPEN(name, mode)) == NULL) {
  726. XBell(DISP, 0);
  727. return NULL;
  728. }
  729. return fp;
  730. }
  731. void
  732. SFtextChanged(void)
  733. {
  734. if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~')) {
  735. (void)strcpy(SFcurrentPath, SFtextBuffer);
  736. SFtextPos = XawTextGetInsertionPoint(selFileField);
  737. }
  738. else {
  739. (void)strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer);
  740. SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir);
  741. }
  742. if (!SFworkProcAdded) {
  743. (void)XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL);
  744. SFworkProcAdded = 1;
  745. }
  746. SFupdatePath();
  747. }
  748. static void
  749. SFprepareToReturn(void)
  750. {
  751. SFstatus = SEL_FILE_NULL;
  752. /* XtRemoveGrab(selFile); */
  753. XtUnmapWidget(selFile);
  754. if (SFdirModTimerId) {
  755. XtRemoveTimeOut(SFdirModTimerId);
  756. SFdirModTimerId = 0;
  757. }
  758. if (SFchdir(SFstartDir)) {
  759. XtAppError(SFapp, "XsraSelFile: can't return to current directory");
  760. }
  761. }
  762. void
  763. XsraSelFile(Widget parent, struct filesel_callback *callback)
  764. /* const char *title, const char *prompt, */
  765. /* const char *ok, const char *cancel, */
  766. /* const char *init_path, */
  767. /* const char *mask, */
  768. /* Boolean must_exist, */
  769. /* Widget *ret_widget */
  770. {
  771. static Boolean firstTime = True;
  772. Widget w;
  773. Cardinal i;
  774. Arg arglist[20];
  775. XEvent event;
  776. if (!callback->prompt) {
  777. callback->prompt = "Pathname:";
  778. }
  779. if (!callback->title) {
  780. callback->title = "Xdvi: select filename";
  781. }
  782. if (!callback->ok) {
  783. callback->ok = "OK";
  784. }
  785. if (!callback->cancel) {
  786. callback->cancel = "Cancel";
  787. }
  788. if (firstTime) {
  789. firstTime = False;
  790. SFdisplay = XtDisplay(parent);
  791. w = SFcreateWidgets(parent, callback->title, callback->prompt, callback->ok, callback->cancel);
  792. }
  793. else {
  794. i = 0;
  795. XtSetArg(arglist[i], XtNlabel, callback->prompt);
  796. i++;
  797. XtSetValues(selFilePrompt, arglist, i);
  798. i = 0;
  799. XtSetArg(arglist[i], XtNlabel, callback->ok);
  800. i++;
  801. XtSetValues(selFileOK, arglist, i);
  802. i = 0;
  803. XtSetArg(arglist[i], XtNlabel, callback->cancel);
  804. i++;
  805. XtSetValues(selFileCancel, arglist, i);
  806. }
  807. SFpositionWidget(selFile);
  808. XtMapWidget(selFile);
  809. {
  810. char *cwd = xgetcwd();
  811. strcpy(SFstartDir, cwd);
  812. free(cwd);
  813. }
  814. if (SFstartDir[0] == 0) {
  815. XtAppError(SFapp, "XsraSelFile: can't get current directory");
  816. }
  817. (void)strcat(SFstartDir, "/");
  818. (void)strcpy(SFcurrentDir, SFstartDir);
  819. if (callback->init_path) {
  820. if (callback->init_path[0] == '/') {
  821. (void)strcpy(SFcurrentPath, callback->init_path);
  822. if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) {
  823. SFsetText(SFcurrentPath);
  824. }
  825. else {
  826. SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
  827. }
  828. }
  829. else {
  830. (void)strcat(strcpy(SFcurrentPath, SFstartDir), callback->init_path);
  831. SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
  832. }
  833. }
  834. else {
  835. SFsetText(SFcurrentDir);
  836. (void)strcpy(SFcurrentPath, SFstartDir);
  837. }
  838. SFfunc = showEntry;
  839. SFtextChanged();
  840. /* don't grab the pointer so that warning popups still work */
  841. /* XtAddGrab(selFile, True, True); */
  842. SFdirModTimerId = XtAppAddTimeOut(SFapp, 1200UL,
  843. SFdirModTimer, (XtPointer) NULL);
  844. if (strcmp(fileMask, callback->filemask) != 0) { /* if mask changed */
  845. SFDir *dir;
  846. strncpy(fileMask, callback->filemask, MASKWIDTH);
  847. XtVaSetValues(selFileMask, XtNstring, fileMask, NULL);
  848. for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
  849. *(dir->dir) = 0; /* force a re-read */
  850. SFupdatePath();
  851. }
  852. while (1) {
  853. XtAppNextEvent(SFapp, &event);
  854. switch (event.type) {
  855. Widget w;
  856. #if 0 /* don't do this, it may send the X server into a busy loop if the File selector
  857. is positioned over a window that is `on top' by default */
  858. case Expose:
  859. if (!raise_message_windows())
  860. raise_file_selector();
  861. break;
  862. #endif
  863. case KeyPress:
  864. case ButtonPress:
  865. /* beep if keypress was inside main window */
  866. w = XtWindowToWidget(DISP, event.xany.window);
  867. while ((w != NULL) && (w != selFile)) {
  868. /* exception: message windows */
  869. if (is_message_window(w))
  870. break;
  871. w = XtParent(w);
  872. }
  873. if (w == NULL || w == globals.widgets.top_level) {
  874. XBell(DISP, 0);
  875. }
  876. break;
  877. }
  878. XtDispatchEvent(&event);
  879. switch (SFstatus) {
  880. case SEL_FILE_TEXT:
  881. SFstatus = SEL_FILE_NULL;
  882. SFtextChanged();
  883. break;
  884. case SEL_FILE_OK:
  885. if (callback->must_exist) {
  886. FILE *tmp_fp = XFOPEN(SFtextBuffer, "r");
  887. dviErrFlagT errflag = NO_ERROR;
  888. if (tmp_fp == NULL) {
  889. popup_message(selFile,
  890. MSG_ERR, NULL, "Could not open %s: %s.\n",
  891. SFtextBuffer, strerror(errno));
  892. SFstatus = SEL_FILE_NULL;
  893. break;
  894. }
  895. else if (!process_preamble(tmp_fp, &errflag)
  896. || !find_postamble(tmp_fp, &errflag)
  897. || !read_postamble(tmp_fp, &errflag, False)) {
  898. popup_message(selFile,
  899. MSG_ERR, NULL, "Error opening %s:\n%s.",
  900. SFtextBuffer, get_dvi_error(errflag));
  901. fclose(tmp_fp);
  902. SFstatus = SEL_FILE_NULL;
  903. break;
  904. }
  905. else { /* file is OK */
  906. fclose(tmp_fp);
  907. SFprepareToReturn();
  908. callback->func_ptr(SFtextBuffer, callback->data);
  909. return;
  910. /* return xstrdup(SFtextBuffer); */
  911. }
  912. }
  913. else {
  914. SFprepareToReturn();
  915. callback->func_ptr(SFtextBuffer, callback->data);
  916. return;
  917. /* return xstrdup(SFtextBuffer); */
  918. }
  919. case SEL_FILE_CANCEL:
  920. SFprepareToReturn();
  921. if (callback->exit_on_cancel)
  922. exit(0);
  923. return;
  924. /* return NULL; */
  925. case SEL_FILE_NULL:
  926. break;
  927. }
  928. }
  929. }
  930. #else
  931. /* silence `empty compilation unit' warnings */
  932. static void bar(void); static void foo() { bar(); } static void bar(void) { foo(); }
  933. #endif /* !defined(MOTIF) */