This is xdriver.c in view mode; [Download] [Up]
/* ** Astrolog (Version 4.10) File: xdriver.c ** ** IMPORTANT NOTICE: the graphics database and chart display routines ** used in this program are Copyright (C) 1991-1994 by Walter D. Pullen ** (cruiser1@stein.u.washington.edu). Permission is granted to freely ** use and distribute these routines provided one doesn't sell, ** restrict, or profit from them in any way. Modification is allowed ** provided these notices remain with any altered or edited versions of ** the program. ** ** The main planetary calculation routines used in this program have ** been Copyrighted and the core of this program is basically a ** conversion to C of the routines created by James Neely as listed in ** Michael Erlewine's 'Manual of Computer Programming for Astrologers', ** available from Matrix Software. The copyright gives us permission to ** use the routines for personal use but not to sell them or profit from ** them in any way. ** ** The PostScript code within the core graphics routines are programmed ** and Copyright (C) 1992-1993 by Brian D. Willoughby ** (brianw@sounds.wa.com). Conditions are identical to those above. ** ** The extended accurate ephemeris databases and formulas are from the ** calculation routines in the program "Placalc" and are programmed and ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl ** (alois@azur.ch). The use of that source code is subject to ** regulations made by Astrodienst Zurich, and the code is not in the ** public domain. This copyright notice must not be changed or removed ** by any user of this program. ** ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991. ** X Window graphics initially programmed 10/23-29/1991. ** PostScript graphics initially programmed 11/29-30/1992. ** Last code change made 3/19/1994. */ #include "astrolog.h" #ifdef GRAPH #ifdef X11 /* Size of the Astrolog X11 icon. These values are defined in xdata.c too. */ #define icon_width 63 #define icon_height 32 #endif #ifdef MSG /* PC specific global variables. */ int hiresmode = DEFHIRESMODE; /* 'High-resolution' graphics mode. */ int loresmode = DEFLORESMODE; /* 'Flicker-free' graphics mode. */ int xscreen = -1000; /* Current graphics mode. */ struct videoconfig config; /* State of current graphics mode. */ #endif /* ****************************************************************************** ** Interactive Screen Graphics Routines. ****************************************************************************** */ #ifdef X11 /* Allocate a color from the present colormap. Given a string like "red" or */ /* "blue" allocate this color and return a value specifying it. */ colrgb XMakeColor(name) char *name; { XColor col; XParseColor(disp, cmap, name, &col); XAllocColor(disp, cmap, &col); return col.pixel; } #endif /* Set up all the colors used by the program, i.e. the foreground and */ /* background colors, and all the colors in the object arrays, based on */ /* whether or not we are in monochrome and/or reverse video mode. */ void XColorInit() { int i; #ifdef X11 if (!xfile) { cmap = XDefaultColormap(disp, screen); for (i = 0; i < 16; i++) rgbind[i] = XMakeColor(rgbname[i]); } #endif on = mainansi[!xreverse]; off = mainansi[xreverse]; hilite = xcolor ? mainansi[2+xreverse] : on; gray = xcolor ? mainansi[3-xreverse] : on; for (i = 0; i <= 6; i++) maincolor[i] = xcolor ? mainansi[i] : on; for (i = 0; i <= 7; i++) rainbowcolor[i] = xcolor ? rainbowansi[i] : on; for (i = 0; i < 4; i++) elemcolor[i] = xcolor ? elemansi[i] : on; for (i = 0; i <= ASPECTS; i++) aspectcolor[i] = xcolor ? aspectansi[i] : on; for (i = 0; i <= total; i++) objectcolor[i] = xcolor ? objectansi[i] : on; #ifdef X11 if (!xfile) { XSetBackground(disp, gc, rgbind[off]); /* Initialize X window colors. */ XSetForeground(disp, pmgc, rgbind[off]); } #endif } #ifdef ISG /* This routine opens up and initializes a window and prepares it to be */ /* drawn upon, and gets various information about the display, too. */ void XBegin() { #ifdef X11 disp = XOpenDisplay(dispname); if (!disp) { PrintError("Can't open display."); Terminate(_FATAL); } screen = DefaultScreen(disp); bg = BlackPixel(disp, screen); fg = WhitePixel(disp, screen); hint.x = offsetx; hint.y = offsety; hint.width = chartx; hint.height = charty; hint.min_width = BITMAPX1; hint.min_height = BITMAPY1; hint.max_width = BITMAPX; hint.max_height = BITMAPY; hint.flags = PPosition | PSize | PMaxSize | PMinSize; #if FALSE wmhint = XGetWMHints(disp, window); wmhint->input = True; XSetWMHints(disp, window, wmhint); #endif depth = DefaultDepth(disp, screen); if (depth < 5) { xmono = TRUE; /* Is this a monochrome monitor? */ xcolor = FALSE; } root = RootWindow(disp, screen); if (xroot) window = root; /* If -XB in effect, we'll use the root window. */ else window = XCreateSimpleWindow(disp, DefaultRootWindow(disp), hint.x, hint.y, hint.width, hint.height, 5, fg, bg); pixmap = XCreatePixmap(disp, window, chartx, charty, depth); icon = XCreateBitmapFromData(disp, DefaultRootWindow(disp), icon_bits, icon_width, icon_height); if (!xroot) XSetStandardProperties(disp, window, appname, appname, icon, (char PTR PTR)xkey, 0, &hint); /* We have two graphics workareas. One is what the user currently sees in */ /* the window, and the other is what we are currently drawing on. When */ /* done, we can quickly copy this to the viewport for a smooth look. */ gc = XCreateGC(disp, window, 0, 0); XSetGraphicsExposures(disp, gc, 0); pmgc = XCreateGC(disp, window, 0, 0); XColorInit(); /* Go set up colors. */ if (!xroot) XSelectInput(disp, window, KeyPressMask | StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask); XMapRaised(disp, window); XSync(disp, 0); XFillRectangle(disp, pixmap, pmgc, 0, 0, chartx, charty); #else /* MSG */ if (!IsValidResmode(xscreen)) /* Initialize graphics mode to hi-res. */ xscreen = hiresmode; _setvideomode(xscreen); if (_grstatus()) { PrintError("Can't enter graphics mode."); Terminate(_FATAL); } _getvideoconfig((struct videoconfig far *) &config); if (config.numcolors < 16) { xmono = TRUE; xcolor = FALSE; } _remapallpalette((long FAR *) rgb); _setactivepage(0); _setvisualpage(0); XColorInit(); #ifdef MOUSE if (MouseInit() > 0) SetPtrVis(SHOW); #endif textrows = abs(textrows); /* Make sure we reset textrows upon restart. */ #endif /* MSG */ } /* Add a certain amount of time to the current hour/day/month/year quantity */ /* defining the present chart. This is used by the chart animation feature. */ /* We can add or subtract anywhere from 1 to 9 seconds, minutes, hours, */ /* days, months, years, decades, centuries, or millenia in any one call. */ /* This is mainly just addition to the appropriate quantity, but we have */ /* to check for overflows, e.g. Dec 30 + 3 days = Jan 2 of Current year + 1 */ void AddTime(mode, toadd) int mode, toadd; { int d; real h, m; h = floor(TT); m = FRACT(TT)*100.0; if (mode == 1) m += 1.0/60.0*(real)toadd; /* Add seconds. */ else if (mode == 2) m += (real)toadd; /* add minutes. */ /* Add hours, either naturally or if minute value overflowed. */ if (m < 0.0 || m >= 60.0 || mode == 3) { if (m >= 60.0) { m -= 60.0; toadd = SGN(toadd); } else if (m < 0.0) { m += 60.0; toadd = SGN(toadd); } h += (real)toadd; } /* Add days, either naturally or if hour value overflowed. */ if (h >= 24.0 || h < 0.0 || mode == 4) { if (h >= 24.0) { h -= 24.0; toadd = SGN(toadd); } else if (h < 0.0) { h += 24.0; toadd = SGN(toadd); } DD = AddDay(MM, DD, YY, toadd); } /* Add months, either naturally or if day value overflowed. */ if (DD > (d = DayInMonth(MM, YY)) || DD < 1 || mode == 5) { if (DD > d) { DD -= d; toadd = SGN(toadd); } else if (DD < 1) { DD += DayInMonth(Mod12(MM - 1), YY); toadd = SGN(toadd); } MM += toadd; } /* Add years, either naturally or if month value overflowed. */ if (MM > 12 || MM < 1 || mode == 6) { if (MM > 12) { MM -= 12; toadd = SGN(toadd); } else if (MM < 1) { MM += 12; toadd = SGN(toadd); } YY += toadd; } if (mode == 7) YY += 10 * toadd; /* Add decades. */ else if (mode == 8) YY += 100 * toadd; /* Add centuries. */ else if (mode == 9) YY += 1000 * toadd; /* Add millenia. */ TT = h+m/100.0; /* Recalibrate hour time. */ } /* Animate the current chart based on the given values indicating how much */ /* to update by. We update and recast the current chart info appropriately. */ void Animate(mode, toadd) int mode, toadd; { if (modex == MODEW || modex == MODEG || modex == MODEP) { degree += toadd; if (degree >= DEGD) /* For animating globe display, add */ degree -= DEGD; /* in appropriate degree value. */ else if (degree < 0) degree += DEGD; } else { if (mode == 10) { #ifdef TIME /* For the continuous chart update to present moment */ /* animation mode, go get whatever time it is now. */ InputData("now"); #else SetCore(Mon, Day, Yea, Tim, Zon, Lon, Lat); AddTime(1, toadd); #endif } else { /* Otherwise add on appropriate time vector to chart info. */ SetCore(Mon, Day, Yea, Tim, Zon, Lon, Lat); AddTime(mode, toadd); } SetMain(MM, DD, YY, TT, ZZ, OO, AA); if (relation) CastRelation(FALSE); else CastChart(TRUE); } } /* Print a list of every key that one can press in an X window to do a */ /* certain function, and a description of what it does. This list gets */ /* displayed whenever one presses the 'H' or '?' key in the window. */ void XDisplayKeys() { char string[STRING]; sprintf(string, "\n%s window keypress options (version %s):", appname, VERSION); Prints(string); Prints(" Press 'H' or '?' to display this list of key options."); Prints(" Press 'p' to toggle pause status on or off."); Prints(" Press 'x' to toggle fg/bg colors on screen."); Prints(" Press 'm' to toggle color/monochrome display on screen."); Prints(" Press 'i' to toggle status of the minor chart modification."); Prints(" Press 'T' to toggle header info on current chart on screen."); Prints(" Press 'b' to toggle drawing of a border around the chart."); Prints(" Press 'l' to toggle labeling of object points in chart."); Prints(" Press 'v' to display current chart positions on text screen."); Prints(" Press 'R', 'C', 'u', 'U' to toggle restriction status of minor"); Prints(" objects, minor house cusps, uranian planets, and stars."); Prints(" Press 'c' to toggle relationship comparison chart mode."); Prints(" Press 's', 'h', 'f', 'F' to toggle status of sidereal zodiac,"); Prints(" heliocentric charts, domal charts, and decan charts."); Prints(" Press 'O' and 'o' to recall/store a previous chart from memory."); #ifdef X11 Prints(" Press 'B' to dump current window contents to root background."); #else Prints(" Press 'B' to resize chart display to full size of screen."); #endif Prints(" Press 'Q' to resize chart display to a square."); Prints(" Press '<' and '>' to decrease/increase the scale size of the"); Prints(" glyphs and the size of world map."); Prints(" Press '[' and ']' to decrease/increase tilt in globe display."); Prints(" Press '+' and '-' to add/subtract a day from current chart."); #ifdef TIME Prints(" Press 'n' to set chart information to current time now."); #endif Prints(" Press 'N' to toggle animation status on or off. Charts will"); Prints(" be updated to current status and globe will rotate."); Prints(" Press '!'-'(' to begin updating current chart by adding times."); Prints(" !: seconds, @: minutes, #: hours, $: days, %: months,"); Prints(" ^: years, &: years*10, *: years*100, (: years*1000."); Prints(" Press 'r' to reverse direction of time-lapse or animation."); Prints(" Press '1'-'9' to set rate of animation to 'n' degrees, etc."); #ifdef MSG Prints(" Press '1'-'9' to determine section of chart to show if clipped."); #endif Prints( " Press 'V','L','A','Z','S','E','W','G','P' to switch to normal (_v),"); Prints( " astro-graph (_L), grid (_g), local (_Z), space (_S), ephemeris"); Prints(" (_E), world map (_XW), globe (_XG), and polar (_XP) modes."); Prints(" Press '0' to toggle between _Z,_Z0 & _XW,_XW0 & _E,_Ey modes."); Prints(" Press 'space' to force redraw of current graphics display."); #ifdef MSG Prints(" Press 'tab' to toggle between graphics resolutions."); #endif Prints(" Press 'q' to terminate the window and program."); #ifdef MOUSE printl(); #ifdef X11 Prints(" Left mouse button: Draw line strokes on chart in window."); Prints(" Middle mouse button: Print coordinates of pointer on world map."); Prints(" Right mouse button: Terminate the window and program."); #endif #ifdef MSG Prints(" Left mouse button: Draw line strokes on chart in screen."); Prints(" Right mouse button: Set coordinates to pointer on world map."); #endif #endif /* MOUSE */ } /* Given two chart size values, adjust them such that the chart will look */ /* "square". We round the higher value down and check certain conditions. */ void XSquare(x, y, force) int *x, *y, force; { if (!force && !ISSQUARE) /* Unless we want to force a square, realize */ return; /* that some chart look better rectangular. */ if (*x > *y) *x = *y; else *y = *x; #ifdef MSG if (ISEGA(xscreen)) /* Scale horizontal size if we're in a PC */ *x = EGATOVGA(*x); /* graphics mode without "square" pixels. */ else if (ISCGA(xscreen)) *x = CGATOVGA(*x); #endif if (ISSIDEBAR) /* Take into account chart's sidebar, if any. */ *x += SIDET; } /* This routine gets called after an X window is brought up and displayed */ /* on the screen. It loops, processing key presses, mouse clicks, etc, that */ /* the window receives, until the user specifies they want to exit program. */ void XSpin() { #ifdef X11 XEvent event; int xresize = FALSE, xredraw = TRUE; #else #ifdef MOUSE EVENT event; #endif int xresize = TRUE, xredraw = FALSE; #endif int xbreak = FALSE, xpause = FALSE, xcast = FALSE, xcorner = 7, mousex = -1, mousey = -1, buttonx = -1, buttony = -1, dir = 1, length, i; colpal coldrw = hilite; xnow = -xnow; while (!xbreak) { /* Some chart windows, like the world maps and aspect grids, should */ /* always be a certian size, so correct if a resize was attempted. */ if (modex == MODEL || modex == MODEW) { length = DEGD*SCALE+2; if (chartx != length) { chartx = length; xresize = TRUE; } length = (90*2+1)*SCALE+2; if (charty != length) { charty = length; xresize = TRUE; } } else if (modex == MODEg) { if (chartx != (length = (gridobjects + (relation <= DASHr0))*CELLSIZE*SCALE+1)) { chartx = length; xresize = TRUE; } if (charty != length) { charty = length; xresize = TRUE; } /* Make sure the window isn't too large or too small. */ } else { if (chartx < BITMAPX1) { chartx = BITMAPX1; xresize = TRUE; } else if (chartx > BITMAPX) { chartx = BITMAPX; xresize = TRUE; } if (charty < BITMAPY1) { charty = BITMAPY1; xresize = TRUE; } else if (charty > BITMAPY) { charty = BITMAPY; xresize = TRUE; } } /* If in animation mode, ensure we are in the flicker free resolution. */ if (xnow < 0) { xnow = -xnow; #ifdef MSG if (xscreen == hiresmode) { xscreen = loresmode; XBegin(); chartx = config.numxpixels; charty = config.numypixels; XSquare(&chartx, &charty, FALSE); xresize = TRUE; } #endif } /* Physically resize window if we've changed the size parameters. */ if (xresize) { xresize = FALSE; #ifdef X11 XResizeWindow(disp, window, chartx, charty); XFreePixmap(disp, pixmap); pixmap = XCreatePixmap(disp, window, chartx, charty, depth); #else if (config.numxpixels > chartx) offsetx = (config.numxpixels - chartx) >> 1; else { if (xcorner % 3 == 1) offsetx = 0; else if (xcorner % 3 == 0) offsetx = -chartx + config.numxpixels; else offsetx = -(chartx - config.numxpixels) / 2; } if (config.numypixels > charty) offsety = (config.numypixels - charty) >> 1; else { if (xcorner > 6) offsety = 0; else if (xcorner < 4) offsety = -charty + config.numypixels; else offsety = -(charty - config.numypixels) / 2; } #endif xredraw = TRUE; } /* Recast chart if the chart information has changed any. */ if (xcast) { xcast = FALSE; SetCore(Mon, Day, Yea, Tim, Zon, Lon, Lat); if (relation) CastRelation(FALSE); else CastChart(TRUE); xredraw = TRUE; } if (xnow && !xpause) xredraw = TRUE; /* Update the screen if anything has changed since last time around. */ if (xredraw) { xredraw = FALSE; /* If we're in animation mode, change the chart info appropriately. */ if (xnow) Animate(xnow, dir); #ifdef X11 XFillRectangle(disp, pixmap, pmgc, 0, 0, chartx, charty); #else /* MSG */ #ifdef MOUSE SetPtrVis(HIDE); #endif if (config.numvideopages > 1) _setactivepage(_getactivepage() == 0); #endif /* MSG */ XChart(); #ifdef X11 XSync(disp, 0); XCopyArea(disp, pixmap, window, gc, 0, 0, chartx, charty, 0, 0); #else /* MSG */ if (config.numvideopages > 1) _setvisualpage(_getactivepage()); #ifdef MOUSE if (!xnow) SetPtrVis(SHOW); #endif #endif /* MSG */ } /* if */ /* Now process what's on the event queue, i.e. any keys pressed, etc. */ #ifdef X11 if (XEventsQueued(disp, QueuedAfterFlush /*QueuedAfterReading*/ )) { XNextEvent(disp, &event); /* Restore what's on window if a part of it gets uncovered. */ if (event.type == Expose && event.xexpose.count == 0) { XSync(disp, 0); XCopyArea(disp, pixmap, window, gc, 0, 0, chartx, charty, 0, 0); } switch (event.type) { /* Check for a manual resize of window by user. */ case ConfigureNotify: chartx = event.xconfigure.width; charty = event.xconfigure.height; XFreePixmap(disp, pixmap); pixmap = XCreatePixmap(disp, window, chartx, charty, depth); xredraw = TRUE; break; case MappingNotify: XRefreshKeyboardMapping((XMappingEvent PTR)&event); break; #ifdef MOUSE /* Process any mouse buttons the user pressed. */ case ButtonPress: mousex = event.xbutton.x; mousey = event.xbutton.y; if (event.xbutton.button == Button1) { DrawColor(hilite); DrawPoint(mousex, mousey); XSync(disp, 0); XCopyArea(disp, pixmap, window, gc, 0, 0, chartx, charty, 0, 0); } else if (event.xbutton.button == Button2 && (modex == MODEL || modex == MODEW) && degree == 0) { Lon = DEGHALF-(real)(event.xbutton.x-1)/(real)(chartx-2)*DEGREES; Lat = DEGQUAD-(real)(event.xbutton.y-1)/(real)(charty-2)*181.0; fprintf(S, "Mouse is at %s.\n", CharLocation(Lon, Lat, 60.0)); } else if (event.xbutton.button == Button3) xbreak = TRUE; break; /* Check for user dragging any of the mouse buttons across window. */ case MotionNotify: DrawColor(coldrw); DrawLine(mousex, mousey, event.xbutton.x, event.xbutton.y); XSync(disp, 0); XCopyArea(disp, pixmap, window, gc, 0, 0, chartx, charty, 0, 0); mousex = event.xbutton.x; mousey = event.xbutton.y; break; #endif /* Process any keys user pressed in window. */ case KeyPress: length = XLookupString((XKeyEvent PTR)&event, xkey, 10, &key, 0); if (length == 1) { i = xkey[0]; #else /* MSG */ #ifdef MOUSE if (!xnow && GetMouseEvent((EVENT *)&event)) { /* If the left button is down, draw on the screen. */ if (event.fsBtn == LEFT_DOWN && mousex >= 0) { SetPtrVis(HIDE); DrawColor(coldrw); _moveto(mousex, mousey); buttonx = event.x; buttony = event.y; _lineto(buttonx, buttony); /* If the right button is down, change the default location. */ } else if (event.fsBtn == RIGHT_DOWN) { if ((modex == MODEL || modex == MODEW) && degree == 0) { Lon = DEGHALF-(real)(event.x-offsetx)/(real)(chartx-2)*DEGREES; if (Lon < -DEGHALF) Lon = -DEGHALF; else if (Lon > DEGHALF) Lon = DEGHALF; Lat = DEGQUAD-(real)(event.y-offsety)/(real)(charty-2)*181.0; if (Lat < -DEGQUAD) Lat = -DEGQUAD; else if (Lat > DEGQUAD) Lat = DEGQUAD; xcast = TRUE; /* Right button means draw lines if not in a world map mode. */ } else if (buttonx >= 0) { SetPtrVis(HIDE); DrawColor(coldrw); _moveto(buttonx, buttony); _lineto(event.x, event.y); } /* Middle button (which most PC's don't have) mean exit program. */ } else if (event.fsBtn == MIDDLE_DOWN) xbreak = TRUE; mousex = event.x; mousey = event.y; SetPtrVis(SHOW); } else #endif if (kbhit()) { i = getch(); #endif /* MSG */ switch (i) { case ' ': xredraw = TRUE; break; case 'p': xpause = !xpause; break; case 'r': dir = -dir; break; case 'x': xreverse = !xreverse; XColorInit(); xredraw = TRUE; break; case 'm': if (!xmono) { xcolor = !xcolor; #ifdef MSG _getvideoconfig((struct videoconfig far *) &config); #endif XColorInit(); xredraw = TRUE; } break; case 'B': #ifdef X11 XSetWindowBackgroundPixmap(disp, root, pixmap); XClearWindow(disp, root); #else chartx = config.numxpixels; charty = config.numypixels; XSquare(&chartx, &charty, FALSE); xresize = TRUE; #endif break; case 'T': xtext = !xtext; xredraw = TRUE; break; case 'i': xbonus = !xbonus; xredraw = TRUE; break; case 'b': xborder = !xborder; xredraw = TRUE; break; case 'l': xlabel = !xlabel; xredraw = TRUE; break; case '<': if (scale > 100) { scale -= 100; xresize = TRUE; } break; case '>': if (scale < 400) { scale += 100; xresize = TRUE; } break; case '[': if (modex == MODEG) { tilt = tilt > -DEGQUAD ? tilt-11.25 : -DEGQUAD; xredraw = TRUE; } break; case ']': if (modex == MODEG) { tilt = tilt < DEGQUAD ? tilt+11.25 : DEGQUAD; xredraw = TRUE; } break; case 'Q': XSquare(&chartx, &charty, TRUE); xresize = TRUE; break; case 'R': for (i = _CHI; i < THINGS; i++) ignore[i] = !ignore[i]; ignore[_FOR] = !ignore[_FOR]; ignore[_VTX] = !ignore[_VTX]; xredraw = TRUE; break; case 'C': operation ^= DASHC; for (i = C_LO; i <= C_HI; i++) ignore[i] = !(operation & DASHC) || !ignore[i]; xcast = TRUE; break; case 'u': operation ^= DASHu; for (i = U_LO; i <= U_HI; i++) ignore[i] = !(operation & DASHu) || !ignore[i]; xcast = TRUE; break; case 'U': universe = !universe; for (i = S_LO; i <= S_HI; i++) ignore[i] = !universe || !ignore[i]; xcast = TRUE; break; case 'c': if (!relation) { relation = DASHr0; SetTwin(Mon, Day, Yea, Tim, Zon, Lon, Lat); } else relation = 0; xcast = TRUE; break; case 's': operation ^= DASHs; xcast = TRUE; break; case 'h': centerplanet = centerplanet ? 0 : 1; xcast = TRUE; break; case 'f': operation ^= DASHf; xcast = TRUE; break; case 'F': operation ^= DASH3; xcast = TRUE; break; case '+': Animate(4, abs(dir)); xcast = TRUE; break; case '-': Animate(4, -abs(dir)); xcast = TRUE; break; case 'o': SetSave(Mon, Day, Yea, Tim, Zon, Lon, Lat); break; case 'O': SetMain(MonX, DayX, YeaX, TimX, ZonX, LonX, LatX); xcast = TRUE; break; #ifdef TIME case 'n': InputData("now"); SetMain(MM, DD, YY, TT, ZZ, OO, AA); xcast = TRUE; break; #endif case 'N': /* The continuous update animation. */ xnow = xnow ? 0 : -10; break; case '!': xnow = -1; break; /* These are the nine different */ case '@': xnow = -2; break; /* "add time to chart" animations. */ case '#': xnow = -3; break; case '$': xnow = -4; break; case '%': xnow = -5; break; case '^': xnow = -6; break; case '&': xnow = -7; break; case '*': xnow = -8; break; case '(': xnow = -9; break; case 'V': modex = MODEv; xredraw = TRUE; break; /* Should we go */ case 'L': modex = MODEL; xredraw = TRUE; break; /* switch to a */ case 'A': modex = MODEg; xredraw = TRUE; break; /* new chart type? */ case 'Z': modex = MODEZ; xredraw = TRUE; break; case 'S': modex = MODES; xredraw = TRUE; break; case 'E': modex = MODEE; xredraw = TRUE; break; case 'W': modex = MODEW; xredraw = TRUE; break; case 'G': modex = MODEG; xredraw = TRUE; break; case 'P': modex = MODEP; xredraw = TRUE; break; #ifdef BIORHYTHM case 'Y': /* Should we switch to biorhythm chart? */ if (!relation) { SetTwin(Mon, Day, Yea, Tim, Zon, Lon, Lat); } relation = DASHrb; modex = MODEb; xcast = TRUE; break; #endif case '0': exdisplay ^= DASHZ0 | DASHEy | DASHXW0; modex = (modex == MODEv ? MODEw : (modex == MODEw ? MODEv : modex)); xredraw = TRUE; break; case 'v': case 'H': case '?': #ifdef MSG _setvideomode(_DEFAULTMODE); if (i != 'v') _settextrows(43); #endif if (i == 'v') ChartLocation(); else XDisplayKeys(); #ifdef MSG while (!kbhit()) ; i = getch(); if (i == 'q' || i == ESCAPE || i == '\3') { xbreak = TRUE; break; } XBegin(); xresize = TRUE; #endif break; #ifdef MSG case '\t': if (xscreen == hiresmode) xscreen = loresmode; else xscreen = hiresmode; XBegin(); chartx = config.numxpixels; charty = config.numypixels; XSquare(&chartx, &charty, FALSE); xresize = TRUE; break; #endif case '\b': #ifdef MSG #ifdef MOUSE SetPtrVis(HIDE); #endif #endif /* MSG */ DrawClearScreen(); break; #ifdef MOUSE case 'z'-'`': coldrw = BLACK; break; case 'e'-'`': coldrw = MAROON; break; case 'f'-'`': coldrw = DKGREEN; break; case 'o'-'`': coldrw = ORANGE; break; case 'n'-'`': coldrw = DKBLUE; break; case 'u'-'`': coldrw = PURPLE; break; case 'k'-'`': coldrw = DKCYAN; break; case 'l'-'`': coldrw = LTGRAY; break; case 'd'-'`': coldrw = DKGRAY; break; case 'r'-'`': coldrw = RED; break; case 'g'-'`': coldrw = GREEN; break; case 'y'-'`': coldrw = YELLOW; break; case 'b'-'`': coldrw = BLUE; break; case 'v'-'`': coldrw = MAGENTA; break; case 'j'-'`': coldrw = CYAN; break; case 'a'-'`': coldrw = WHITE; break; #ifdef MSG case 't'-'`': SetPtrVis(HIDE); if (buttonx >= 0) _rectangle(_GBORDER, buttonx, buttony, mousex, mousey); SetPtrVis(SHOW); break; case 'x'-'`': SetPtrVis(HIDE); if (buttonx >= 0) _ellipse(_GBORDER, buttonx, buttony, mousex, mousey); SetPtrVis(SHOW); break; #endif #endif /* MOUSE */ case 'q': case ESCAPE: case '\3': xbreak = TRUE; break; default: if (i > '0' && i <= '9') { #ifdef MSG if (xnow) #endif /* Process numbers 1..9 signifying animation rate. */ dir = (dir > 0 ? 1 : -1)*(i-'0'); #ifdef MSG else { /* If we aren't in animation mode, then 1..9 refers to the */ /* clipping "quadrant" to use if chart size > screen size. */ xcorner = i-'0'; xresize = TRUE; } #endif break; } printc(BELL); /* Any key not bound will sound a beep. */ } /* switch */ } /* if */ #ifdef X11 default: ; } /* switch */ } /* if */ #endif } /* while */ } /* This is called right before program termination to get rid of the window. */ void XEnd() { #ifdef X11 XFreeGC(disp, gc); XFreeGC(disp, pmgc); XFreePixmap(disp, pixmap); XDestroyWindow(disp, window); XCloseDisplay(disp); #else _setvideomode(_DEFAULTMODE); #endif } #endif /* ISG */ /* ****************************************************************************** ** Main graphics processing ****************************************************************************** */ /* Print a list of every command switch dealing with the graphics features */ /* that can be passed to the program, and a description of what it does. */ /* This is part of what the -H switch prints, if graphics were compiled in. */ void XDisplaySwitches() { Prints(" _X: Create a graphics chart instead of displaying it as text."); #ifdef ISG Prints(" _Xb: Create bitmap file instead of putting graphics on screen."); #endif Prints(" _Xb[n,c,v,a,b]: Set bitmap file output mode to X11 normal,"); Prints(" compacted, very compact, Ascii (bmtoa), or Windows bmp."); #ifdef PS Prints(" _Xp: Create PostScript stroke graphic instead of bitmap file."); Prints(" _Xp0: Like _Xp but create complete instead of encapsulated file."); #endif #ifdef META Prints(" _XM[0]: Create Windows metafile stroke graphic instead of bitmap."); #endif Prints(" _Xo <file>: Write output bitmap or graphic to specified file."); #ifdef X11 Prints(" _XB: Display X chart on root instead of in a separate window."); #endif Prints(" _Xm: Create monochrome graphic instead of one in color."); Prints(" _Xr: Create chart graphic in reversed colors (white background)."); #ifdef X11 Prints(" _Xw <hor> [<ver>], _ge[..]: Change the size of chart graphic."); #else Prints(" _Xw <hor> [<ver>]: Change the size of chart graphic."); #endif Prints(" _Xs <100,200,300,400>: Change the size of map or characters by %."); Prints(" _Xi: Create chart graphic in slightly modified form."); Prints(" _XT: Inhibit display of chart info at bottom of graphic."); Prints(" _Xl: Inhibit labeling of object points in chart graphic."); Prints(" _X1 <object>: Rotate wheel charts so object is at left edge."); Prints(" _X2 <object>: Rotate wheel charts so object is at top edge."); #ifdef X11 Prints(" _Xd <name>, _di[..] <name>: Open X window on specified display."); #endif Prints(" _XW: Simply create an image of the world map."); Prints(" _XW0: Like _XW but do a non-rectangular Mollewide projection."); Prints(" _XP: Create just the world map, but from a polar projection."); Prints(" _XG [<degrees>]: Display the image of the world as a globe."); #ifdef ISG Prints(" _Xn [<mode>]: Start up chart or globe display in animation mode."); Prints("Also, press 'H' while running for list of key press options."); #endif } /* Process a command line switch passed to the program dealing with the */ /* graphics features. This is just like the processing of each switch in the */ /* main program; however, here each switch has been prefixed with an 'X'. */ int XProcessSwitches(argc, argv, pos) int argc, pos; char **argv; { int i = 0; char string[STRING], c; switch (argv[0][pos]) { case '\0': break; case 'b': c = CAP(argv[0][pos+1]); if (IsValidBmpmode(c)) bitmapmode = c; xbitmap = TRUE; psfile = metafile = FALSE; break; #ifdef PS case 'p': psfile = TRUE + (argv[0][pos+1] != '0'); xbitmap = metafile = FALSE; break; #endif #ifdef META case 'M': if (argv[0][pos+1] == '0') xfont = !xfont; metafile = TRUE; xbitmap = psfile = FALSE; break; #endif case 'o': if (argc <= 1) { TooFew("Xo"); return -1; } if (!xbitmap && !psfile && !metafile) xbitmap = TRUE; outputfile = argv[1]; i++; break; #ifdef X11 case 'B': xroot = !xroot; break; #endif case 'm': xcolor = !xcolor; break; case 'r': xreverse = !xreverse; break; case 'w': if (argc <= 1) { TooFew("Xw"); return -1; } chartx = atoi(argv[1]); if (argc > 2 && (charty = atoi(argv[2]))) { argc--; argv++; i++; } else charty = chartx; if (!IsValidGraphx(chartx)) { BadVal("Xw", chartx); return -1; } if (!IsValidGraphy(charty)) { BadVal("Xw", charty); return -1; } i++; break; case 's': if (argc <= 1) { TooFew("Xs"); return -1; } scale = atoi(argv[1]); if (scale < 100) scale *= 100; if (!IsValidScale(scale)) { BadVal("Xs", scale); return -1; } i++; break; case 'i': xbonus = !xbonus; break; case 'T': xtext = !xtext; break; case 'l': xlabel = !xlabel; break; case '1': if (argc <= 1) { TooFew("X1"); return -1; } xeast = atoi(argv[1]); if (!IsItem(xeast)) { BadVal("X1", xeast); return -1; } i++; break; case '2': if (argc <= 1) { TooFew("X2"); return -1; } xeast = atoi(argv[1]); if (!IsItem(xeast)) { BadVal("X2", xeast); return -1; } xeast = -xeast; i++; break; case 'd': if (argc <= 1) { TooFew("Xd"); return -1; } dispname = argv[1]; i++; break; case 'W': if (argc > 1 && ((degree = atoi(argv[1])) || argv[1][0] == '0')) { i++; if (degree < 0 || degree >= DEGD) { BadVal("XW", degree); return -1; } } else degree = 0; modex = MODEW; if (argv[0][pos+1] == '0') exdisplay |= DASHXW0; autom = TRUE; break; case 'P': if (argc > 1 && ((degree = atoi(argv[1])) || argv[1][0] == '0')) { i++; if (degree < 0 || degree >= DEGD) { BadVal("XP", degree); return -1; } } else degree = 0; modex = MODEP; if (argv[0][pos+1] == '0') exdisplay |= DASHXP0; autom = TRUE; break; case 'G': if (argc > 1 && ((degree = atoi(argv[1])) || argv[1][0] == '0')) { i++; if (degree < 0 || degree >= DEGD) { BadVal("XG", degree); return -1; } if (argc > 2 && ((tilt = atof(argv[2])) || argv[2][0] == '0')) { i++; if (tilt < -DEGQUAD || tilt > DEGQUAD) { BadVal2("XG", tilt); return -1; } } } modex = MODEG; autom = TRUE; break; #ifdef ISG case 'n': if (argc > 1 && (xnow = atoi(argv[1]))) i++; else xnow = 10; if (xnow < 1 || xnow > 10) { BadVal("Xn", xnow); return -1; } break; #endif default: sprintf(string, "Unknown switch '%s'", argv[0]); PrintError(string); return -1; } return i; /* 'i' contains the value to be added to argc when we return. */ } /* This is the main interface to all the graphics features. This routine */ /* is called from the main program if any of the -X switches were specified, */ /* and it sets up for and goes and generates the appropriate graphics chart. */ /* We return TRUE if successfull, FALSE if some non-fatal error occurred. */ bool XAction() { char string[STRING]; xfile = (xbitmap || psfile || metafile); /* First figure out what graphic mode to generate the chart in, based on */ /* various non-X command switches, e.g. -L combined with -X, -g combined */ /* with -X, and so on, and determine the size the window is to be, too. */ if (modex == MODEv) { if (todisplay & DASHw) modex = MODEw; else if (todisplay & DASHL) modex = MODEL; else if ((todisplay & DASHg) | (todisplay & DASHm)) { modex = MODEg; if (relation <= DASHr0 && (todisplay & DASHm) > 0 && (exdisplay & DASHm0) == 0) exdisplay |= DASHg0; chartx = charty = (gridobjects + (relation <= DASHr0))*CELLSIZE*SCALE + 1; } else if (todisplay & DASHZ) modex = MODEZ; else if (todisplay & DASHS) modex = MODES; else if (todisplay & DASHE) modex = MODEE; else if (relation == DASHrb) modex = MODEb; } if (ISSIDEBAR) chartx += SIDESIZE; if (modex == MODEL || modex == MODEW) { chartx = DEGD*SCALE+2; charty = (90*2+1)*SCALE+2; } scalet = psfile ? PSMUL : (metafile ? METAMUL : 1); if (xfile) { if (chartx > BITMAPX) chartx = BITMAPX; if (charty > BITMAPY) charty = BITMAPY; if (xbitmap) { bitmaprow = (chartx + 1) >> 1; Allocate(bm, (long)bitmaprow * charty, bitmap); if (bm == NULL) { sprintf(string, "Not enough memory for %d by %d bitmap (%ld bytes).", chartx, charty, (long)bitmaprow * charty); PrintError(string); return FALSE; } } #ifdef PS else if (psfile) PSbegin(); #endif else { Allocate(bm, MAXMETA, bitmap); if (bm == NULL) { sprintf(string, "Not enough memory for metafile. (%ld bytes.)", MAXMETA); PrintError(string); return FALSE; } chartx *= METAMUL; /* Increase chart sizes and scales behind the */ charty *= METAMUL; /* scenes to make graphics look smoother. */ scale *= METAMUL; } XColorInit(); } #ifdef ISG else XBegin(); #endif if (xroot || xfile) /* Go draw the graphic chart. */ XChart(); if (xfile) { /* Write bitmap to file if in that mode. */ WriteFile(); if (!psfile) Deallocate(bm); } #ifdef ISG else { #ifdef X11 if (xroot) { XSetWindowBackgroundPixmap(disp, root, pixmap); /* Process -XB. */ XClearWindow(disp, root); /* If -Xn in effect with -XB, then enter infinite loop where we */ /* calculate and animate chart, displaying on the root window. */ if (xnow) loop { Animate(xnow, 1); if (relation > DASHr0 || (modex != MODEZ && modex != MODES)) XFillRectangle(disp, pixmap, pmgc, 0, 0, chartx, charty); XChart(); XSetWindowBackgroundPixmap(disp, root, pixmap); XClearWindow(disp, root); } } else #endif XSpin(); /* Window's up; process commands given to window now. */ XEnd(); } #endif /* ISG */ return TRUE; } #endif /* GRAPH */ /* xdriver.c */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.