xditview.c revision f80a6dcd
1/* $XConsortium: xditview.c,v 1.32 94/04/17 20:43:36 eswu Exp $ */ 2/* 3 4Copyright (c) 1991 X Consortium 5 6Permission is hereby granted, free of charge, to any person obtaining 7a copy of this software and associated documentation files (the 8"Software"), to deal in the Software without restriction, including 9without limitation the rights to use, copy, modify, merge, publish, 10distribute, sublicense, and/or sell copies of the Software, and to 11permit persons to whom the Software is furnished to do so, subject to 12the following conditions: 13 14The above copyright notice and this permission notice shall be included 15in all copies or substantial portions of the Software. 16 17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR 21OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23OTHER DEALINGS IN THE SOFTWARE. 24 25Except as contained in this notice, the name of the X Consortium shall 26not be used in advertising or otherwise to promote the sale, use or 27other dealings in this Software without prior written authorization 28from the X Consortium. 29 30*/ 31/* $XFree86: xc/programs/xditview/xditview.c,v 1.4tsi Exp $ */ 32/* 33 * xditview -- 34 * 35 * Display ditroff output in an X window 36 */ 37 38#include <X11/Intrinsic.h> 39#include <X11/StringDefs.h> 40#include <X11/Xatom.h> 41#include <X11/Shell.h> 42#include <X11/Xos.h> /* rindex declaration */ 43#include <X11/Xaw/Paned.h> 44#include <X11/Xaw/Panner.h> 45#include <X11/Xaw/Porthole.h> 46#include <X11/Xaw/Viewport.h> 47#include <X11/Xaw/Box.h> 48#include <X11/Xaw/Command.h> 49#include <X11/Xaw/Dialog.h> 50#include <X11/Xaw/Label.h> 51#include <X11/Xaw/MenuButton.h> 52#include <X11/Xaw/SimpleMenu.h> 53#include <X11/Xaw/SmeBSB.h> 54#include <X11/Xaw/AsciiText.h> 55 56#include "Dvi.h" 57 58#include "xdit.bm" 59#include "xdit_mask.bm" 60#include <stdio.h> 61#include <stdlib.h> 62 63/* Command line options table. Only resources are entered here...there is a 64 pass over the remaining options after XtParseCommand is let loose. */ 65 66static XrmOptionDescRec options[] = { 67{"-page", "*dvi.pageNumber", XrmoptionSepArg, NULL}, 68{"-backingStore", "*dvi.backingStore", XrmoptionSepArg, NULL}, 69{"-noPolyText", "*dvi.noPolyText", XrmoptionNoArg, "TRUE"}, 70{"-resolution", "*dvi.screenResolution",XrmoptionSepArg, NULL}, 71}; 72 73static char current_file_name[1024]; 74static FILE *current_file; 75 76static void MakePrompt(Widget, char *, void (*)(char *), char *); 77 78/* 79 * Report the syntax for calling xditview. 80 */ 81 82static void 83Syntax(char *call) 84{ 85 (void) printf ("Usage: %s [-fg <color>] [-bg <color>]\n", call); 86 (void) printf (" [-bd <color>] [-bw <pixels>] [-help]\n"); 87 (void) printf (" [-display displayname] [-geometry geom]\n"); 88 (void) printf (" [-page <page-number>] [-backing <backing-store>]\n"); 89 (void) printf (" [-resolution <screen-resolution>]\n\n"); 90 exit(1); 91} 92 93static void NewResolution (char *resString); 94static void NewFile (char *name); 95static void DisplayPageNumber (void); 96static void VisitFile (char *name, Boolean resetPage); 97static Widget toplevel, paned, porthole, dvi; 98#ifdef NOTDEF 99static Widget form, panner; 100#endif 101static Widget popupMenu; 102static Widget menuBar; 103static Widget fileMenuButton, fileMenu; 104static Widget pageNumber; 105 106static void NextPage(Widget entry, XtPointer name, XtPointer data); 107static void PreviousPage(Widget entry, XtPointer name, XtPointer data); 108static void SetResolution(Widget entry, XtPointer name, XtPointer data); 109static void OpenFile(Widget entry, XtPointer name, XtPointer data); 110static void RevisitFile(Widget entry, XtPointer name, XtPointer data); 111static void Quit(Widget entry, XtPointer closure, XtPointer data); 112 113struct menuEntry { 114 char *name; 115 void (*function)(Widget entry, XtPointer name, XtPointer data); 116}; 117 118static struct menuEntry popupMenuEntries[] = { 119 { "nextPage", NextPage }, 120 { "previousPage", PreviousPage }, 121 { "setResolution", SetResolution }, 122 { "openFile", OpenFile }, 123 { "revisitFile", RevisitFile }, 124 { "quit", Quit } 125}; 126 127static struct menuEntry fileMenuEntries[] = { 128 { "openFile", OpenFile }, 129 { "revisitFile", RevisitFile }, 130 { "setResolution", SetResolution }, 131 { "quit", Quit } 132}; 133 134static void NextPageAction(Widget, XEvent *, String *, Cardinal *); 135static void PreviousPageAction(Widget, XEvent *, String *, Cardinal *); 136static void SetResolutionAction(Widget, XEvent *, String *, Cardinal *); 137static void OpenFileAction(Widget, XEvent *, String *, Cardinal *); 138static void RevisitFileAction(Widget, XEvent *, String *, Cardinal *); 139static void QuitAction(Widget, XEvent *, String *, Cardinal *); 140static void AcceptAction(Widget, XEvent *, String *, Cardinal *); 141static void CancelAction(Widget, XEvent *, String *, Cardinal *); 142static void UpdatePageNumber(Widget, XEvent *, String *, Cardinal *); 143static void Noop(Widget, XEvent *, String *, Cardinal *); 144 145XtActionsRec xditview_actions[] = { 146 { "NextPage", NextPageAction }, 147 { "PreviousPage", PreviousPageAction }, 148 { "SetResolution", SetResolutionAction }, 149 { "OpenFile", OpenFileAction }, 150 { "Quit", QuitAction }, 151 { "Accept", AcceptAction }, 152 { "Cancel", CancelAction }, 153 { "SetPageNumber", UpdatePageNumber }, 154 { "Noop", Noop } 155}; 156 157static Atom wm_delete_window; 158 159#ifdef NOTDEF 160/* Function Name: PannerCallback 161 * Description: called when the panner has moved. 162 * Arguments: panner - the panner widget. 163 * closure - *** NOT USED ***. 164 * report_ptr - the panner record. 165 * Returns: none. 166 */ 167 168/* ARGSUSED */ 169static void 170PannerCallback(Widget w, XtPointer closure, XtPointer report_ptr) 171{ 172 Arg args[2]; 173 XawPannerReport *report = (XawPannerReport *) report_ptr; 174 175 if (!dvi) 176 return; 177 XtSetArg (args[0], XtNx, -report->slider_x); 178 XtSetArg (args[1], XtNy, -report->slider_y); 179 180 XtSetValues(dvi, args, 2); 181} 182 183/* Function Name: PortholeCallback 184 * Description: called when the porthole or its child has 185 * changed 186 * Arguments: porthole - the porthole widget. 187 * panner_ptr - the panner widget. 188 * report_ptr - the porthole record. 189 * Returns: none. 190 */ 191 192/* ARGSUSED */ 193static void 194PortholeCallback(Widget w, XtPointer panner_ptr, XtPointer report_ptr) 195{ 196 Arg args[10]; 197 Cardinal n = 0; 198 XawPannerReport *report = (XawPannerReport *) report_ptr; 199 Widget panner = (Widget) panner_ptr; 200 201 XtSetArg (args[n], XtNsliderX, report->slider_x); n++; 202 XtSetArg (args[n], XtNsliderY, report->slider_y); n++; 203 if (report->changed != (XawPRSliderX | XawPRSliderY)) { 204 XtSetArg (args[n], XtNsliderWidth, report->slider_width); n++; 205 XtSetArg (args[n], XtNsliderHeight, report->slider_height); n++; 206 XtSetArg (args[n], XtNcanvasWidth, report->canvas_width); n++; 207 XtSetArg (args[n], XtNcanvasHeight, report->canvas_height); n++; 208 } 209 XtSetValues (panner, args, n); 210} 211#endif 212 213int 214main(int argc, char **argv) 215{ 216 char *file_name = 0; 217 int i; 218 XtAppContext xtcontext; 219 Arg topLevelArgs[2]; 220 Widget entry; 221 222 XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL); 223 224 toplevel = XtAppInitialize(&xtcontext, "Xditview", 225 options, XtNumber (options), 226 &argc, argv, NULL, NULL, 0); 227 if (argc > 2) 228 Syntax(argv[0]); 229 230 XtAppAddActions(xtcontext, xditview_actions, XtNumber (xditview_actions)); 231 XtOverrideTranslations 232 (toplevel, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()")); 233 234 XtSetArg (topLevelArgs[0], XtNiconPixmap, 235 XCreateBitmapFromData (XtDisplay (toplevel), 236 XtScreen(toplevel)->root, 237 (char *) xdit_bits, 238 xdit_width, xdit_height)); 239 240 XtSetArg (topLevelArgs[1], XtNiconMask, 241 XCreateBitmapFromData (XtDisplay (toplevel), 242 XtScreen(toplevel)->root, 243 (char *) xdit_mask_bits, 244 xdit_mask_width, xdit_mask_height)); 245 XtSetValues (toplevel, topLevelArgs, 2); 246 if (argc > 1) 247 file_name = argv[1]; 248 249 /* 250 * create the popup menu and insert the entries 251 */ 252 popupMenu = XtCreatePopupShell ("popupMenu", simpleMenuWidgetClass, toplevel, 253 NULL, 0); 254 for (i = 0; i < XtNumber (popupMenuEntries); i++) { 255 entry = XtCreateManagedWidget(popupMenuEntries[i].name, 256 smeBSBObjectClass, popupMenu, 257 NULL, (Cardinal) 0); 258 XtAddCallback(entry, XtNcallback, popupMenuEntries[i].function, NULL); 259 } 260 261 paned = XtCreateManagedWidget("paned", panedWidgetClass, toplevel, 262 NULL, (Cardinal) 0); 263 menuBar = XtCreateManagedWidget ("menuBar", boxWidgetClass, paned, 0, 0); 264 265 fileMenuButton = XtCreateManagedWidget ("fileMenuButton", menuButtonWidgetClass, 266 menuBar, NULL, (Cardinal) 0); 267 fileMenu = XtCreatePopupShell ("fileMenu", simpleMenuWidgetClass, 268 fileMenuButton, NULL, (Cardinal) 0); 269 for (i = 0; i < XtNumber (fileMenuEntries); i++) { 270 entry = XtCreateManagedWidget(fileMenuEntries[i].name, 271 smeBSBObjectClass, fileMenu, 272 NULL, (Cardinal) 0); 273 XtAddCallback (entry, XtNcallback, fileMenuEntries[i].function, NULL); 274 } 275 276 (void) XtCreateManagedWidget ("prevButton", commandWidgetClass, 277 menuBar, NULL, (Cardinal) 0); 278 279 pageNumber = XtCreateManagedWidget("pageNumber", asciiTextWidgetClass, 280 menuBar, NULL, (Cardinal) 0); 281 282 (void) XtCreateManagedWidget ("nextButton", commandWidgetClass, 283 menuBar, NULL, (Cardinal) 0); 284 285#ifdef NOTDEF 286 form = XtCreateManagedWidget ("form", formWidgetClass, paned, 287 NULL, (Cardinal) 0); 288 panner = XtCreateManagedWidget ("panner", pannerWidgetClass, 289 form, NULL, 0); 290 porthole = XtCreateManagedWidget ("porthole", portholeWidgetClass, 291 form, NULL, 0); 292 XtAddCallback(porthole, 293 XtNreportCallback, PortholeCallback, (XtPointer) panner); 294 XtAddCallback(panner, 295 XtNreportCallback, PannerCallback, (XtPointer) porthole); 296#else 297 porthole = XtCreateManagedWidget ("viewport", viewportWidgetClass, 298 paned, NULL, 0); 299#endif 300 dvi = XtCreateManagedWidget ("dvi", dviWidgetClass, porthole, NULL, 0); 301 if (file_name) 302 VisitFile (file_name, FALSE); 303 XtRealizeWidget (toplevel); 304 wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", 305 False); 306 (void) XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel), 307 &wm_delete_window, 1); 308 XtAppMainLoop(xtcontext); 309 310 return 0; 311} 312 313static void 314DisplayPageNumber () 315{ 316 Arg arg[2]; 317 int actual_number, last_page; 318 XawTextBlock text; 319 int length; 320 char value[128]; 321 char *cur; 322 323 XtSetArg (arg[0], XtNpageNumber, &actual_number); 324 XtSetArg (arg[1], XtNlastPageNumber, &last_page); 325 XtGetValues (dvi, arg, 2); 326 if (actual_number == 0) 327 sprintf (value, "<none>"); 328 else if (last_page > 0) 329 sprintf (value, "%d of %d", actual_number, last_page); 330 else 331 sprintf (value, "%d", actual_number); 332 text.firstPos = 0; 333 text.length = strlen (value); 334 text.ptr = value; 335 text.format = FMT8BIT; 336 XtSetArg (arg[0], XtNstring, &cur); 337 XtGetValues (XawTextGetSource (pageNumber), arg, 1); 338 length = strlen (cur); 339 XawTextReplace (pageNumber, 0, length, &text); 340} 341 342static void 343SetPageNumber (int number) 344{ 345 Arg arg[1]; 346 347 XtSetArg (arg[0], XtNpageNumber, number); 348 XtSetValues (dvi, arg, 1); 349 DisplayPageNumber (); 350} 351 352static void 353UpdatePageNumber (Widget w, XEvent *xev, String *s, Cardinal *c) 354{ 355 char *string; 356 Arg arg[1]; 357 358 XtSetArg (arg[0], XtNstring, &string); 359 XtGetValues (XawTextGetSource(pageNumber), arg, 1); 360 SetPageNumber (atoi(string)); 361} 362 363static void 364NewResolution(resString) 365char *resString; 366{ 367 int res; 368 Arg arg[1]; 369 370 res = atoi (resString); 371 if (res <= 0) 372 return; 373 XtSetArg (arg[0], XtNscreenResolution, res); 374 XtSetValues (dvi, arg, 1); 375} 376 377static void 378VisitFile (char *name, Boolean resetPage) 379{ 380 Arg arg[3]; 381 char *n; 382 FILE *new_file; 383 Boolean seek = 0; 384 int i; 385 386 if (current_file) { 387 if (!strcmp (current_file_name, "-")) 388 ; 389 else if (current_file_name[0] == '|') 390 pclose (current_file); 391 else 392 fclose (current_file); 393 } 394 if (!strcmp (name, "-")) 395 new_file = stdin; 396 else if (name[0] == '|') 397 new_file = popen (name+1, "r"); 398 else { 399 new_file = fopen (name, "r"); 400 seek = 1; 401 } 402 if (!new_file) { 403 /* XXX display error message */ 404 return; 405 } 406 i = 0; 407 XtSetArg (arg[i], XtNfile, new_file); i++; 408 XtSetArg (arg[i], XtNseek, seek); i++; 409 if (resetPage) { 410 XtSetArg (arg[i], XtNpageNumber, 1); i++; 411 } 412 XtSetValues (dvi, arg, i); 413 XtSetArg (arg[0], XtNtitle, name); 414 if (name[0] != '/' && (n = rindex (name, '/'))) 415 n = n + 1; 416 else 417 n = name; 418 XtSetArg (arg[1], XtNiconName, n); 419 XtSetValues (toplevel, arg, 2); 420 strcpy (current_file_name, name); 421 current_file = new_file; 422 DisplayPageNumber (); 423} 424 425static void 426NewFile (name) 427char *name; 428{ 429 VisitFile (name, TRUE); 430} 431 432static char fileBuf[1024]; 433static char resolutionBuf[1024]; 434 435static void 436ResetMenuEntry (Widget entry) 437{ 438 Arg arg[1]; 439 440 XtSetArg (arg[0], XtNpopupOnEntry, entry); 441 XtSetValues (XtParent(entry) , arg, (Cardinal) 1); 442} 443 444/*ARGSUSED*/ 445static void 446NextPage (entry, name, data) 447 Widget entry; 448 XtPointer name, data; 449{ 450 NextPageAction(entry, NULL, NULL, NULL); 451 ResetMenuEntry (entry); 452} 453 454static void 455NextPageAction (Widget w, XEvent *xev, String *s, Cardinal *c) 456{ 457 Arg args[1]; 458 int number; 459 460 XtSetArg (args[0], XtNpageNumber, &number); 461 XtGetValues (dvi, args, 1); 462 SetPageNumber (number+1); 463} 464 465/*ARGSUSED*/ 466static void 467PreviousPage (entry, name, data) 468 Widget entry; 469 XtPointer name, data; 470{ 471 PreviousPageAction (entry, NULL, NULL, NULL); 472 ResetMenuEntry (entry); 473} 474 475static void 476PreviousPageAction (Widget w, XEvent *xev, String *s, Cardinal *c) 477{ 478 Arg args[1]; 479 int number; 480 481 XtSetArg (args[0], XtNpageNumber, &number); 482 XtGetValues (dvi, args, 1); 483 SetPageNumber (number-1); 484} 485 486/*ARGSUSED*/ 487static void 488SetResolution (entry, name, data) 489 Widget entry; 490 XtPointer name, data; 491{ 492 SetResolutionAction (entry, NULL, NULL, NULL); 493 ResetMenuEntry (entry); 494} 495 496static void 497SetResolutionAction (Widget w, XEvent *xev, String *s, Cardinal *c) 498{ 499 Arg args[1]; 500 int cur; 501 502 XtSetArg (args[0], XtNscreenResolution, &cur); 503 XtGetValues (dvi, args, 1); 504 sprintf (resolutionBuf, "%d", cur); 505 MakePrompt (toplevel, "Screen resolution:", NewResolution, resolutionBuf); 506} 507 508/*ARGSUSED*/ 509static void 510OpenFile (entry, name, data) 511 Widget entry; 512 XtPointer name, data; 513{ 514 OpenFileAction (entry, NULL, NULL, NULL); 515 ResetMenuEntry (entry); 516} 517 518static void 519OpenFileAction (Widget w, XEvent *xev, String *s, Cardinal *c) 520{ 521 if (current_file_name[0]) 522 strcpy (fileBuf, current_file_name); 523 else 524 fileBuf[0] = '\0'; 525 MakePrompt (toplevel, "File to open:", NewFile, fileBuf); 526} 527 528/*ARGSUSED*/ 529static void 530RevisitFile (entry, name, data) 531 Widget entry; 532 XtPointer name, data; 533{ 534 RevisitFileAction (entry, NULL, NULL, NULL); 535 ResetMenuEntry (entry); 536} 537 538static void 539RevisitFileAction (Widget w, XEvent *xev, String *s, Cardinal *c) 540{ 541 if (current_file_name[0]) 542 VisitFile (current_file_name, FALSE); 543} 544 545/*ARGSUSED*/ 546static void 547Quit (entry, closure, data) 548 Widget entry; 549 XtPointer closure, data; 550{ 551 QuitAction (entry, NULL, NULL, NULL); 552} 553 554static void 555QuitAction (Widget w, XEvent *xev, String *s, Cardinal *c) 556{ 557 exit (0); 558} 559 560Widget promptShell, promptDialog; 561void (*promptfunction)(char *); 562 563/* ARGSUSED */ 564static 565void CancelAction (widget, event, params, num_params) 566 Widget widget; 567 XEvent *event; 568 String *params; 569 Cardinal *num_params; 570{ 571 if (promptShell) { 572 XtSetKeyboardFocus(toplevel, (Widget) None); 573 XtDestroyWidget(promptShell); 574 promptShell = (Widget) 0; 575 } 576} 577 578 579/* ARGSUSED */ 580static 581void AcceptAction (widget, event, params, num_params) 582 Widget widget; 583 XEvent *event; 584 String *params; 585 Cardinal *num_params; 586{ 587 (*promptfunction)(XawDialogGetValueString(promptDialog)); 588 CancelAction (widget, event, params, num_params); 589} 590 591static 592void Noop (Widget w, XEvent *xev, String *s, Cardinal *c) 593{ 594} 595 596static void 597MakePrompt(centerw, prompt, func, def) 598Widget centerw; 599char *prompt; 600void (*func)(char *); 601char *def; 602{ 603 static Arg dialogArgs[] = { 604 {XtNlabel, (XtArgVal) 0}, 605 {XtNvalue, (XtArgVal) 0}, 606 }; 607 Arg valueArgs[1]; 608 Arg centerArgs[2]; 609 Position source_x, source_y; 610 Position dest_x, dest_y; 611 Dimension center_width, center_height; 612 Dimension prompt_width, prompt_height; 613 Widget valueWidget; 614 615 CancelAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0); 616 promptShell = XtCreatePopupShell ("promptShell", transientShellWidgetClass, 617 toplevel, NULL, (Cardinal) 0); 618 dialogArgs[0].value = (XtArgVal)prompt; 619 dialogArgs[1].value = (XtArgVal)def; 620 promptDialog = XtCreateManagedWidget( "promptDialog", dialogWidgetClass, 621 promptShell, dialogArgs, XtNumber (dialogArgs)); 622 XawDialogAddButton(promptDialog, "accept", NULL, NULL); 623 XawDialogAddButton(promptDialog, "cancel", NULL, NULL); 624 valueWidget = XtNameToWidget (promptDialog, "value"); 625 if (valueWidget) { 626 XtSetArg (valueArgs[0], XtNresizable, TRUE); 627 XtSetValues (valueWidget, valueArgs, 1); 628 /* 629 * as resizable isn't set until just above, the 630 * default value will be displayed incorrectly. 631 * rectify the situation by resetting the values 632 */ 633 XtSetValues (promptDialog, dialogArgs, XtNumber (dialogArgs)); 634 } 635 XtSetKeyboardFocus (promptDialog, valueWidget); 636 XtSetKeyboardFocus (toplevel, valueWidget); 637 XtRealizeWidget (promptShell); 638 /* 639 * place the widget in the center of the "parent" 640 */ 641 XtSetArg (centerArgs[0], XtNwidth, ¢er_width); 642 XtSetArg (centerArgs[1], XtNheight, ¢er_height); 643 XtGetValues (centerw, centerArgs, 2); 644 XtSetArg (centerArgs[0], XtNwidth, &prompt_width); 645 XtSetArg (centerArgs[1], XtNheight, &prompt_height); 646 XtGetValues (promptShell, centerArgs, 2); 647 source_x = (int)(center_width - prompt_width) / 2; 648 source_y = (int)(center_height - prompt_height) / 3; 649 XtTranslateCoords (centerw, source_x, source_y, &dest_x, &dest_y); 650 XtSetArg (centerArgs[0], XtNx, dest_x); 651 XtSetArg (centerArgs[1], XtNy, dest_y); 652 XtSetValues (promptShell, centerArgs, 2); 653 XtMapWidget(promptShell); 654 promptfunction = func; 655} 656