⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xdriver.c

📁 占星术4.0源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
** Astrolog (Version 4.00) File: xdriver.c
**
** IMPORTANT NOTICE: the graphics database and chart display routines
** used in this program are Copyright (C) 1991-1993 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 12/31/1993.
*/

#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 += 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 >= DEGR)     /* For animating globe display, add */
      degree -= DEGR;       /* in appropriate degree value.     */
    else if (degree < 0)
      degree += DEGR;
  } 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 update 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 */
}


/* 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,
    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 = DEGR*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) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -