xditview.c revision 65912f00
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 145static XtActionsRec 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 = NULL; 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, NULL, 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 (void) 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(char *resString) 365{ 366 int res; 367 Arg arg[1]; 368 369 res = atoi (resString); 370 if (res <= 0) 371 return; 372 XtSetArg (arg[0], XtNscreenResolution, res); 373 XtSetValues (dvi, arg, 1); 374} 375 376static void 377VisitFile (char *name, Boolean resetPage) 378{ 379 Arg arg[3]; 380 char *n; 381 FILE *new_file; 382 Boolean seek = 0; 383 int i; 384 385 if (current_file) { 386 if (!strcmp (current_file_name, "-")) 387 ; 388 else if (current_file_name[0] == '|') 389 pclose (current_file); 390 else 391 fclose (current_file); 392 } 393 if (!strcmp (name, "-")) 394 new_file = stdin; 395 else if (name[0] == '|') 396 new_file = popen (name+1, "r"); 397 else { 398 new_file = fopen (name, "r"); 399 seek = 1; 400 } 401 if (!new_file) { 402 /* XXX display error message */ 403 return; 404 } 405 i = 0; 406 XtSetArg (arg[i], XtNfile, new_file); i++; 407 XtSetArg (arg[i], XtNseek, seek); i++; 408 if (resetPage) { 409 XtSetArg (arg[i], XtNpageNumber, 1); i++; 410 } 411 XtSetValues (dvi, arg, i); 412 XtSetArg (arg[0], XtNtitle, name); 413 if (name[0] != '/' && (n = rindex (name, '/'))) 414 n = n + 1; 415 else 416 n = name; 417 XtSetArg (arg[1], XtNiconName, n); 418 XtSetValues (toplevel, arg, 2); 419 strcpy (current_file_name, name); 420 current_file = new_file; 421 DisplayPageNumber (); 422} 423 424static void 425NewFile (char *name) 426{ 427 VisitFile (name, TRUE); 428} 429 430static char fileBuf[1024]; 431static char resolutionBuf[1024]; 432 433static void 434ResetMenuEntry (Widget entry) 435{ 436 Arg arg[1]; 437 438 XtSetArg (arg[0], XtNpopupOnEntry, entry); 439 XtSetValues (XtParent(entry) , arg, (Cardinal) 1); 440} 441 442/*ARGSUSED*/ 443static void 444NextPage (Widget entry, XtPointer name, XtPointer data) 445{ 446 NextPageAction(entry, NULL, NULL, NULL); 447 ResetMenuEntry (entry); 448} 449 450static void 451NextPageAction (Widget w, XEvent *xev, String *s, Cardinal *c) 452{ 453 Arg args[1]; 454 int number; 455 456 XtSetArg (args[0], XtNpageNumber, &number); 457 XtGetValues (dvi, args, 1); 458 SetPageNumber (number+1); 459} 460 461/*ARGSUSED*/ 462static void 463PreviousPage (Widget entry, XtPointer name, XtPointer data) 464{ 465 PreviousPageAction (entry, NULL, NULL, NULL); 466 ResetMenuEntry (entry); 467} 468 469static void 470PreviousPageAction (Widget w, XEvent *xev, String *s, Cardinal *c) 471{ 472 Arg args[1]; 473 int number; 474 475 XtSetArg (args[0], XtNpageNumber, &number); 476 XtGetValues (dvi, args, 1); 477 SetPageNumber (number-1); 478} 479 480/*ARGSUSED*/ 481static void 482SetResolution (Widget entry, XtPointer name, XtPointer data) 483{ 484 SetResolutionAction (entry, NULL, NULL, NULL); 485 ResetMenuEntry (entry); 486} 487 488static void 489SetResolutionAction (Widget w, XEvent *xev, String *s, Cardinal *c) 490{ 491 Arg args[1]; 492 int cur; 493 494 XtSetArg (args[0], XtNscreenResolution, &cur); 495 XtGetValues (dvi, args, 1); 496 sprintf (resolutionBuf, "%d", cur); 497 MakePrompt (toplevel, "Screen resolution:", NewResolution, resolutionBuf); 498} 499 500/*ARGSUSED*/ 501static void 502OpenFile (Widget entry, XtPointer name, XtPointer data) 503{ 504 OpenFileAction (entry, NULL, NULL, NULL); 505 ResetMenuEntry (entry); 506} 507 508static void 509OpenFileAction (Widget w, XEvent *xev, String *s, Cardinal *c) 510{ 511 if (current_file_name[0]) 512 strcpy (fileBuf, current_file_name); 513 else 514 fileBuf[0] = '\0'; 515 MakePrompt (toplevel, "File to open:", NewFile, fileBuf); 516} 517 518/*ARGSUSED*/ 519static void 520RevisitFile (Widget entry, XtPointer name, XtPointer data) 521{ 522 RevisitFileAction (entry, NULL, NULL, NULL); 523 ResetMenuEntry (entry); 524} 525 526static void 527RevisitFileAction (Widget w, XEvent *xev, String *s, Cardinal *c) 528{ 529 if (current_file_name[0]) 530 VisitFile (current_file_name, FALSE); 531} 532 533/*ARGSUSED*/ 534static void 535Quit (Widget entry, XtPointer closure, XtPointer data) 536{ 537 QuitAction (entry, NULL, NULL, NULL); 538} 539 540static void 541QuitAction (Widget w, XEvent *xev, String *s, Cardinal *c) 542{ 543 exit (0); 544} 545 546static Widget promptShell, promptDialog; 547static void (*promptfunction)(char *); 548 549/* ARGSUSED */ 550static 551void CancelAction (Widget widget, XEvent *event, 552 String *params, Cardinal *num_params) 553{ 554 if (promptShell) { 555 XtSetKeyboardFocus(toplevel, (Widget) None); 556 XtDestroyWidget(promptShell); 557 promptShell = (Widget) 0; 558 } 559} 560 561 562/* ARGSUSED */ 563static 564void AcceptAction (Widget widget, XEvent *event, 565 String *params, Cardinal *num_params) 566{ 567 (*promptfunction)(XawDialogGetValueString(promptDialog)); 568 CancelAction (widget, event, params, num_params); 569} 570 571static 572void Noop (Widget w, XEvent *xev, String *s, Cardinal *c) 573{ 574} 575 576static void 577MakePrompt(Widget centerw, char *prompt, void (*func)(char *), char *def) 578{ 579 static Arg dialogArgs[] = { 580 {XtNlabel, (XtArgVal) 0}, 581 {XtNvalue, (XtArgVal) 0}, 582 }; 583 Arg valueArgs[1]; 584 Arg centerArgs[2]; 585 Position source_x, source_y; 586 Position dest_x, dest_y; 587 Dimension center_width, center_height; 588 Dimension prompt_width, prompt_height; 589 Widget valueWidget; 590 591 CancelAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0); 592 promptShell = XtCreatePopupShell ("promptShell", transientShellWidgetClass, 593 toplevel, NULL, (Cardinal) 0); 594 dialogArgs[0].value = (XtArgVal)prompt; 595 dialogArgs[1].value = (XtArgVal)def; 596 promptDialog = XtCreateManagedWidget( "promptDialog", dialogWidgetClass, 597 promptShell, dialogArgs, XtNumber (dialogArgs)); 598 XawDialogAddButton(promptDialog, "accept", NULL, NULL); 599 XawDialogAddButton(promptDialog, "cancel", NULL, NULL); 600 valueWidget = XtNameToWidget (promptDialog, "value"); 601 if (valueWidget) { 602 XtSetArg (valueArgs[0], XtNresizable, TRUE); 603 XtSetValues (valueWidget, valueArgs, 1); 604 /* 605 * as resizable isn't set until just above, the 606 * default value will be displayed incorrectly. 607 * rectify the situation by resetting the values 608 */ 609 XtSetValues (promptDialog, dialogArgs, XtNumber (dialogArgs)); 610 } 611 XtSetKeyboardFocus (promptDialog, valueWidget); 612 XtSetKeyboardFocus (toplevel, valueWidget); 613 XtRealizeWidget (promptShell); 614 /* 615 * place the widget in the center of the "parent" 616 */ 617 XtSetArg (centerArgs[0], XtNwidth, ¢er_width); 618 XtSetArg (centerArgs[1], XtNheight, ¢er_height); 619 XtGetValues (centerw, centerArgs, 2); 620 XtSetArg (centerArgs[0], XtNwidth, &prompt_width); 621 XtSetArg (centerArgs[1], XtNheight, &prompt_height); 622 XtGetValues (promptShell, centerArgs, 2); 623 source_x = (int)(center_width - prompt_width) / 2; 624 source_y = (int)(center_height - prompt_height) / 3; 625 XtTranslateCoords (centerw, source_x, source_y, &dest_x, &dest_y); 626 XtSetArg (centerArgs[0], XtNx, dest_x); 627 XtSetArg (centerArgs[1], XtNy, dest_y); 628 XtSetValues (promptShell, centerArgs, 2); 629 XtMapWidget(promptShell); 630 promptfunction = func; 631} 632