/contrib/groff/src/devices/xditview/xditview.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 657 lines · 499 code · 93 blank · 65 comment · 41 complexity · 1c0451b66965cb712470460c141d400d MD5 · raw file

  1. /*
  2. * Copyright 1991 Massachusetts Institute of Technology
  3. *
  4. * Permission to use, copy, modify, distribute, and sell this software and its
  5. * documentation for any purpose is hereby granted without fee, provided that
  6. * 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 M.I.T. not be used in advertising or
  9. * publicity pertaining to distribution of the software without specific,
  10. * written prior permission. M.I.T. makes no representations about the
  11. * suitability of this software for any purpose. It is provided "as is"
  12. * without express or implied warranty.
  13. *
  14. * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  16. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  17. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  18. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  19. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  20. *
  21. */
  22. /*
  23. * xditview --
  24. *
  25. * Display ditroff output in an X window
  26. */
  27. #ifndef SABER
  28. #ifndef lint
  29. static char rcsid[] = "$XConsortium: xditview.c,v 1.17 89/12/10 17:05:08 rws Exp $";
  30. #endif /* lint */
  31. #endif /* SABER */
  32. #ifdef HAVE_CONFIG_H
  33. #include <config.h>
  34. #endif
  35. #include <X11/Xatom.h>
  36. #include <X11/Xlib.h>
  37. #include <X11/Xos.h>
  38. #include <X11/Intrinsic.h>
  39. #include <X11/StringDefs.h>
  40. #include <X11/Shell.h>
  41. #include <X11/Xaw/Paned.h>
  42. #include <X11/Xaw/Viewport.h>
  43. #include <X11/Xaw/Box.h>
  44. #include <X11/Xaw/Command.h>
  45. #include <X11/Xaw/Dialog.h>
  46. #include <X11/Xaw/Label.h>
  47. #include <X11/Xaw/SimpleMenu.h>
  48. #include <X11/Xaw/SmeBSB.h>
  49. #include <stdlib.h>
  50. #include <signal.h>
  51. #include <stdio.h>
  52. #include "Dvi.h"
  53. #include "xdit.bm"
  54. #include "xdit_mask.bm"
  55. #ifdef NEED_DECLARATION_POPEN
  56. FILE *popen(const char *, const char *);
  57. #endif /* NEED_DECLARATION_POPEN */
  58. #ifdef NEED_DECLARATION_PCLOSE
  59. int pclose (FILE *);
  60. #endif /* NEED_DECLARATION_PCLOSE */
  61. typedef void (*MakePromptFunc)(const char *);
  62. static String fallback_resources[] = {
  63. #include "GXditview-ad.h"
  64. NULL
  65. };
  66. static struct app_resources {
  67. char *print_command;
  68. char *filename;
  69. } app_resources;
  70. #define offset(field) XtOffset(struct app_resources *, field)
  71. /* Application resources. */
  72. static XtResource resources[] = {
  73. {(String)"printCommand", (String)"PrintCommand", (String)XtRString,
  74. sizeof(char*), offset(print_command), (String)XtRString, NULL},
  75. {(String)"filename", (String)"Filename", (String)XtRString,
  76. sizeof(char*), offset(filename), (String)XtRString, NULL},
  77. };
  78. #undef offset
  79. /* Command line options table. Only resources are entered here...there is a
  80. pass over the remaining options after XtParseCommand is let loose. */
  81. static XrmOptionDescRec options[] = {
  82. {(char *)"-page", (char *)"*dvi.pageNumber",
  83. XrmoptionSepArg, NULL},
  84. {(char *)"-backingStore", (char *)"*dvi.backingStore",
  85. XrmoptionSepArg, NULL},
  86. {(char *)"-resolution", (char *)"*dvi.resolution",
  87. XrmoptionSepArg, NULL},
  88. {(char *)"-printCommand", (char *)".printCommand",
  89. XrmoptionSepArg, NULL},
  90. {(char *)"-filename", (char *)".filename",
  91. XrmoptionSepArg, NULL},
  92. {(char *)"-noPolyText", (char *)"*dvi.noPolyText",
  93. XrmoptionNoArg, (XPointer)"TRUE"},
  94. };
  95. static char current_print_command[1024];
  96. static char current_file_name[1024];
  97. static FILE *current_file;
  98. /*
  99. * Report the syntax for calling xditview.
  100. */
  101. static void
  102. Syntax(const char *call)
  103. {
  104. (void) printf ("Usage: %s [-fg <color>] [-bg <color>]\n", call);
  105. (void) printf (" [-bd <color>] [-bw <pixels>] [-help]\n");
  106. (void) printf (" [-display displayname] [-geometry geom]\n");
  107. (void) printf (" [-page <page-number>] [-backing <backing-store>]\n");
  108. (void) printf (" [-resolution <res>] [-print <command>]\n");
  109. (void) printf (" [-filename <file>] [filename]\n\n");
  110. exit(1);
  111. }
  112. static void NewFile (const char *);
  113. static void SetPageNumber (int);
  114. static Widget toplevel, paned, viewport, dvi;
  115. static Widget page;
  116. static Widget simpleMenu;
  117. static void NextPage(Widget, XtPointer, XtPointer);
  118. static void PreviousPage(Widget, XtPointer, XtPointer);
  119. static void SelectPage(Widget, XtPointer, XtPointer);
  120. static void OpenFile(Widget, XtPointer, XtPointer);
  121. static void Quit(Widget, XtPointer, XtPointer);
  122. static void Print(Widget, XtPointer, XtPointer);
  123. static struct menuEntry {
  124. const char *name;
  125. XtCallbackProc function;
  126. } menuEntries[] = {
  127. {"nextPage", NextPage},
  128. {"previousPage", PreviousPage},
  129. {"selectPage", SelectPage},
  130. {"print", Print},
  131. {"openFile", OpenFile},
  132. {"quit", Quit},
  133. };
  134. static void NextPageAction(Widget, XEvent *, String *, Cardinal *);
  135. static void PreviousPageAction(Widget, XEvent *, String *, Cardinal *);
  136. static void SelectPageAction(Widget, XEvent *, String *, Cardinal *);
  137. static void OpenFileAction(Widget, XEvent *, String *, Cardinal *);
  138. static void QuitAction(Widget, XEvent *, String *, Cardinal *);
  139. static void AcceptAction(Widget, XEvent *, String *, Cardinal *);
  140. static void CancelAction(Widget, XEvent *, String *, Cardinal *);
  141. static void PrintAction(Widget, XEvent *, String *, Cardinal *);
  142. static void RerasterizeAction(Widget, XEvent *, String *, Cardinal *);
  143. static void MakePrompt(Widget, const char *, MakePromptFunc, const char *);
  144. XtActionsRec xditview_actions[] = {
  145. {(String)"NextPage", NextPageAction},
  146. {(String)"PreviousPage", PreviousPageAction},
  147. {(String)"SelectPage", SelectPageAction},
  148. {(String)"Print", PrintAction},
  149. {(String)"OpenFile", OpenFileAction},
  150. {(String)"Rerasterize", RerasterizeAction},
  151. {(String)"Quit", QuitAction},
  152. {(String)"Accept", AcceptAction},
  153. {(String)"Cancel", CancelAction},
  154. };
  155. #define MenuNextPage 0
  156. #define MenuPreviousPage 1
  157. #define MenuSelectPage 2
  158. #define MenuPrint 3
  159. #define MenuOpenFile 4
  160. #define MenuQuit 5
  161. static char pageLabel[256] = "Page <none>";
  162. int main(int argc, char **argv)
  163. {
  164. char *file_name = 0;
  165. Cardinal i;
  166. static Arg labelArgs[] = {
  167. {XtNlabel, (XtArgVal) pageLabel},
  168. };
  169. XtAppContext xtcontext;
  170. Arg topLevelArgs[2];
  171. Widget entry;
  172. Arg pageNumberArgs[1];
  173. int page_number;
  174. toplevel = XtAppInitialize(&xtcontext, "GXditview",
  175. options, XtNumber (options),
  176. &argc, argv, fallback_resources, NULL, 0);
  177. if (argc > 2
  178. || (argc == 2 && (!strcmp(argv[1], "-help")
  179. || !strcmp(argv[1], "--help"))))
  180. Syntax(argv[0]);
  181. XtGetApplicationResources(toplevel, (XtPointer)&app_resources,
  182. resources, XtNumber(resources),
  183. NULL, (Cardinal) 0);
  184. if (app_resources.print_command)
  185. strcpy(current_print_command, app_resources.print_command);
  186. XtAppAddActions(xtcontext, xditview_actions, XtNumber (xditview_actions));
  187. XtSetArg (topLevelArgs[0], XtNiconPixmap,
  188. XCreateBitmapFromData (XtDisplay (toplevel),
  189. XtScreen(toplevel)->root,
  190. (char *)xdit_bits,
  191. xdit_width, xdit_height));
  192. XtSetArg (topLevelArgs[1], XtNiconMask,
  193. XCreateBitmapFromData (XtDisplay (toplevel),
  194. XtScreen(toplevel)->root,
  195. (char *)xdit_mask_bits,
  196. xdit_mask_width, xdit_mask_height));
  197. XtSetValues (toplevel, topLevelArgs, 2);
  198. if (argc > 1)
  199. file_name = argv[1];
  200. /*
  201. * create the menu and insert the entries
  202. */
  203. simpleMenu = XtCreatePopupShell ("menu", simpleMenuWidgetClass, toplevel,
  204. NULL, 0);
  205. for (i = 0; i < XtNumber (menuEntries); i++) {
  206. entry = XtCreateManagedWidget(menuEntries[i].name,
  207. smeBSBObjectClass, simpleMenu,
  208. NULL, (Cardinal) 0);
  209. XtAddCallback(entry, XtNcallback, menuEntries[i].function, NULL);
  210. }
  211. paned = XtCreateManagedWidget("paned", panedWidgetClass, toplevel,
  212. NULL, (Cardinal) 0);
  213. viewport = XtCreateManagedWidget("viewport", viewportWidgetClass, paned,
  214. NULL, (Cardinal) 0);
  215. dvi = XtCreateManagedWidget ("dvi", dviWidgetClass, viewport, NULL, 0);
  216. page = XtCreateManagedWidget ("label", labelWidgetClass, paned,
  217. labelArgs, XtNumber (labelArgs));
  218. XtSetArg (pageNumberArgs[0], XtNpageNumber, &page_number);
  219. XtGetValues (dvi, pageNumberArgs, 1);
  220. if (file_name)
  221. NewFile (file_name);
  222. /* NewFile modifies current_file_name, so do this here. */
  223. if (app_resources.filename)
  224. strcpy(current_file_name, app_resources.filename);
  225. XtRealizeWidget (toplevel);
  226. if (file_name)
  227. SetPageNumber (page_number);
  228. XtAppMainLoop(xtcontext);
  229. return 0;
  230. }
  231. static void
  232. SetPageNumber (int number)
  233. {
  234. Arg arg[2];
  235. int actual_number, last_page;
  236. XtSetArg (arg[0], XtNpageNumber, number);
  237. XtSetValues (dvi, arg, 1);
  238. XtSetArg (arg[0], XtNpageNumber, &actual_number);
  239. XtSetArg (arg[1], XtNlastPageNumber, &last_page);
  240. XtGetValues (dvi, arg, 2);
  241. if (actual_number == 0)
  242. sprintf (pageLabel, "Page <none>");
  243. else if (last_page > 0)
  244. sprintf (pageLabel, "Page %d of %d", actual_number, last_page);
  245. else
  246. sprintf (pageLabel, "Page %d", actual_number);
  247. XtSetArg (arg[0], XtNlabel, pageLabel);
  248. XtSetValues (page, arg, 1);
  249. }
  250. static void
  251. SelectPageNumber (const char *number_string)
  252. {
  253. SetPageNumber (atoi(number_string));
  254. }
  255. static int hadFile = 0;
  256. static void
  257. NewFile (const char *name)
  258. {
  259. Arg arg[2];
  260. char *n;
  261. FILE *new_file;
  262. Boolean seek = 0;
  263. if (current_file) {
  264. if (!strcmp (current_file_name, "-"))
  265. ;
  266. else if (current_file_name[0] == '|')
  267. pclose (current_file);
  268. else
  269. fclose (current_file);
  270. }
  271. if (!strcmp (name, "-"))
  272. new_file = stdin;
  273. else if (name[0] == '|')
  274. new_file = popen (name+1, "r");
  275. else {
  276. new_file = fopen (name, "r");
  277. seek = 1;
  278. }
  279. if (!new_file) {
  280. /* XXX display error message */
  281. return;
  282. }
  283. XtSetArg (arg[0], XtNfile, new_file);
  284. XtSetArg (arg[1], XtNseek, seek);
  285. XtSetValues (dvi, arg, 2);
  286. if (hadFile || name[0] != '-' || name[1] != '\0') {
  287. XtSetArg (arg[0], XtNtitle, name);
  288. if (name[0] != '/' && (n = strrchr (name, '/')))
  289. n = n + 1;
  290. else
  291. n = (char *)name;
  292. XtSetArg (arg[1], XtNiconName, n);
  293. XtSetValues (toplevel, arg, 2);
  294. }
  295. hadFile = 1;
  296. SelectPageNumber ("1");
  297. strcpy (current_file_name, name);
  298. current_file = new_file;
  299. }
  300. static char fileBuf[1024];
  301. static void
  302. ResetMenuEntry (Widget entry)
  303. {
  304. Arg arg[1];
  305. XtSetArg (arg[0], (String)XtNpopupOnEntry, entry);
  306. XtSetValues (XtParent(entry) , arg, (Cardinal) 1);
  307. }
  308. /*ARGSUSED*/
  309. static void
  310. NextPage (Widget entry, XtPointer name, XtPointer data)
  311. {
  312. name = name; /* unused; suppress compiler warning */
  313. data = data;
  314. NextPageAction((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
  315. ResetMenuEntry (entry);
  316. }
  317. static void
  318. NextPageAction (Widget widget, XEvent *event,
  319. String *params, Cardinal *num_params)
  320. {
  321. Arg args[1];
  322. int number;
  323. XtSetArg (args[0], XtNpageNumber, &number);
  324. XtGetValues (dvi, args, 1);
  325. SetPageNumber (number+1);
  326. widget = widget; /* unused; suppress compiler warning */
  327. event = event;
  328. params = params;
  329. num_params = num_params;
  330. }
  331. /*ARGSUSED*/
  332. static void
  333. PreviousPage (Widget entry, XtPointer name, XtPointer data)
  334. {
  335. name = name; /* unused; suppress compiler warning */
  336. data = data;
  337. PreviousPageAction ((Widget)NULL, (XEvent *) 0, (String *) 0,
  338. (Cardinal *) 0);
  339. ResetMenuEntry (entry);
  340. }
  341. static void
  342. PreviousPageAction (Widget widget, XEvent *event,
  343. String *params, Cardinal *num_params)
  344. {
  345. Arg args[1];
  346. int number;
  347. XtSetArg (args[0], XtNpageNumber, &number);
  348. XtGetValues (dvi, args, 1);
  349. SetPageNumber (number-1);
  350. widget = widget; /* unused; suppress compiler warning */
  351. event = event;
  352. params = params;
  353. num_params = num_params;
  354. }
  355. /* ARGSUSED */
  356. static void
  357. SelectPage (Widget entry, XtPointer name, XtPointer data)
  358. {
  359. name = name; /* unused; suppress compiler warning */
  360. data = data;
  361. SelectPageAction ((Widget)NULL, (XEvent *) 0, (String *) 0,
  362. (Cardinal *) 0);
  363. ResetMenuEntry (entry);
  364. }
  365. static void
  366. SelectPageAction (Widget widget, XEvent *event,
  367. String *params, Cardinal *num_params)
  368. {
  369. widget = widget; /* unused; suppress compiler warning */
  370. event = event;
  371. params = params;
  372. num_params = num_params;
  373. MakePrompt (toplevel, "Page number", SelectPageNumber, "");
  374. }
  375. static void
  376. DoPrint (const char *name)
  377. {
  378. FILE *print_file;
  379. RETSIGTYPE (*handler)(int);
  380. /* Avoid dieing because of an invalid command. */
  381. handler = signal(SIGPIPE, SIG_IGN);
  382. print_file = popen(name, "w");
  383. if (!print_file)
  384. /* XXX print error message */
  385. return;
  386. DviSaveToFile(dvi, print_file);
  387. pclose(print_file);
  388. signal(SIGPIPE, handler);
  389. strcpy(current_print_command, name);
  390. }
  391. static void
  392. RerasterizeAction (Widget widget, XEvent *event,
  393. String *params, Cardinal *num_params)
  394. {
  395. Arg args[1];
  396. int number;
  397. if (current_file_name[0] == 0) {
  398. /* XXX display an error message */
  399. return;
  400. }
  401. XtSetArg (args[0], XtNpageNumber, &number);
  402. XtGetValues (dvi, args, 1);
  403. NewFile(current_file_name);
  404. SetPageNumber (number);
  405. widget = widget; /* unused; suppress compiler warning */
  406. event = event;
  407. params = params;
  408. num_params = num_params;
  409. }
  410. /* ARGSUSED */
  411. static void
  412. Print (Widget entry, XtPointer name, XtPointer data)
  413. {
  414. name = name; /* unused; suppress compiler warning */
  415. data = data;
  416. PrintAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
  417. ResetMenuEntry (entry);
  418. }
  419. static void
  420. PrintAction (Widget widget, XEvent *event,
  421. String *params, Cardinal *num_params)
  422. {
  423. widget = widget; /* unused; suppress compiler warning */
  424. event = event;
  425. params = params;
  426. num_params = num_params;
  427. if (current_print_command[0])
  428. strcpy (fileBuf, current_print_command);
  429. else
  430. fileBuf[0] = '\0';
  431. MakePrompt (toplevel, "Print command:", DoPrint, fileBuf);
  432. }
  433. /* ARGSUSED */
  434. static void
  435. OpenFile (Widget entry, XtPointer name, XtPointer data)
  436. {
  437. name = name; /* unused; suppress compiler warning */
  438. data = data;
  439. OpenFileAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
  440. ResetMenuEntry (entry);
  441. }
  442. static void
  443. OpenFileAction (Widget widget, XEvent *event,
  444. String *params, Cardinal *num_params)
  445. {
  446. widget = widget; /* unused; suppress compiler warning */
  447. event = event;
  448. params = params;
  449. num_params = num_params;
  450. if (current_file_name[0])
  451. strcpy (fileBuf, current_file_name);
  452. else
  453. fileBuf[0] = '\0';
  454. MakePrompt (toplevel, "File to open:", NewFile, fileBuf);
  455. }
  456. /* ARGSUSED */
  457. static void
  458. Quit (Widget entry, XtPointer closure, XtPointer data)
  459. {
  460. entry = entry; /* unused; suppress compiler warning */
  461. closure = closure;
  462. data = data;
  463. QuitAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
  464. }
  465. static void
  466. QuitAction (Widget widget, XEvent *event,
  467. String *params, Cardinal *num_params)
  468. {
  469. widget = widget; /* unused; suppress compiler warning */
  470. event = event;
  471. params = params;
  472. num_params = num_params;
  473. exit (0);
  474. }
  475. Widget promptShell, promptDialog;
  476. MakePromptFunc promptfunction;
  477. /* ARGSUSED */
  478. static
  479. void CancelAction (Widget widget, XEvent *event,
  480. String *params, Cardinal *num_params)
  481. {
  482. widget = widget; /* unused; suppress compiler warning */
  483. event = event;
  484. params = params;
  485. num_params = num_params;
  486. if (promptShell) {
  487. XtSetKeyboardFocus(toplevel, (Widget) None);
  488. XtDestroyWidget(promptShell);
  489. promptShell = (Widget) 0;
  490. }
  491. }
  492. static
  493. void AcceptAction (Widget widget, XEvent *event,
  494. String *params, Cardinal *num_params)
  495. {
  496. (*promptfunction)(XawDialogGetValueString(promptDialog));
  497. CancelAction (widget, event, params, num_params);
  498. }
  499. static void
  500. MakePrompt(Widget centerw, const char *prompt,
  501. MakePromptFunc func, const char *def)
  502. {
  503. static Arg dialogArgs[] = {
  504. {XtNlabel, 0},
  505. {XtNvalue, 0},
  506. };
  507. Arg valueArgs[1];
  508. Arg centerArgs[2];
  509. Position source_x, source_y;
  510. Position dest_x, dest_y;
  511. Dimension center_width, center_height;
  512. Dimension prompt_width, prompt_height;
  513. Widget valueWidget;
  514. CancelAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0);
  515. promptShell = XtCreatePopupShell ("promptShell", transientShellWidgetClass,
  516. toplevel, NULL, (Cardinal) 0);
  517. dialogArgs[0].value = (XtArgVal)prompt;
  518. dialogArgs[1].value = (XtArgVal)def;
  519. promptDialog = XtCreateManagedWidget( "promptDialog", dialogWidgetClass,
  520. promptShell, dialogArgs, XtNumber (dialogArgs));
  521. XawDialogAddButton(promptDialog, "accept", NULL, (XtPointer) 0);
  522. XawDialogAddButton(promptDialog, "cancel", NULL, (XtPointer) 0);
  523. valueWidget = XtNameToWidget (promptDialog, "value");
  524. if (valueWidget) {
  525. XtSetArg (valueArgs[0], (String)XtNresizable, TRUE);
  526. XtSetValues (valueWidget, valueArgs, 1);
  527. /*
  528. * as resizable isn't set until just above, the
  529. * default value will be displayed incorrectly.
  530. * rectify the situation by resetting the values
  531. */
  532. XtSetValues (promptDialog, dialogArgs, XtNumber (dialogArgs));
  533. }
  534. XtSetKeyboardFocus (promptDialog, valueWidget);
  535. XtSetKeyboardFocus (toplevel, valueWidget);
  536. XtRealizeWidget (promptShell);
  537. /*
  538. * place the widget in the center of the "parent"
  539. */
  540. XtSetArg (centerArgs[0], XtNwidth, &center_width);
  541. XtSetArg (centerArgs[1], XtNheight, &center_height);
  542. XtGetValues (centerw, centerArgs, 2);
  543. XtSetArg (centerArgs[0], XtNwidth, &prompt_width);
  544. XtSetArg (centerArgs[1], XtNheight, &prompt_height);
  545. XtGetValues (promptShell, centerArgs, 2);
  546. source_x = (center_width - prompt_width) / 2;
  547. source_y = (center_height - prompt_height) / 3;
  548. XtTranslateCoords (centerw, source_x, source_y, &dest_x, &dest_y);
  549. XtSetArg (centerArgs[0], XtNx, dest_x);
  550. XtSetArg (centerArgs[1], XtNy, dest_y);
  551. XtSetValues (promptShell, centerArgs, 2);
  552. XtMapWidget(promptShell);
  553. promptfunction = func;
  554. }
  555. /*
  556. Local Variables:
  557. c-indent-level: 4
  558. c-continued-statement-offset: 4
  559. c-brace-offset: -4
  560. c-argdecl-indent: 4
  561. c-label-offset: -4
  562. c-tab-always-indent: nil
  563. End:
  564. */