argv@island.uu.net (Dan Heller) (07/21/89)
Submitted-by: Mark Moraes <moraes@ai.toronto.edu> Posting-number: Volume 4, Issue 65 Archive-name: xtroff/part18 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 18 (of 18)." # Contents: xtroff/xwindows.c # Wrapped by moraes@neat.ai on Thu Jul 13 20:55:26 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'xtroff/xwindows.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xtroff/xwindows.c'\" else echo shar: Extracting \"'xtroff/xwindows.c'\" \(35916 characters\) sed "s/^X//" >'xtroff/xwindows.c' <<'END_OF_FILE' X#ifndef SUNTOOLS X/* X * X Windows routines - These pretty closely mirror the SunView X * interface in sunwindows.c. The main difference is that this has more X * and more flexible bindings, and has the Next-Section, Prev-Section X * bindings. This one also lacks the StatusPanel stuff - nice, but X * somewhat unnecessary in my opinion. Instead, it has an emacs-style X * Minibuffer at the bottom for interaction. It also lacks the feature X * to Print the file or page - sheer laziness. The code is there - just X * didn't bother to call the routines because it also means fixing the X * printcaps. Sigh! The suntroff code is remarkably independent of the X * window system - the routines in this file or windows.c set up the X * frame window (a Form), the drawing window (Chris Peterson's X * Window.c, lifted straight from xman. It should be in Xaw), the event X * handlers, and menus(the menu widget in contrib/menus). The only X * other X dependent code is in draw.c and a small chunk in the X * LoadFontBits() routine in font.c! Its been ifdef'ed assuming X * that if you're not compiling for SUNTOOLS, you're compiling for X * X11. - Mark Moraes. X */ X#ifndef lint Xstatic char rcsid[]="$Header: xwindows.c,v 1.6 89/03/01 23:38:29 xwindows Exp $"; X#endif X X#include <stdio.h> X#include <ctype.h> X#include <signal.h> X#include <X11/Intrinsic.h> X#include <X11/StringDefs.h> X#include <X11/Shell.h> X#include <X11/Scroll.h> X#include <X11/Form.h> X#include "Window.h" /* Chris Peterson's Window widget */ X#include "Minibuf.h" /* My Minibuf widget */ X#include "Menu.h" /* contrib/menus after Dana Chee's fixes */ X#include <X11/cursorfont.h> X#include <X11/Xutil.h> X X#define YES 1 X#define NO 0 X#define ABORT -1 X X/* X * These are the various actions allowed in the canvas window - each X * related to a procedure X */ Xstatic void StartPan(), EndPan(), PagePan(), Number(), EscapeNumber(), X GoToPage(), ForwardPage(), BackPage(), NextSection(), PrevSection(), X Quit(), SetMenuPos(), MenuSelection(), Popdown(), Rerasterize(), X MousePrintPage(), MousePrintDocument(); X Xstatic XtActionsRec canvasActionTable[] = { X {"SetMenuPos", SetMenuPos}, X {"start-pan", StartPan}, X {"end-pan", EndPan}, X {"page-pan", PagePan}, X {"number", Number}, X {"escape", EscapeNumber}, X {"go-to-page", GoToPage}, X {"forward-page",ForwardPage}, X {"back-page", BackPage}, X {"print-page", MousePrintPage}, X {"print-document", MousePrintDocument}, X {"next-section",NextSection}, X {"prev-section",PrevSection}, X {"rerasterize", Rerasterize}, X {"quit", Quit}, X}; X X/* We want the menu to go away when the button comes up */ Xstatic String menuTransTbl = "<Btn3Up>: MenuPopdown(popupShell)"; X X/* X * These are default bindings for the actions in the canvas window. All X * actions except MenuPopup and MenuPopdown are defined in the action X * table above, and have corresp callback routines in this file. X * MenuPopup and MenuPopdown are provided by the Xt Intrinsics - for X * some reason, it doesn't seem possible to create a spring-loaded X * shell from an application other than by these two actions. I'd have X * preferred an XtPopup() with a spring-loaded parameter, and there's X * even such a routine in the Toolkit - _XtPopup! Of course, I may X * just be missing something obvious... I plead guilty to complete X * (well, almost complete) incomprehension of the Toolkit Intrinsics X * doc. - moraes X */ Xstatic String canvasTransTbl = X "<Btn3Down>: SetMenuPos() MenuPopup(popupShell)\n\ X <Btn3Up>: MenuPopdown(popupShell)\n\ X <Btn2Down>: start-pan()\n\ X <Btn2Up>: end-pan()\n\ X <LeaveWindow>: end-pan()\n\ X <Btn2Motion>: page-pan()\n\ X <Key>0x30: number()\n\ X <Key>0x31: number()\n\ X <Key>0x32: number()\n\ X <Key>0x33: number()\n\ X <Key>0x34: number()\n\ X <Key>0x35: number()\n\ X <Key>0x36: number()\n\ X <Key>0x37: number()\n\ X <Key>0x38: number()\n\ X <Key>0x39: number()\n\ X <Key>0xff1b: escape()\n\ X Shift<Key>P: print-page()\n\ X <Key>P: back-page()\n\ X <Key>B: back-page()\n\ X <Key>-: back-page()\n\ X <Key>0xff7f: back-page()\n\ X <Key>0xff08: back-page()\n\ X <Key>0xffff: back-page()\n\ X Ctrl<Key>H: back-page()\n\ X <Key>0xff51: back-page()\n\ X <Key>N: forward-page()\n\ X <Key>F: forward-page()\n\ X <Key>+: forward-page()\n\ X <Key>0xff0d: forward-page()\n\ X Ctrl<Key>M: forward-page()\n\ X <Key>0xff0a: forward-page()\n\ X Ctrl<Key>J: forward-page()\n\ X <Key>0xff53: forward-page()\n\ X Shift<Btn1Down>:prev-section()\n\ X <Key>0xff52: prev-section()\n\ X <Btn1Down>: next-section()\n\ X <Key>0x20: next-section()\n\ X <Key>0xff54: next-section()\n\ X <Key>G: go-to-page()\n\ X <Key>R: rerasterize()\n\ X <Key>Q: quit()\n\ X "; X X#include "suntroff.h" X X/* Preserved most of the sunview names */ XWindow OuterFrame; XWidget BaseFrame; /* Top Level Window Frame */ XWidget CanvasWidget; XWindow DrawingCanvas; /* Main Drawing Window for Text */ XWidget MainMenu; /* Top Level User Menu */ XWidget PopupShell; /* Popup Shell enclosing the Main menu */ XWidget HorizScroll; /* Horizontal Scroll Bar */ XWidget VertScroll; /* Vertical Scroll Bar */ XWidget InputWidget = NULL; /* Minibuffer widget for input and dislay */ XWindow InputWin; XPixmap PagePixRect; /* Full Page Pix Rect for Drawing Page */ Xint ViewLeft = 0, ViewTop = 0; /* Page Offset for display */ X/* Set these to the window height and width */ Xint ViewWidth = 0, ViewHeight = 0; Xint OriginalX = -1; Xint OriginalY = -1; Xint Scrollbars = 1; /* Does User want scrollbars????? */ Xchar *homeDir; Xchar *Printer; X X/* X * The following icon of a hand was generated by Stefano Concino@SPAR. X */ X#define hand_width 16 X#define hand_height 16 X#define hand_x_hot 8 X#define hand_y_hot 8 Xstatic char hand_bits[] = { X 0x80, 0x00, 0x40, 0x09, 0x48, 0x15, 0x54, 0x15, 0x54, 0x15, 0x54, 0x15, X 0x54, 0x15, 0x54, 0x15, 0x74, 0xd2, 0x04, 0xa8, 0x08, 0xa8, 0x18, 0xa8, X 0x30, 0x90, 0x20, 0x40, 0x20, 0x20, 0x60, 0x18}; X Xstatic char hand_mask_bits[] = { X 0xc0, 0x09, 0x68, 0x1d, 0x7e, 0x37, 0x76, 0x37, 0x76, 0x37, 0x76, 0x37, X 0x76, 0x37, 0x76, 0xf7, 0x76, 0xf2, 0x06, 0xb8, 0x0e, 0xb8, 0x1c, 0xb8, X 0x3c, 0x90, 0x38, 0xc0, 0x30, 0x60, 0x70, 0x38}; X X#include "ditroff.bm" X XCursor HandCursor; XCursor WorkingCursor; XCursor WaitCursor; XCursor TextCursor; X XXWMHints xwmh; X XPixel fgcolor, bgcolor; X/* Needed for the undocumented XCreatePixmapCursor() */ Xstatic XColor bg = {0, 0, 0, 0}; Xstatic XColor fg = {0, ~0, ~0, ~0}; Xunsigned int depth; XDimension xwidth, xheight; X XDisplay *dpy; XScreen *scn; XGC gc; /* The Graphic context we use for all drawing */ XGC fillgc; /* Used for filled objects - presently only bullets */ XGC cleargc; /* The GC used for clearing the Pixmap */ X X/* X * DON'T CHANGE THE ORDER OF THE ARGS IN THE VARIOUS ARG STRUCTS. IF X * YOU WANT TO ADD STUFF, ADD IT AT THE END OF THE STRUCT, BECAUSE WE X * REFER TO SOME OF THE ELEMENTS BY POSITION IN THE CODE. X */ X/* No spacing between the widgets on the Form */ Xstatic Arg form_args[] = { X {XtNdefaultDistance, (XtArgVal) 0}, X}; X Xstatic void finished_input(); Xstatic XtCallbackRec minibufCallbacks[] = { X {finished_input, NULL}, X {NULL, NULL}, X}; X Xstatic Arg minibuf_args[] = { X {XtNwidth, (XtArgVal) 0}, X {XtNfinishedCallback, (XtArgVal) minibufCallbacks}, X {XtNfromVert, (XtArgVal) NULL}, X {XtNresizable, (XtArgVal) False}, X}; X X/* we use this when we ask what the various attributes of the Canvas. */ Xstatic Arg query_args[] = { X {XtNbackground, (XtArgVal) &bgcolor}, X {XtNforeground, (XtArgVal) &fgcolor}, X {XtNwidth, (XtArgVal) &xwidth}, X {XtNheight, (XtArgVal) &xheight}, X}; X X/* args for the canvas window - we fill in translations by hand */ Xstatic Arg canvas_args[] = { X {XtNwidth, (XtArgVal) 950}, X {XtNheight, (XtArgVal) 830}, X {XtNfromHoriz, (XtArgVal) NULL}, X {XtNtranslations, 0}, X}; X Xstatic void Scrolled(); Xstatic XtCallbackRec scrollCallbacks[] = { X { Scrolled, NULL }, X { NULL, NULL }, X}; X Xstatic void Jumped(); Xstatic XtCallbackRec jumpCallbacks[] = { X { Jumped, NULL }, X { NULL, NULL }, X}; X X/* X * We change the XtNlength, XtNorientation and XtNfromHoriz by getting X * the size from the Canvas - don't take this value seriously. X * XtNfromHoriz also changes to XtNfromVert. X */ Xstatic Arg scroll_args[] = { X {XtNlength, (XtArgVal) 850}, X {XtNorientation, (XtArgVal) XtorientVertical}, X {XtNfromHoriz, (XtArgVal) NULL}, X {XtNscrollProc, (XtArgVal) scrollCallbacks}, X {XtNjumpProc, (XtArgVal) jumpCallbacks}, X}; X Xstatic MenuItemsList menu_list[] = { X {"Rerasterize", MenuSelection, (caddr_t) 1, 0}, X {"Next Page", MenuSelection, (caddr_t) 2, 0}, X {"Previous Page", MenuSelection, (caddr_t) 3, 0}, X {"Next Page Section", MenuSelection, (caddr_t) 4, 0}, X {"Previous Page Section", MenuSelection, (caddr_t) 5, 0}, X {"Show Status", MenuSelection, (caddr_t) 6, 0}, X {"Search Forward", MenuSelection, (caddr_t) 7, 0}, X {"Search Backward", MenuSelection, (caddr_t) 8, 0}, X {"Change File", MenuSelection, (caddr_t) 9, 0}, X {"Change Command", MenuSelection, (caddr_t) 10, 0}, X {"Go To Page", MenuSelection, (caddr_t) 11, 0}, X {"Print Page", MenuSelection, (caddr_t) 12, 0}, X {"Print Document", MenuSelection, (caddr_t) 13, 0}, X {"Set Printer", MenuSelection, (caddr_t) 14, 0}, X {"Quit", MenuSelection, (caddr_t) 0, 0}, X {NULL, NULL, NULL, NULL} X}; X Xstatic Arg menu_args[] = { X {XtNmenuItemsList, (XtArgVal) menu_list }, X {XtNtranslations, 0}, X}; X Xstatic Arg shell_args[] = { X {XtNtranslations, 0}, X}; X Xstatic int CurrentPage = 1; Xchar FileName[BUFSIZ] = ""; /* File containing ditroff output */ Xchar TempFileName[BUFSIZ]; /* Temp file that can be deleted. */ Xchar CommandString[BUFSIZ] = "";/* String pointer to ditroff command */ Xchar *ActualFileName; /* File that buffers ditroff output */ Xint PageRequest = 0; /* Partially read page number request */ Xint CommandMode = 0; /* Taking input from file or command line */ X/* not used in the X version - we don't print any messages. sigh! one day... */ Xint ErrorsPending = 0; /* Set if errors are pending and need to be X * displayed. Used in case tool is iconic X * when error message is needed. This boolean X * variable is checked at redisplay time. X * This was done at the suggestion of X * davy@ecn.purdue.edu.......11/28/86 X */ Xint isMapped = 0; Xchar *SearchItem; Xint SUNRES = 120; X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X char *option; X XGCValues gcv; /* Struct for creating GC */ X Pixmap cursorPixmap, cursorMask; X void RepaintCanvas(); X static void RecordMapStatus(); X Widget topLevel; X XtTranslations canvasTranslations; X XtTranslations menuTranslations; X extern char *getenv(); X X if ((homeDir = getenv("HOME")) == NULL) X homeDir = ""; X if ((Printer = getenv("PRINTER")) == NULL) X Printer = "PostScript"; X /* make the top level using argc, argv */ X topLevel = XtInitialize("xtroff", "TroffPreviewer", X (XrmOptionDescRec *) NULL, 0, (Cardinal *) &argc, argv); X dpy = XtDisplay(topLevel); X scn = XtScreen(topLevel); X depth = DefaultDepthOfScreen(scn); X /* just one option for ourselves - rest are Toolkit options */ X if (option = XGetDefault(dpy, "xtroff", "scrollbar")) { X if (strcmp(option, "on") == 0) X Scrollbars = 1; X else X Scrollbars = 0; X } X argv++; X while (*argv && argv[0][0] == '-'){ X if (strncmp(argv[0],"-scrollbar",4) == NULL){ X Scrollbars = 0; X } else if (strncmp(argv[0],"-full",3) == NULL){ X SUNRES = 75; X canvas_args[0].value = 647; X } else if (strncmp(argv[0],"-command",3) == NULL){ X *CommandString = '\0'; X while (*++argv) { X strcat(CommandString,*argv); X strcat(CommandString, " "); X } X CommandMode = 1; X } else { X fprintf(stderr,"Unknown option %s\n",argv[0]); X } X if (*argv){ X argv++; X } X } X if (argv[0] && argv[0][0]){ X CommandMode = 0; X strcpy(FileName,argv[0]); X } X#ifdef DEBUG X if (CommandMode) X printf("Command = \"%s\"\n", CommandString); X else { X if (FileName) printf("File = \"%s\"\n", FileName); X else printf ("reading from stdin"); X } X#endif X /* CreatePopUpPanel(); */ X XtAddActions(canvasActionTable, XtNumber(canvasActionTable)); X canvasTranslations = XtParseTranslationTable(canvasTransTbl); X BaseFrame = XtCreateManagedWidget("form", formWidgetClass, topLevel, X form_args, XtNumber(form_args)); X canvas_args[3].value = (XtArgVal) canvasTranslations; X CanvasWidget = XtCreateManagedWidget("canvas", windowWidgetClass, X BaseFrame, canvas_args, XtNumber(canvas_args)); X XtGetValues(CanvasWidget, query_args, XtNumber(query_args)); X ViewWidth = xwidth; X ViewHeight = xheight; X if (Scrollbars) { X /* vertical scrollbar to the right of the canvas */ X XtSetArg(scroll_args[0], XtNlength, xheight); X XtSetArg(scroll_args[2], XtNfromHoriz, CanvasWidget); X VertScroll = XtCreateManagedWidget("vscroll", X scrollbarWidgetClass, BaseFrame, X scroll_args, XtNumber(scroll_args)); X /* horizontal scrollbar below the canvas */ X XtSetArg(scroll_args[0], XtNlength, xwidth); X XtSetArg(scroll_args[1], XtNorientation, XtorientHorizontal); X XtSetArg(scroll_args[2], XtNfromVert, CanvasWidget); X HorizScroll = XtCreateManagedWidget("hscroll", X scrollbarWidgetClass, BaseFrame, X scroll_args, XtNumber(scroll_args)); X } X XtAddEventHandler(CanvasWidget, (EventMask) ExposureMask, NULL, X RepaintCanvas, "redraw_data"); X XtAddEventHandler(CanvasWidget, (EventMask) StructureNotifyMask, NULL, X RecordMapStatus, "map_data"); X /* X * make a menu or button box - ShowStatus, ReRasterize, Print, X * Print Page, previous Page, Next Page, Quit X */ X menuTranslations = XtParseTranslationTable(menuTransTbl); X shell_args[0].value = menu_args[1].value = (XtArgVal) menuTranslations; X PopupShell = XtCreatePopupShell ("popupShell", X overrideShellWidgetClass, X CanvasWidget, X (ArgList) shell_args, X XtNumber(shell_args)); X MainMenu = XtCreateManagedWidget ("mainMenu", X menuWidgetClass, X PopupShell, X (ArgList) menu_args, X XtNumber (menu_args)); X minibuf_args[0].value = (XtArgVal) ViewWidth; X if (Scrollbars) X minibuf_args[2].value = (XtArgVal) HorizScroll; X else X minibuf_args[2].value = (XtArgVal) CanvasWidget; X InputWidget = XtCreateManagedWidget("minibuf", minibufWidgetClass, X BaseFrame, minibuf_args, XtNumber(minibuf_args)); X XtRealizeWidget(topLevel); X DrawingCanvas = XtWindow(CanvasWidget); X OuterFrame = XtWindow(topLevel); X InputWin = XtWindow(InputWidget); X X fg.pixel = fgcolor; X bg.pixel = bgcolor; X XQueryColor(dpy, DefaultColormapOfScreen(scn), &fg); X XQueryColor(dpy, DefaultColormapOfScreen(scn), &bg); X cursorPixmap = XCreateBitmapFromData(dpy, DrawingCanvas, X hand_bits, hand_width, hand_height); X cursorMask = XCreateBitmapFromData(dpy, DrawingCanvas, X hand_mask_bits, hand_width, hand_height); X HandCursor = XCreatePixmapCursor(dpy, cursorPixmap, cursorMask, X &fg, &bg, hand_x_hot, hand_y_hot); X XFreePixmap(dpy, cursorPixmap); X XFreePixmap(dpy, cursorMask); X X xwmh.icon_pixmap = XCreatePixmapFromBitmapData(dpy, XtWindow(topLevel), X ditroff_bits, ditroff_width, ditroff_height, fgcolor, bgcolor, depth); X xwmh.flags = IconPixmapHint; X XSetWMHints(dpy, XtWindow(topLevel), &xwmh); X WorkingCursor = XCreateFontCursor(dpy, XC_diamond_cross); X WaitCursor = XCreateFontCursor(dpy, XC_watch); X TextCursor = XCreateFontCursor(dpy, XC_xterm); X XDefineCursor(dpy, DrawingCanvas, WorkingCursor); X gcv.font = XLoadFont(dpy, "variable"); X gcv.foreground = fgcolor; X gcv.background = bgcolor; X gcv.function = GXcopy; X gc = XCreateGC(dpy, DrawingCanvas, X (GCForeground | GCBackground | GCFunction | GCFont), &gcv); X gcv.foreground = bgcolor; X gcv.background = fgcolor; X cleargc = XCreateGC(dpy, DrawingCanvas, X (GCForeground | GCBackground | GCFunction), &gcv); X gcv.foreground = fgcolor; X gcv.background = bgcolor; X gcv.function = GXcopy; X gcv.fill_style = FillSolid; X gcv.arc_mode = ArcPieSlice; X fillgc = XCreateGC(dpy, DrawingCanvas, X (GCForeground | GCBackground | GCFunction | GCFillStyle | GCArcMode), X &gcv); X /* Alloc a 1 bit deep pixmap if PAGE_PIXEL_WIDTH X PAGE_PIXEL_HEIGHT */ X PagePixRect = XCreatePixmap(dpy, DrawingCanvas, X (unsigned int) PAGE_PIXEL_WIDTH, (unsigned int) PAGE_PIXEL_HEIGHT, X depth); X XFlush(dpy); X /* X * We'll keep changing fonts - simpler, but is it fast enough? X * Should we try setting the font path X */ X#ifdef DEBUG X { X int nfonts; X int i; X char **fonts = XGetFontPath(dpy, &nfonts); X for (i = 0; i < nfonts; i++) { X printf("\"%s\"\n", fonts[i]); X } X XFreeFontPath(fonts); X } X#endif X XtMainLoop(); X if (*TempFileName) X (void) unlink(TempFileName); X exit(0); X} X X/*ARGSUSED*/ Xvoid XRepaintCanvas(w, data, ev) XWidget w; Xcaddr_t data; XXEvent *ev; X{ X static rastered = 0; X X if (!isMapped) X return; X X /* X Put the pixmap on the screen at the appropriate X ViewLeft, ViewTop; X */ X if (ev && ev->xexpose.count == 0) { X XEvent event; X /* Skip all excess redraws */ X while (XCheckTypedEvent(dpy, Expose, &event)) X ; X } X X if( !rastered && ev) X { X rastered = 1; X Rerasterize(BaseFrame, (XEvent *) NULL, (String *) NULL, X (Cardinal *) NULL); X } X SetScrollBar(); X X#ifdef WINDOWDEBUG X printf("repaint - ViewLeft = %d, Top = %d, Width = %d, Height = %d\n", X ViewLeft, ViewTop, ViewWidth, ViewHeight); X#endif X XCopyArea(dpy, PagePixRect, DrawingCanvas, gc, ViewLeft, ViewTop, X (unsigned int) ViewWidth, (unsigned int) ViewHeight, 0, 0); X XFlush(dpy); X} X X/*ARGSUSED*/ Xstatic void XRecordMapStatus(w, data, ev) XWidget w; Xcaddr_t data; XXEvent *ev; X{ X if (ev->type == MapNotify) { X#ifdef WINDOWDEBUG X printf("window mapped\n"); X#endif X isMapped = TRUE; X RepaintCanvas(CanvasWidget, (caddr_t) NULL, (XEvent *) NULL); X } else if (ev->type = ConfigureNotify) { X XConfigureEvent *cev = (XConfigureEvent *) ev; X#ifdef WINDOWDEBUG X printf("window resized\n"); X#endif X if (cev->width != ViewWidth || cev->height != ViewHeight) { X ViewWidth = cev->width; X ViewHeight = cev->height; X ResizeScrollBar(); X } X } X} X X X X/*ARGSUSED*/ Xstatic void XStartPan(w, event, params, nparams) XWidget w; XString *params; XCardinal *nparams; XXMotionEvent *event; X{ X OriginalX = event->x; X OriginalY = event->y; X#ifdef DEBUG X printf("starting pan from %d, %d\n", OriginalX, OriginalY); X#endif X XDefineCursor(dpy, DrawingCanvas, HandCursor); X PageRequest = 0; X} X X/*ARGSUSED*/ Xstatic void XEndPan(w, event, params, nparams) XWidget w; XString *params; XCardinal *nparams; XXMotionEvent *event; X{ X if (OriginalX != -1 && OriginalY != -1){ X OriginalX = OriginalY = -1; X#ifdef DEBUG X printf("ending pan\n"); X#endif X XDefineCursor(dpy, DrawingCanvas, WorkingCursor); X } X PageRequest = 0; X} X X/*ARGSUSED*/ Xstatic void XPagePan(w, event, params, nparams) XWidget w; XString *params; XCardinal *nparams; XXMotionEvent *event; X{ X ViewLeft -= event->x - OriginalX; X if (ViewLeft + ViewWidth > PAGE_PIXEL_WIDTH) X ViewLeft = PAGE_PIXEL_WIDTH - ViewWidth; X if (ViewLeft < 0) X ViewLeft = 0; X X ViewTop -= event->y - OriginalY; X if (ViewTop + ViewHeight > PAGE_PIXEL_HEIGHT) X ViewTop = PAGE_PIXEL_HEIGHT - ViewHeight; X if (ViewTop < 0) X ViewTop = 0; X#ifdef DEBUG X printf("panning - ViewLeft, Top = %d, %d\n", ViewLeft, ViewTop); X#endif X if ((OriginalX != event->x) || (OriginalY != event->y)){ X XCopyArea(dpy, PagePixRect, DrawingCanvas, gc, ViewLeft, X ViewTop, (unsigned int) ViewWidth, (unsigned int) ViewHeight, X 0, 0); X#ifdef DEBUG X printf("panned\n"); X#endif X OriginalX = event->x; X OriginalY = event->y; X SetScrollBar(); X } X PageRequest = 0; X} X X X/*ARGSUSED*/ Xstatic void XNumber(w, event, params, nparams) XWidget w; XString *params; XCardinal *nparams; XXEvent *event; X{ X char ch; X X XLookupString(&event->xkey, &ch, 1, (KeySym *) NULL, X (XComposeStatus *) NULL); X PageRequest = PageRequest*10 + ch - '0'; X#ifdef WINDOWDEBUG X printf("ch = %c, arg = %d\n", ch, PageRequest); X#endif X X} X X/*ARGSUSED*/ Xstatic void XEscapeNumber(w, event, params, nparams) XWidget w; XString *params; XCardinal *nparams; XXEvent *event; X{ X PageRequest = 0; X#ifdef WINDOWDEBUG X printf("arg = 0\n"); X#endif X} X X X/*ARGSUSED*/ Xstatic void XGoToPage(w, event, params, nparams) XWidget w; XString *params; XCardinal *nparams; XXEvent *event; X{ X#ifdef WINDOWDEBUG X printf("goto page %d\n", PageRequest); X#endif X ViewTop = 0; X CurrentPage = ShowPage(PageRequest); X PageRequest = 0; X} X X/*ARGSUSED*/ Xstatic void XBackPage(w, event, params, nparams) XWidget w; XString *params; XCardinal *nparams; XXEvent *event; X{ X int curpage = CurrentPage; X X if (!PageRequest) X PageRequest++; X CurrentPage -= PageRequest; X if (CurrentPage <= 0) X CurrentPage = 1; X if (CurrentPage != curpage) { X ViewTop = 0; X CurrentPage = ShowPage(CurrentPage); X } X PageRequest = 0; X} X X/*ARGSUSED*/ Xstatic void XForwardPage(w, event, params, nparams) XWidget w; XString *params; XCardinal *nparams; XXEvent *event; X{ X if (!PageRequest) X PageRequest++; X CurrentPage += PageRequest; X ViewTop = 0; X CurrentPage = ShowPage(CurrentPage); X PageRequest = 0; X} X X/*ARGSUSED*/ Xstatic void XPrevSection(w, event, params, nparams) XWidget w; XString *params; XCardinal *nparams; XXEvent *event; X{ X int curpage = CurrentPage; X X /* X * Back up to the previous section to be viewed. If X * the screen is large enough to show the whole X * page, then back up to the previous page. Else X * back up to the previous half of the page. Only X * change ViewTop - leave ViewLeft alone as X * part of the philosophy - in general, the X * width of the page fits nicely on the screen X */ X do { X ViewTop -= ViewHeight; X if (ViewTop <= -ViewHeight) { X if (CurrentPage > 1) { X ViewTop = PAGE_PIXEL_HEIGHT - ViewHeight; X CurrentPage--; X } else { X CurrentPage = 1; X ViewTop = 0; X break; X } X } else if (ViewTop < 0) { X ViewTop = 0; X } X } while (--PageRequest > 0); X if (curpage != CurrentPage) X CurrentPage = ShowPage(CurrentPage); X else X RefreshPage(); X PageRequest = 0; X} X X X/*ARGSUSED*/ Xstatic void XNextSection(w, event, params, nparams) XWidget w; XString *params; XCardinal *nparams; XXEvent *event; X{ X int curpage = CurrentPage; X X /* X * Advance to the next section to be viewed. If X * the screen is large enough to show the whole X * page, then advance to the next page. Else X * advance to the next half of the page. Only X * change ViewTop - leave ViewLeft alone as X * part of the philosophy - in general, the X * width of the page fits nicely on the screen X */ X do { X ViewTop += ViewHeight; X if (ViewTop >= PAGE_PIXEL_HEIGHT) { X ViewTop = 0; X CurrentPage++; X } else if (ViewTop > PAGE_PIXEL_HEIGHT - ViewHeight) { X ViewTop = PAGE_PIXEL_HEIGHT - ViewHeight; X } X } while (--PageRequest > 0); X if (curpage != CurrentPage) X CurrentPage = ShowPage(CurrentPage); X else X RefreshPage(); X PageRequest = 0; X} X Xstatic void MousePrintPage() X{ X PrintPage(CurrentPage, Printer); X} X Xstatic void MousePrintDocument() X{ X PrintDocument(ActualFileName, Printer); X X} X X X/*ARGSUSED*/ Xstatic void XQuit(w, event, params, nparams) XWidget w; XString *params; XCardinal *nparams; XXEvent *event; X{ X if (*TempFileName) X (void) unlink(TempFileName); X exit(0); X} X X X/* These are the scrolling and jumping (thumbing no longer supported) X callbacks */ X/*ARGSUSED*/ Xstatic void XScrolled(w, closure, call_data) XWidget w; Xcaddr_t closure; Xint call_data; X{ X#ifdef WINDOWDEBUG X printf( "scrolled by %d pixels.\n", call_data ); X#endif X if (w == VertScroll) { X ViewTop += call_data * PAGE_PIXEL_HEIGHT / ViewHeight; X if (ViewTop < 0) X ViewTop = 0; X else if (ViewTop > PAGE_PIXEL_HEIGHT - ViewHeight) X ViewTop = PAGE_PIXEL_HEIGHT - ViewHeight; X } else if (w == HorizScroll) { X ViewLeft += call_data * PAGE_PIXEL_WIDTH / ViewWidth; X if (ViewLeft < 0) X ViewLeft = 0; X else if (ViewLeft > PAGE_PIXEL_WIDTH - ViewWidth) X ViewLeft = PAGE_PIXEL_WIDTH - ViewWidth; X } X X XCopyArea(dpy, PagePixRect, DrawingCanvas, gc, ViewLeft, ViewTop, X (unsigned int) ViewWidth, (unsigned int) ViewHeight, 0, 0); X SetScrollBar(); X} X X X/*ARGSUSED*/ Xstatic void XJumped(w, closure, percent) XWidget w; Xcaddr_t closure; Xcaddr_t percent; X{ X float top = *((float *) percent); X#ifdef WINDOWDEBUG X printf( "thumbed to %f%%\n", top ); X#endif X if (w == VertScroll) { X ViewTop = top * PAGE_PIXEL_HEIGHT; X if (ViewTop > PAGE_PIXEL_HEIGHT - ViewHeight) X ViewTop = PAGE_PIXEL_HEIGHT - ViewHeight; X } else if (w == HorizScroll) { X ViewLeft = top * PAGE_PIXEL_WIDTH; X if (ViewLeft > PAGE_PIXEL_WIDTH - ViewWidth) X ViewLeft = PAGE_PIXEL_WIDTH - ViewWidth; X } X XCopyArea(dpy, PagePixRect, DrawingCanvas, gc, ViewLeft, ViewTop, X (unsigned int) ViewWidth, (unsigned int) ViewHeight, 0, 0); X SetScrollBar(); X} X X XSetScrollBar() X{ X if (!Scrollbars) X return; X XtScrollBarSetThumb(VertScroll, X (float) ((float) ViewTop / (float) PAGE_PIXEL_HEIGHT), X (float) ((float) ViewHeight / (float) PAGE_PIXEL_HEIGHT)); X XtScrollBarSetThumb(HorizScroll, X (float) ((float) ViewLeft / (float) PAGE_PIXEL_WIDTH), X (float) ((float) ViewWidth / (float) PAGE_PIXEL_WIDTH)); X} X XResizeScrollBar() X{ X Dimension tmp; X if (!Scrollbars) X return; X tmp = (Dimension) ViewHeight; X XtSetArg(scroll_args[0], XtNlength, tmp); X XtSetValues(VertScroll, scroll_args, 1); X tmp = (Dimension) ViewWidth; X XtSetArg(scroll_args[0], XtNlength, tmp); X XtSetValues(HorizScroll, scroll_args, 1); X SetScrollBar(); X} X X XSearchForward(){ X int i; X X i = SearchFile(SearchItem,CurrentPage,1); X if (i){ X CurrentPage = i; X ShowPage(i); X } else { X SetTitleBar("Displaying",CurrentPage); X } X return(i); X} X XSearchBackward(){ X int i; X X i = SearchFile(SearchItem,CurrentPage,-1); X if (i){ X CurrentPage = i; X ShowPage(i); X } else { X SetTitleBar("Displaying",CurrentPage); X } X return(i); X} X X X/*ARGSUSED*/ Xstatic void XRerasterize(w, event, params, nparams) XWidget w; XString *params; XCardinal *nparams; XXEvent *event; X{ X#ifndef STANDALONE X static FILE *FilePointer = 0; X static FILE *PipePointer = 0; X static int ProcessPid = 0; X extern char *mktemp(); X X if (FilePointer && FilePointer != stdin){ X (void) fclose(FilePointer); X } X if (PipePointer){ X (void) fclose(PipePointer); X (void) kill(ProcessPid, SIGKILL); X } X ProcessPid = 0; X PipePointer = FilePointer = 0; X X if (!CommandMode && FileName != NULL && FileName[0] != '\0'){ X FilePointer = fopen(FileName,"r"); X if (!FilePointer){ X warning("Can't open %s for reading input.\n", X FileName); X } else { X ActualFileName = FileName; X InitializeFile(FilePointer, FilePointer); X } X } else { X static char FileName[BUFSIZ], *p; X int PipeFds[2]; X X if (CommandMode) { X p = CommandString; X if (!p){ X while (isspace(*p)) X p++; X } X if (!p || !*p){ X warning("Rasterize called without a command.\nUse the menu to set a command."); X return; X } X } X X (void) pipe(PipeFds); /* Get two halves of pipe */ X X ProcessPid = fork(); /* And then Fork */ X if (ProcessPid == -1) { X warning("Couldn't fork. Help\n"); X return; X } X if (!ProcessPid){ /* First the Child */ X int y; X X close(1); X dup2(PipeFds[1], 1); X for( y = 3; y < getdtablesize(); y++) X close(y); X X if (!CommandMode) { X execl("/bin/cat", (char *) 0); X fatal("Someone stole /bin/cat - help!\n"); X } else { X system(p); X exit(0); X } X /*NOTREACHED*/ X } X X PipePointer = fdopen(PipeFds[0], "r"); X (void) close(PipeFds[1]); X X if (*TempFileName) { X (void) strcpy(FileName, TempFileName); X } else { X (void) strcpy(FileName,"/tmp/suntroff.XXXXXX"); X (void) mktemp(FileName); X (void) strcpy(TempFileName, FileName); X } X X FilePointer = fdopen(open(FileName, X O_RDWR|O_CREAT|O_TRUNC,0644), "r+"); X X if (!FilePointer){ X (void) fprintf(stderr, X "Can't open buffer file for the command:\n"); X (void) fprintf(stderr,"\t%s\n", CommandString); X exit(1); X } X ActualFileName = FileName; X InitializeFile(PipePointer, FilePointer); X } X X ShowPage(CurrentPage); X#endif STANDALONE X} X X/* X * For those without a window manager that puts titlebars, maybe we X * should put a Label widget X */ XSetTitleBar(status,PageNumber) Xchar *status; Xint PageNumber; X{ X extern char *DefaultTitle; X char Buffer[BUFSIZ]; X char TempStatus[BUFSIZ]; X int FrameWidth, Width, i; X X /* No way of getting this from the window manager, is there? */ X FrameWidth = 60; X X if (PageNumber >= 0) X (void) sprintf(TempStatus,"%s Page %d",status,PageNumber); X else X (void) sprintf(TempStatus, "%s", status); X X strncpy(Buffer,DefaultTitle,BUFSIZ); X i = strlen(DefaultTitle); X X Width = strlen(TempStatus); X X while (i + Width < FrameWidth){ X Buffer[i++] = ' '; X } X if (FrameWidth - i > 0){ X strncpy(&Buffer[i],TempStatus,FrameWidth-i); X } X XStoreName(dpy, OuterFrame, Buffer); X#if 0 X if (PageNumber >= 0){ X (void) sprintf(PageNumberValue,"%d",PageNumber); X panel_set_value(PageItem,PageNumberValue); X } X#endif X if (STREQ(status, "Displaying")) X XDefineCursor(dpy, DrawingCanvas, WorkingCursor); X else X XDefineCursor(dpy, DrawingCanvas, WaitCursor); X XFlush(dpy); X} X Xstatic char *SavedTitleBar = NULL; X XSaveTitleBar(){ X XFetchName(dpy, OuterFrame, &SavedTitleBar); X XFlush(dpy); X} X XRestoreTitleBar(){ X if (SavedTitleBar) { X XStoreName(dpy, OuterFrame, SavedTitleBar); X XFlush(dpy); X XDefineCursor(dpy, DrawingCanvas, WorkingCursor); X } X} X X#include <varargs.h> X X/*VARARGS0*/ Xfatal(va_alist) Xva_dcl X{ X va_list args; X char *fmt; X X va_start(args); X fprintf(stderr,"Fatal Error: "); X fmt = va_arg(args, char *); X (void) vfprintf(stderr,fmt,args); X va_end(args); X if (*TempFileName) X (void) unlink(TempFileName); X exit(1); X} X X/*VARARGS0*/ Xwarning(va_alist) Xva_dcl X{ X va_list args; X char *fmt; X char Message[BUFSIZ]; X X va_start(args); X fmt = va_arg(args, char *); X (void) vsprintf(Message,fmt,args); X va_end(args); X message(Message); X} X X X/* X * We move the menu to the current mouse location before popping it up X * with MenuPopup. Pity MenuPopup doesn't do this! X */ X/*ARGSUSED*/ Xstatic void XSetMenuPos (w, clientdata, calldata) XWidget w; Xcaddr_t clientdata; Xcaddr_t calldata; X{ X Window root, child; X int rootx, rooty, winx, winy; X unsigned int mask; X X XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, X &rootx, &rooty, &winx, &winy, &mask); X /* X * The -OFFSET,-OFFSET displacement just makes sure mouse is in X * the menu X */ X#define OFFSET 10 X XtMoveWidget(PopupShell, (Position) (rootx - OFFSET), X (Position) rooty - OFFSET); X} X X X/*ARGSUSED*/ Xstatic void XMenuSelection (widget, closure, call_data) XWidget widget; Xcaddr_t closure, call_data; X{ X char *get_input(); X char *tmpstr; X char statusbuf[128]; X X XtPopdown(PopupShell); X XFlush(dpy); X switch ((int) closure) X { X case 1: X Rerasterize(BaseFrame, (XEvent *) NULL, X (String *) NULL, (Cardinal *) NULL); X break; X case 2: X ForwardPage(BaseFrame, (XEvent *) NULL, X (String *) NULL, (Cardinal *) NULL); X break; X case 3: X BackPage(BaseFrame, (XEvent *) NULL, X (String *) NULL, (Cardinal *) NULL); X break; X case 4: X NextSection(BaseFrame, (XEvent *) NULL, X (String *) NULL, (Cardinal *) NULL); X break; X case 5: X PrevSection(BaseFrame, (XEvent *) NULL, X (String *) NULL, (Cardinal *) NULL); X break; X case 6: X if (CommandMode) { X (void) sprintf(statusbuf, "Command is \"%s\"", X CommandString); X } else { X (void) sprintf(statusbuf, "File is \"%s\"", X FileName); X } X message(statusbuf); X break; X case 7: X tmpstr = get_input(": search-forward ? ", X SearchItem, FALSE); X if (tmpstr) { X if (SearchItem) X free(SearchItem); X SearchItem = tmpstr; X if (SearchForward()) { X message("Found!"); X } else { X message("Not found!"); X } X } X break; X case 8: X tmpstr = get_input(": search-reverse ? ", X SearchItem, FALSE); X if (tmpstr) { X if (SearchItem) X free(SearchItem); X SearchItem = tmpstr; X if (SearchBackward()) { X message("Found!"); X } else { X message("Not found!"); X } X } X break; X case 9: X /* Change File */ X tmpstr = get_input(": file-name ? ", FileName, TRUE); X if (tmpstr) { X CommandMode = 0; X strcpy(FileName, tmpstr); X free(tmpstr); X Rerasterize(BaseFrame, (XEvent *) NULL, X (String *) NULL, (Cardinal *) NULL); X } X break; X case 10: X /* Change Command */ X tmpstr = get_input(": formatting-command ? ", X CommandString, FALSE); X if (tmpstr) { X CommandMode = 1; X strcpy(CommandString, tmpstr); X free(tmpstr); X Rerasterize(BaseFrame, (XEvent *) NULL, X (String *) NULL, (Cardinal *) NULL); X } X break; X case 11: X /* Go to page */ X tmpstr = get_input(": go-to-page ? ", (char *) NULL, X FALSE); X if (tmpstr) { X PageRequest = atoi(tmpstr); X GoToPage(BaseFrame, (XEvent *) NULL, X (String *) NULL, (Cardinal *) NULL); X } X break; X case 12: X /* Print page */ X MousePrintPage(); X break; X case 13: X /* Print document */ X MousePrintDocument(); X break; X case 14: X /* Set Printer name */ X tmpstr = get_input(": set-printer-name ? ", Printer, X FALSE); X if (tmpstr) X Printer = tmpstr; X break; X case 0: X Quit(BaseFrame, (XEvent *) NULL, X (String *) NULL, (Cardinal *) NULL); X break; X default: X message("Programmer error: unknown menu selection"); X break; X } X} X X Xstatic char *input; Xstatic int inputdone = TRUE; X X/* X * This routine focuses all input on the InputWindow, and starts up a X * loop which forms a secondary dispatcher, ignoring all events except X * ExposeWindow events on windows other than the InputWindow. This X * effectively forces the user to use the InputWindow. The loop X * terminates when input is completed, either by inputting a string, in X * which case finished_input will be invoked, or by aborting. Both set X * the completion flag and the loop quits, focussing input back to the X * previous holder. No harm is done to this application if focus is not X * given to the minibuffer, or removed from it - it's just more X * convenient for the user who doesn't have to move a mouse around too X * much. The routine returns the input string, or a NULL if the input X * was aborted. X */ Xchar * Xget_input(prompt, default_string, complete) Xchar *prompt, *default_string; X{ X XEvent ev; X X XDefineCursor(dpy, DrawingCanvas, TextCursor); X MinibufGetInput(InputWidget, prompt, default_string, complete); X XtAddGrab(InputWidget, False, False); X XtSetKeyboardFocus(CanvasWidget, InputWidget); X inputdone = FALSE; X while (!inputdone) { X XtNextEvent(&ev); X (void) XtDispatchEvent(&ev); X } X XtSetKeyboardFocus(CanvasWidget, (Widget) None); X XtRemoveGrab(InputWidget); X XDefineCursor(dpy, DrawingCanvas, WorkingCursor); X return(input); X} X X X/* X * Callback, invoked when user hits RETURN in the InputWidget (or whatever X * the user has bound 'newline' to) in which case inp_string points to X * an alloc'ed string. If the user aborts input (^G, ^C) then X * inp_string is NULL X */ X/*ARGSUSED*/ Xstatic void Xfinished_input(w, tag, inp_string) XWindow w; Xcaddr_t tag; Xchar *inp_string; X{ X input = inp_string; X inputdone = TRUE; X} X X X/* X * Asks to confirm something - If they reply "y", returns YES, if they X * reply "n", returns NO, if they abort, returns ABORT. You are given X * IMPATIENCE tries to answer X */ Xconfirm(query, default_answer) Xchar *default_answer; Xchar *query; X{ X char *answer; X char c; X char *mesg = "Answer yes or no, please (y/n)"; X int count = 0; X#define IMPATIENCE 5 X X do { X if ((answer = get_input(query, default_answer, FALSE)) == NULL) X return (ABORT); X c = (isupper(answer[0])) ? tolower(answer[0]) : answer[0]; X if (c == 'y') X return(YES); X else if (c == 'n') X return(NO); X message(mesg); X /* Let's get really explicit next time */ X mesg = "Type 'y' and RETURN if you want to answer YES, 'n' for NO, CTRL-G to abort"; X } while (count++ < IMPATIENCE); X message("Forget it - Aborting"); X return(ABORT); X} X X X/* X * Message is printed on the communication line if the windows are X * mapped, otherwise fprintf'ed to stderr X */ Xmessage(s) Xchar *s; X{ X if (InputWidget != 0) X MinibufDisplayMessage(InputWidget, s, TRUE); X else X fprintf(stderr, "%s\n", s); X} X X/*ARGSUSED*/ XSetPrinter(s) Xchar *s; X{ X} X X#ifdef STANDALONE XShowPage(){ X printf("Show Page called.\n"); X} X Xchar *DefaultTitle = "Standalone Window Code"; X XSearchFile(){ X printf("Search file called.\n"); X} X XRefreshPage(){ X} X X#endif STANDALONE X#endif SUNTOOLS X/* Don't put anything after this line */ END_OF_FILE if test 35916 -ne `wc -c <'xtroff/xwindows.c'`; then echo shar: \"'xtroff/xwindows.c'\" unpacked with wrong size! fi # end of 'xtroff/xwindows.c' fi echo shar: End of archive 18 \(of 18\). cp /dev/null ark18isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 18 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0