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