PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/xdvik-22.84.14/texk/xdvik/gui/sfSelFile.c

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