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