home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume42 / astrolog / part08 / driver.c
C/C++ Source or Header  |  1994-03-25  |  56KB  |  1,808 lines

  1. /*
  2. ** Astrolog (Version 4.10) File: driver.c
  3. **
  4. ** IMPORTANT NOTICE: the graphics database and chart display routines
  5. ** used in this program are Copyright (C) 1991-1994 by Walter D. Pullen
  6. ** (cruiser1@stein.u.washington.edu). Permission is granted to freely
  7. ** use and distribute these routines provided one doesn't sell,
  8. ** restrict, or profit from them in any way. Modification is allowed
  9. ** provided these notices remain with any altered or edited versions of
  10. ** the program.
  11. **
  12. ** The main planetary calculation routines used in this program have
  13. ** been Copyrighted and the core of this program is basically a
  14. ** conversion to C of the routines created by James Neely as listed in
  15. ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  16. ** available from Matrix Software. The copyright gives us permission to
  17. ** use the routines for personal use but not to sell them or profit from
  18. ** them in any way.
  19. **
  20. ** The PostScript code within the core graphics routines are programmed
  21. ** and Copyright (C) 1992-1993 by Brian D. Willoughby
  22. ** (brianw@sounds.wa.com). Conditions are identical to those above.
  23. **
  24. ** The extended accurate ephemeris databases and formulas are from the
  25. ** calculation routines in the program "Placalc" and are programmed and
  26. ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
  27. ** (alois@azur.ch). The use of that source code is subject to
  28. ** regulations made by Astrodienst Zurich, and the code is not in the
  29. ** public domain. This copyright notice must not be changed or removed
  30. ** by any user of this program.
  31. **
  32. ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
  33. ** X Window graphics initially programmed 10/23-29/1991.
  34. ** PostScript graphics initially programmed 11/29-30/1992.
  35. ** Last code change made 3/19/1994.
  36. */
  37.  
  38. #include "astrolog.h"
  39.  
  40. char *filenamescreen = NULL, *filenameout, **extralines;
  41. int prog = FALSE, extracount = 0;
  42.  
  43.  
  44. /*
  45. ******************************************************************************
  46. ** Table Display Routines.
  47. ******************************************************************************
  48. */
  49.  
  50. /* A subprocedure of the credit displayed below, this prints out one line */
  51. /* of credit information on the screen. Given a string, it's displayed    */
  52. /* centered with left and right borders around it, in the given color.    */
  53.  
  54. #define CREDITWIDTH 74
  55.  
  56. void PrintW(string, col)
  57. char *string;
  58. int col;
  59. {
  60.   int i;
  61.  
  62.   if (!string) {
  63.  
  64.     /* Null string means print the top, bottom, or a separator row. */
  65.  
  66.     if (col < 0)
  67.       AnsiColor(RED);
  68.     printc(col ? (col > 0 ? BOXSW : BOXNW) : BOXJE);
  69.     PrintTab(BOXH, CREDITWIDTH);
  70.     printc(col ? (col > 0 ? BOXSE : BOXNE) : BOXJW);
  71.   } else {
  72.     i = StringLen(string);
  73.     printc(BOXV);
  74.     PrintTab(' ', (CREDITWIDTH-i)/2 + (i&1));
  75.     AnsiColor(col);
  76.     fprintf(S, "%s", string);
  77.     PrintTab(' ', (CREDITWIDTH-i)/2);
  78.     AnsiColor(RED);
  79.     printc(BOXV);
  80.   }
  81.   printl();
  82. }
  83.  
  84.  
  85. /* Display a list of credits showing those who helped create the various  */
  86. /* parts of Astrolog, as well as important copyright and version info, as */
  87. /* displayed with the -Hc switch.                                         */
  88.  
  89. void DisplayCredits()
  90. {
  91.   char string[STRING];
  92.  
  93.   PrintW(NULL, -1);
  94.   sprintf(string, "%s version %s", appname, VERSION);
  95.   PrintW(string, WHITE);
  96.   sprintf(string, "As of %s.", DATE);
  97.   PrintW(string, LTGRAY);
  98.   PrintW("By Walter D. Pullen (cruiser1@stein.u.washington.edu)", CYAN);
  99.   PrintW(NULL, 0);
  100.   PrintW("Main planetary calculation formulas were converted from", GREEN);
  101.   PrintW(
  102.     "routines by James Neely, as listed in 'Manual of Computer Programming",
  103.     GREEN);
  104.   PrintW(
  105.     "for Astrologers' by Michael Erlewine, available from Matrix Software.",
  106.     GREEN);
  107.   PrintW("PostScript graphics routines by Brian D. Willoughby", YELLOW);
  108.   PrintW(
  109.     "Extended ephemeris calculation and formulas are by Alois Treindl,",
  110.     MAGENTA);
  111.   PrintW(
  112.     "as in the package 'Placalc', available from Astrodienst AG.", MAGENTA);
  113.   PrintW(
  114.     "IMPORTANT: Astrolog is 'freeware', but is copyrighted and not in public",
  115.     LTGRAY);
  116.   PrintW(
  117.     "domain. Permission is granted to freely use and distribute these",
  118.     LTGRAY);
  119.   PrintW(
  120.     "routines provided one does not sell, restrict, or profit from the",
  121.     LTGRAY);
  122.   PrintW(
  123.     "program or its output in any way. Modification is allowed provided",
  124.     LTGRAY);
  125.   PrintW(
  126.     "these exact notices remain with any altered or edited versions of the",
  127.     LTGRAY);
  128.   PrintW(
  129.     "program. These conditions are true of both the program in whole and of",
  130.     LTGRAY);
  131.   PrintW(
  132.     "all parts by any individual author. Violators are subject to copyright",
  133.     LTGRAY);
  134.   PrintW(
  135.     "law penalties, and negative karmic debts to aforementioned contributors.",
  136.     LTGRAY);
  137.   PrintW(NULL, 0);
  138.   PrintW(
  139.     "Special thanks to all those unmentioned, seen and unseen, who have",
  140.      BLUE);
  141.   PrintW(
  142.     "pointed out problems, suggested featues, and sent many positive vibes!",
  143.     BLUE);
  144.   PrintW(NULL, 1);
  145.   AnsiColor(DEFAULT);
  146. }
  147.  
  148.  
  149. /* Print out a command switch or keypress info line to the screen, as done  */
  150. /* with the -H switch or 'H' key in a graphic window. This is just printing */
  151. /* out the string, except in Ansi mode we set the proper colors: Red for    */
  152. /* header lines, Green for individual switches or keys, and White for the   */
  153. /* rest of the line telling what it does. We also prefix each switch with   */
  154. /* either Unix's '-' or PC's '/', whichever is appropriate for the system.  */
  155.  
  156. void Prints(string)
  157. char *string;
  158. {
  159.   int dash;
  160.   char c;
  161.  
  162.   dash = string[1];
  163.   if (*string != ' ')
  164.     AnsiColor(RED);
  165.   else if (dash != ' ')
  166.     AnsiColor(dash == 'P' || string[3] == ' ' || string[3] == ':' ?
  167.       GREEN : DKGREEN);
  168.   else
  169.     AnsiColor(DEFAULT);
  170.   while ((c = *string) && c != ':' &&
  171.     (dash != 'P' || (c != ' ' || *(string+1) != 't'))) {
  172.     if (c != '_')
  173.       printc(c);
  174.     else
  175.       printc(DASH);
  176.     string++;
  177.   }
  178.   if (*string)
  179.     printc(*string++);
  180.   AnsiColor(DEFAULT);
  181.   while (c = *string) {
  182.     if (c != '_')
  183.       printc(c);
  184.     else
  185.       printc(DASH);
  186.     string++;
  187.   }
  188.   printl();
  189. }
  190.  
  191.  
  192. /* Print a list of every command switch that can be passed to the program, */
  193. /* and a description of what it does. This is what the -H switch prints.   */
  194.  
  195. void DisplaySwitches()
  196. {
  197.   char string[STRING];
  198.  
  199.   sprintf(string, "%s (version %s) command switches:", appname, VERSION);
  200.   Prints(string);
  201.   Prints(" _H: Display this help list.");
  202.   Prints(" _Hc: Display program credits and copyrights.");
  203.   Prints(" _H0: Display names of zodiac signs and houses.");
  204.   Prints(" _O: Display available planets and other celestial objects.");
  205.   Prints(" _O0: Like _O but ignore object restrictions.");
  206.   Prints(" _A: Display available aspects, their angles, and present orbs.");
  207. #ifdef INTERPRET
  208.   Prints(" _I0: Display meanings of signs, houses, planets, and aspects.");
  209. #endif
  210.   Prints(" _Q: Prompt for more command switches after display finished.");
  211. #ifdef SWITCHES
  212.   Prints(" _Q0: Like _Q but prompt for additional switches on startup.");
  213. #endif
  214.   Prints("\nSwitches which determine the type of chart to display:");
  215.   Prints(" _v: Display list of object positions (chosen by default).");
  216.   Prints(" _v0: Like _v but express velocities relative to average speed.");
  217.   Prints(" _w [<rows>]: Display chart in a graphic house wheel format.");
  218.   Prints(" _w0 [..]: Like _w but reverse order of objects in houses 4..9.");
  219.   Prints(" _g: Display aspect and midpoint grid among planets.");
  220.   Prints(" _g0: Like _g but flag aspect configurations (e.g. Yod's) too.");
  221.   Prints(" _g0: For comparison charts, show midpoints instead of aspects.");
  222.   Prints(" _ga: Like _g but indicate applying instead of difference orbs.");
  223.   Prints(" _m: Display all object midpoints in sorted zodiac order.");
  224.   Prints(" _m0: Like _m but list aspects ordered by influence instead.");
  225.   Prints(" _m[0]a: Like _m0 but indicate applying and separating orbs.");
  226.   Prints(" _Z: Display planet locations with respect to the local horizon.");
  227. #ifdef GRAPH
  228.   Prints(" _Z0: Like _Z but express coordinates relative to polar center.");
  229. #endif
  230.   Prints(" _Zd: Search day for object local rising and setting times.");
  231.   Prints(" _S: Display x,y,z coordinate positions of planets in space.");
  232.   Prints(" _j: Display astrological influences of each object in chart.");
  233.   Prints(" _j0: Like _j but include influences of each zodiac sign as well.");
  234.   Prints(" _L [<step>]: Display astro-graph locations of planetary angles.");
  235.   Prints(" _L0 [..]: Like _L but display list of latitude crossings too.");
  236.   Prints(" _K: Display a calendar for given month.");
  237.   Prints(" _Ky: Like _K but display a calendar for the entire year.");
  238.   Prints(" _d [<step>]: Print all aspects and changes occurring in a day.");
  239.   Prints(" _dm: Like _d but print all aspects for the entire month.");
  240.   Prints(" _dy: Like _d but print all aspects for the entire year.");
  241.   Prints(" _dp <month> <year>: Print aspects within progressed chart.");
  242.   Prints(" _dpy <year>: Like _dp but search for aspects within entire year.");
  243.   Prints(" _dp[y]n: Search for progressed aspects in current month/year.");
  244.   Prints(" _D: Like _d but display aspects by influence instead of time.");
  245.   Prints(" _E: Display planetary ephemeris for given month.");
  246.   Prints(" _Ey: Display planetary ephemeris for the entire year.");
  247.   Prints(" _e: Print all charts together (i.e. _v_w_g0_m_Z_S_j0_L0_K_d_D_E).");
  248.   Prints(
  249.     " _t <month> <year>: Compute all transits to natal planets in month.");
  250.   Prints(
  251.     " _tp <month> <year>: Compute progressions in month for chart.");
  252.   Prints(" _t[p]y: <year>: Compute transits/progressions for entire year.");
  253.   Prints(" _t[p]Y: <year> <years>: Compute transits for a number of years.");
  254. #ifdef TIME
  255.   Prints(" _t[py]n: Compute transits to natal planets for current time now.");
  256. #endif
  257.   Prints(" _T <month> <day> <year>: Display transits ordered by influence.");
  258.   Prints(" _Tp <month> <day> <year>: Print progressions instead of transits.");
  259. #ifdef TIME
  260.   Prints(" _T[p]n: Display transits ordered by influence for current date.");
  261. #endif
  262. #ifdef INTERPRET
  263.   Prints(" _I [<columns>]: Print interpretation of selected charts.");
  264. #endif
  265.   Prints("\nSwitches which affect how the chart parameters are obtained:");
  266. #ifdef TIME
  267.   Prints(" _n: Compute chart for this exact moment using current time.");
  268.   Prints(" _n[d,m,y]: Compute chart for start of current day, month, year.");
  269. #endif
  270.   Prints(" _z: Assume Daylight time (change default zone appropriately).");
  271.   Prints(" _z <zone>: Change the default time zone (for _d_E_t_q options).");
  272.   Prints(" _l <long> <lat>: Change the default longitude & latitude.");
  273.   Prints(" _q <month> <date> <year> <time>: Compute chart with defaults.");
  274.   Prints(" _qd <month> <date> <year>: Compute chart for noon on date.");
  275.   Prints(" _qm <month> <year>: Compute chart for first of month.");
  276.   Prints(" _qy <year>: Compute chart for first day of year.");
  277.   Prints(" _qa <month> <date> <year> <time> <zone> <long> <lat>:");
  278.   Prints("     Compute chart automatically given specified data.");
  279.   Prints(" _qj <day>: Compute chart for time of specified Julian day.");
  280.   Prints(" _i <file>: Compute chart based on info in file.");
  281.   Prints(" _o <file> [..]: Write parameters of current chart to file.");
  282.   Prints(" _o0 <file> [..]: Like _o but output planet/house positions.");
  283.   Prints(" _os <file>: Redirect output of text charts to file.");
  284.   Prints("\nSwitches which affect what information is used in a chart:");
  285.   Prints(" _R [<obj1> [<obj2> ..]]: Restrict specific bodies from displays.");
  286.   Prints(" _R0 [<obj1> ..]: Like _R but restrict everything first.");
  287.   Prints(" _R1 [<obj1> ..]: Like _R0 but unrestrict and show all objects.");
  288.   Prints(" _R[C,u,U]: Restrict all minor cusps, all uranians, or stars.");
  289.   Prints(" _RT[0,1,C,u,U] [..]: Restrict transiting planets in _t lists.");
  290.   Prints(" _C: Include non-angular house cusps in charts.");
  291.   Prints(" _u: Include transneptunian/uranian bodies in charts.");
  292.   Prints(" _U: Include locations of fixed background stars in charts.");
  293.   Prints(" _U[z,l,n,b]: Order by azimuth, altitude, name, or brightness.");
  294.   Prints(" _A <0-18>: Specify the number of aspects to use in charts.");
  295.   Prints(" _Ao <aspect> <orb>: Specify maximum orb for an aspect.");
  296.   Prints(" _Am <planet> <orb>: Specify maximum orb allowed to a planet.");
  297.   Prints(" _Ad <planet> <orb>: Specify orb addition given to a planet.");
  298.   Prints(" _Aa <aspect> <angle>: Change the actual angle of an aspect.");
  299.   Prints("\nSwitches which affect how a chart is computed:");
  300. #ifdef PLACALC
  301.   Prints(" _b: Use ephemeris files for more accurate location computations.");
  302.   Prints(" _b0: Like _b but display locations to the nearest second too.");
  303. #endif
  304.   Prints(" _c <value>: Select a different default system of houses.");
  305.   Prints("     (0 = Placidus, 1 = Koch, 2 = Equal, 3 = Campanus,");
  306.   Prints("     4 = Meridian, 5 = Regiomontanus, 6 = Porphyry, 7 = Morinus,");
  307.   Prints(
  308.     "     8 = Topocentric, 9 = Equal (MC), 10 = Neo-Porphyry, 11 = None.)");
  309.   Prints(" _s [..]: Compute a sidereal instead of the normal tropical chart.");
  310.   Prints(" _s0: Display locations as right ascension instead of degrees.");
  311.   Prints(" _h [<objnum>]: Compute positions centered on specified object.");
  312.   Prints(" _p <month> <day> <year>: Cast 2ndary progressed chart for date.");
  313.   Prints(" _p0 <month> <day> <year>: Cast solar arc chart for date.");
  314. #ifdef TIME
  315.   Prints(" _p[0]n: Cast progressed chart based on current date now.");
  316. #endif
  317.   Prints(" _pd <days>: Set no. of days to progress / day (default 365.25).");
  318.   Prints(" _x <1-360>: Cast harmonic chart based on specified factor.");
  319.   Prints(" _1 [<objnum>]: Cast chart with specified object on Ascendant.");
  320.   Prints(" _2 [<objnum>]: Cast chart with specified object on Midheaven.");
  321.   Prints(" _3: Display objects in their zodiac decan positions.");
  322.   Prints(" _f: Display houses as sign positions (flip them).");
  323.   Prints(" _G: Compute houses based on geographic location only.");
  324.   Prints(" _F <objnum> <sign> <deg>: Force object's position to be value.");
  325.   Prints(" _+ [<days>]: Cast chart for specified no. of days in the future.");
  326.   Prints(" _- [<days>]: Cast chart for specified no. of days in the past.");
  327.   Prints(" _+[m,y] [<value>]: Cast chart for no. of months/years in future.");
  328.   Prints("\nSwitches for relationship and comparison charts:");
  329.   Prints(" _r <file1> <file2>: Compute a relationship synastry chart.");
  330.   Prints(" _rc <file1> <file2>: Compute a composite chart.");
  331.   Prints(" _rm <file1> <file2>: Compute a time space midpoint chart.");
  332.   Prints(" _r[c,m]0 <file1> <file2> <ratio1> <ratio2>: Weighted chart.");
  333.   Prints(" _rd <file1> <file2>: Print time span between files' dates.");
  334. #ifdef BIORHYTHM
  335.   Prints(" _rb <file1> <file2>: Display biorhythm for file1 at time file2.");
  336. #endif
  337.   Prints(" _r0 <file1> <file2>: Keep the charts separate in comparison.");
  338.   Prints(" _rp <file1> <file2>: Like _r0 but do file1 with progr. to file2.");
  339. #ifdef TIME
  340.   Prints(" _y <file>: Display current house transits for particular chart.");
  341. #ifdef BIORHYTHM
  342.   Prints(" _y[b,d,p] <file>: Print biorhythm/datediff for current time now.");
  343. #endif
  344. #endif /* TIME */
  345.   Prints("\nSwitches to access graphics options:");
  346.   Prints(" _k: Display text charts using Ansi characters and color.");
  347. #ifdef MSG
  348.   Prints(" _V: <25,43,50>: Start up with text mode set to number of rows.");
  349. #endif
  350.  
  351.   /* If graphics features are compiled in, call an additional procedure to */
  352.   /* display the command switches offered dealing with the graphics stuff. */
  353.  
  354. #ifdef GRAPH
  355.   XDisplaySwitches();
  356. #endif
  357. }
  358.  
  359.  
  360. /* Print out a list of the various objects - planets, asteroids, house     */
  361. /* cusps, stars - recognized by the program, and their index values. This  */
  362. /* is displayed when the -O switch is invoked. For some objects, display   */
  363. /* additional information, e.g. ruling signs for planets, brightnesses and */
  364. /* positions in the sky for fixed stars, etc.                              */
  365.  
  366. void PrintObjects(all)
  367. int all;
  368. {
  369.   int i, j;
  370.   real Off;
  371.  
  372.   if (!(operation & DASHC))
  373.     for (i = C_LO; i <= C_HI; i++)    /* Set up restrictions properly: Minor */
  374.       ignore[i] = TRUE;               /* cusps and uranians included only if */
  375.   if (!(operation & DASHu))           /* -C and -u switches are in effect.   */
  376.     for (i = U_LO; i <= U_HI; i++)
  377.       ignore[i] = TRUE;
  378.   fprintf(S, "%s planets and objects:\n", appname);
  379.   fprintf(S, "No. Name       Rule Co-Rule Fall Co-Fall Exalt Debilitate\n\n");
  380.   for (i = 1; i <= BASE; i++) if (all || !ignore[i]) {
  381.     AnsiColor(objectansi[i]);
  382.     fprintf(S, "%2d %-12s", i, objectname[i]);
  383.     if (i <= OBJECTS) {                      /* Print rulerships, etc */
  384.       if (ruler1[i]) {                       /* for the planets.      */
  385.         j = ruler2[i];
  386.         fprintf(S, "%c%c%c  %c%c%c     ", SIGNAM(ruler1[i]),
  387.           j ? signname[j][0] : ' ', j ? signname[j][1] : ' ',
  388.           j ? signname[j][2] : ' ');
  389.         fprintf(S, "%c%c%c  %c%c%c     ", SIGNAM(Mod12(ruler1[i]+6)),
  390.           j ? signname[Mod12(j+6)][0] : ' ',
  391.           j ? signname[Mod12(j+6)][1] : ' ',
  392.           j ? signname[Mod12(j+6)][2] : ' ');
  393.         fprintf(S, "%c%c%c   %c%c%c", SIGNAM(exalt[i]),
  394.           SIGNAM(Mod12(exalt[i]+6)));
  395.       }
  396.     } else {
  397.       if (ruler1[i]) {
  398.         fprintf(S, "%c%c%c          %c%c%c", SIGNAM(ruler1[i]),
  399.           SIGNAM(Mod12(ruler1[i]+6)));
  400.         fprintf(S, "          %c%c%c   %c%c%c", SIGNAM(exalt[i]),
  401.           SIGNAM(Mod12(exalt[i]+6)));
  402.       }
  403.       if (i <= C_HI)
  404.         fprintf(S, "  Minor House Cusp #%d", i-OBJECTS);
  405.       else
  406.         fprintf(S, "  Uranian #%d", i-U_LO+1);
  407.     }
  408.     printl();
  409.   }
  410.  
  411.   /* Now, if -U in effect, read in and display stars in specified order. */
  412.  
  413.   if (all || universe) {
  414.     Off = ProcessInput(TRUE);
  415.     ComputeStars(operation & DASHs ? 0.0 : -Off);
  416.     for (i = S_LO; i <= S_HI; i++) if (all | !ignore[i]) {
  417.       j = BASE+starname[i-BASE];
  418.       AnsiColor(objectansi[j]);
  419.       fprintf(S, "%2d %-12s", i, objectname[j]);
  420.       fprintf(S, "Star #%2d   ", i-BASE);
  421.       PrintZodiac(planet[j]);
  422.       fprintf(S, "    ");
  423.       PrintAltitude(planetalt[j]);
  424.       fprintf(S, " %5.2f\n", starbright[j-BASE]);
  425.     }
  426.   }
  427.   AnsiColor(DEFAULT);
  428. }
  429.  
  430.  
  431. /* Print out a list of all the aspects recognized by the program, and info  */
  432. /* about them: their names, index numbers, degree angles, present orbs, and */
  433. /* the description of their glyph. This gets displayed when the -A switch   */
  434. /* is invoked (without any argument).                                       */
  435.  
  436. void PrintAspects()
  437. {
  438.   int i;
  439.  
  440.   fprintf(S, "%s aspects:\nNo. Name         Abbrev. Angle    Orb", appname);
  441.   fprintf(S, "          Description of glyph\n\n");
  442.   for (i = 1; i <= ASPECTS; i++) {
  443.     AnsiColor(aspectansi[i]);
  444.     fprintf(S, "%2d %-15s(%s) %6.2f +/- %1.0f degrees - %s\n",
  445.       i, aspectname[i], aspectabbrev[i],
  446.       aspectangle[i], aspectorb[i], aspectglyph[i]);
  447.   }
  448.   AnsiColor(DEFAULT);
  449. }
  450.  
  451.  
  452. /* Print out a list of the 12 signs and houses of the zodiac, and their    */
  453. /* standard and traditional names, as done when the -H0 switch is invoked. */
  454.  
  455. void PrintSigns()
  456. {
  457.   int i;
  458.  
  459.   fprintf(S, "%s signs and houses:\n", appname);
  460.   fprintf(S, "Sign        English name      House Traditional name\n\n");
  461.   for (i = 1; i <= SIGNS; i++) {
  462.     AnsiColor(signansi(i));
  463.     fprintf(S, "%-12sthe %-14s%2d%s  House of %s\n",
  464.       signname[i], signenglish[i], i, post[i], housetradition[i]);
  465.   }
  466.   AnsiColor(DEFAULT);
  467. }
  468.  
  469.  
  470. /*
  471. ******************************************************************************
  472. ** File IO Routines.
  473. ******************************************************************************
  474. */
  475.  
  476. /* Print an error message signifying that a particular option in the        */
  477. /* defaults file is invalid. This is a subprocedure of InputDefaults below. */
  478.  
  479. void BadDef(option)
  480. char *option;
  481. {
  482.   char string[STRING];
  483.  
  484.   sprintf(string, "Bad default %s in %s.", option, DEFAULT_INFOFILE);
  485.   PrintError(string);
  486. }
  487.  
  488.  
  489. /* Read in a set of default program values used in the program, such as */
  490. /* present location, time zone, the system of houses to use, the number */
  491. /* of aspects and what orbs to use, and so on. These values are always  */
  492. /* read in at the beginning of program execution.                       */
  493.  
  494. /* The NEXTDEFAULT macro means to skip all comments in the file until we   */
  495. /* reach the beginning of the next set of data, delimited with a '=' sign. */
  496.  
  497. #define NEXTDEFAULT while(getc(data) != '=');
  498.  
  499. bool InputDefaults()
  500. {
  501.   FILE *data;
  502.   char name[STRING];
  503.   int i, j;
  504.  
  505.   filename = DEFAULT_INFOFILE;
  506.   data = OpenFile(filename, 0);  /* First lets open the info file. */
  507.   if (data == NULL)              /* If file not found anywhere, then forget */
  508.     return FALSE;                /* it and use the compile time defaults.   */
  509.  
  510.   NEXTDEFAULT; fscanf(data, "%s", name);
  511.   if (StringCmp(name, VERSION) != 0) {
  512.     sprintf(name, "%s: Bad information in default parameter file '%s'.",
  513.       appname, filename);
  514.     PrintWarning(name);
  515.     PrintWarning(
  516.       "Delete this file or obtain one compatible with current version.");
  517.     Terminate(_ERROR);
  518.     return FALSE;
  519.   }
  520.   NEXTDEFAULT; fscanf(data, "%lf", &defzone);        /* Time zone     */
  521.   if (!IsValidZon(defzone))
  522.     BadDef("Time Zone");
  523.   NEXTDEFAULT; fscanf(data, "%lf", &deflong);        /* Longitude     */
  524.   if (!IsValidLon(deflong))
  525.     BadDef("Longitude");
  526.   NEXTDEFAULT; fscanf(data, "%lf", &deflat);         /* Latitude      */
  527.   if (!IsValidLat(deflat))
  528.     BadDef("Latitude");
  529.   NEXTDEFAULT; fscanf(data, "%d",  &i);              /* Zodiac system */
  530.   if (i)
  531.     operation |= DASHs;
  532.   NEXTDEFAULT; fscanf(data, "%lf", &addfactor);      /* Zodiac offset */
  533.   if (!IsValidLon(addfactor))
  534.     BadDef("Add Factor");
  535.   NEXTDEFAULT; fscanf(data, "%d",  &aspects);        /* # of aspects  */
  536.   if (!IsValidAspect(aspects))
  537.     BadDef("Aspect Number");
  538.   NEXTDEFAULT; fscanf(data, "%d",  &housesystem);    /* House system   */
  539.   if (!IsValidSystem(housesystem))
  540.     BadDef("House System");
  541.   NEXTDEFAULT; fscanf(data, "%d",  &ansi);           /* Ansi text?     */
  542.   NEXTDEFAULT; fscanf(data, "%d",  &divisions);      /* For -d and -T  */
  543.   if (!IsValidDivision(divisions))
  544.     BadDef("Searching Divisions");
  545.   NEXTDEFAULT; fscanf(data, "%d",  &placalc);        /* Use ephemeris  */
  546.   NEXTDEFAULT; fscanf(data, "%d",  &seconds);        /* Zodiac seconds */
  547.   seconds = seconds != 0;
  548.   NEXTDEFAULT; fscanf(data, "%d",  &wheelrows);      /* For -w charts  */
  549.   if (!IsValidWheel(wheelrows))
  550.     BadDef("Wheel Rows");
  551.   NEXTDEFAULT; fscanf(data, "%d",  &screenwidth);    /* For -I charts  */
  552.   if (!IsValidScreen(screenwidth))
  553.     BadDef("Screen Width");
  554.   NEXTDEFAULT; fscanf(data, "%d",  &eurodate);       /* D/M/Y vs. M/D/Y?     */
  555.   NEXTDEFAULT; fscanf(data, "%d",  &eurotime);       /* 24hr vs. 12hr clock? */
  556.   NEXTDEFAULT; fscanf(data, "%d",  &smartcusp);      /* Logical -C displays? */
  557.   NEXTDEFAULT; fscanf(data, "%d",  &column80);       /* Clip text at col 80? */
  558.  
  559.   NEXTDEFAULT;
  560.   for (i = 1; i <= BASE; i++) {            /* Object restrictions         */
  561.     fscanf(data, "%d", &j);
  562.     ignore[i] = j > 0;
  563.   }
  564.   NEXTDEFAULT;
  565.   for (i = 1; i <= BASE; i++) {            /* Transit object restrictions */
  566.     fscanf(data, "%d", &j);
  567.     ignore2[i] = j > 0;
  568.   }
  569.   NEXTDEFAULT;
  570.   fscanf(data, "%d", &j); ignore[0]  = j > 0;    /* Restrict sign changes */
  571.   NEXTDEFAULT;
  572.   fscanf(data, "%d", &j); ignore2[0] = j > 0;    /* Restrict dir. changes */
  573.   NEXTDEFAULT;
  574.   for (i = 1; i <= ASPECTS; i++)           /* Orbs for aspects  */
  575.     fscanf(data, "%lf", &aspectorb[i]);
  576.   NEXTDEFAULT;
  577.   for (i = 1; i <= BASE; i++)              /* Orbs for planets  */
  578.     fscanf(data, "%lf", &planetorb[i]);
  579.   NEXTDEFAULT;
  580.   for (i = 1; i <= BASE; i++)              /* Extra planet orbs */
  581.     fscanf(data, "%lf", &planetadd[i]);
  582.   NEXTDEFAULT; fscanf(data, "%lf", &objectinf[BASE+1]);     /* Rules sign  */
  583.   NEXTDEFAULT; fscanf(data, "%lf", &objectinf[BASE+2]);     /* Exalts in   */
  584.   NEXTDEFAULT; fscanf(data, "%lf",  &houseinf[SIGNS+1]);    /* Rules house */
  585.   NEXTDEFAULT; fscanf(data, "%lf",  &houseinf[SIGNS+2]);    /* Exalts in   */
  586.   NEXTDEFAULT;
  587.   for (i = 1; i <= BASE; i++)
  588.     fscanf(data, "%lf", &objectinf[i]);    /* Influence of each object */
  589.   for (i = 1; i <= SIGNS; i++)
  590.     fscanf(data, "%lf", &houseinf[i]);     /* Influence of each house  */
  591.   for (i = 1; i <= ASPECTS; i++)
  592.     fscanf(data, "%lf", &aspectinf[i]);    /* Influence of each aspect */
  593.   NEXTDEFAULT;
  594.   for (i = 1; i <= BASE; i++)
  595.     fscanf(data, "%lf", &transitinf[i]);   /* Each object when transiting */
  596.  
  597.   /* Graphics defaults begin here. These are only read in with certain     */
  598.   /* compile options. They need to be read in last for file compatibility. */
  599.  
  600. #ifdef GRAPH
  601.   NEXTDEFAULT; fscanf(data, "%d", &chartx);       /* Horizontal graph size */
  602.   if (!IsValidGraphx(chartx))
  603.     BadDef("Horizontal Bitmap Size");
  604.   NEXTDEFAULT; fscanf(data, "%d", &charty);       /* Vertical graph size   */
  605.   if (!IsValidGraphx(chartx))
  606.     BadDef("Vertical Bitmap Size");
  607.  
  608.   /* Setting value to select alternate graphic glyphs for certain objects. */
  609.   NEXTDEFAULT; fscanf(data, "%d", &i);
  610.   if (i%10 == 1)
  611.     signdraw[_CAP] = "BH4RFR2ER3G3D2GDFR2EU2HL3G2DG";
  612.   if (i%100/10 == 1)
  613.     objectdraw[_URA] = "BD2D0BU6NG2NF2D4LGD2FR2EU2HL";
  614.   if (i%1000/100 == 1)
  615.     objectdraw[_PLU] = "BL3R5EU2HL5D8R5";
  616.  
  617.   NEXTDEFAULT; fscanf(data, "%d", &gridobjects);  /* Aspect grid cells     */
  618.   if (!IsValidGrid(gridobjects))
  619.     BadDef("Aspect Grid Cells");
  620.   NEXTDEFAULT;
  621.   do {
  622.     bitmapmode = getc(data);
  623.   } while (bitmapmode <= ' ');
  624.   if (!IsValidBmpmode(bitmapmode))                /* Bitmap file mode        */
  625.     BadDef("Bitmap File Mode");
  626.   NEXTDEFAULT; fscanf(data, "%d", &xfont);        /* Font simulation flag    */
  627.   NEXTDEFAULT; fscanf(data, "%d", &psinchz);      /* PostScript orientation  */
  628.   NEXTDEFAULT; fscanf(data, "%lf", &psinchx);     /* PS horizon. paper size  */
  629.   NEXTDEFAULT; fscanf(data, "%lf", &psinchy);     /* PS vertical paper size  */
  630.  
  631. #ifdef MSG
  632.   NEXTDEFAULT; fscanf(data, "%d", &hiresmode);    /* Normal graphics mode    */
  633.   if (!IsValidResmode(hiresmode))
  634.     BadDef("High Resolution Size");
  635.   NEXTDEFAULT; fscanf(data, "%d", &loresmode);    /* Animation graphics mode */
  636.   if (!IsValidResmode(loresmode))
  637.     BadDef("Low Resolution Size");
  638. #endif
  639. #endif /* GRAPH */
  640.   fclose(data);
  641.   return TRUE;
  642. }
  643.  
  644.  
  645. /* Take the current chart information, and write it out to the file   */
  646. /* as indicated by the -o switch. This is only executed at the end of */
  647. /* program execution if the -o switch is in effect.                   */
  648.  
  649. bool OutputData()
  650. {
  651.   char string[STRING];
  652.   FILE *data;
  653.   int i, j;
  654.   real k;
  655.  
  656.   data = fopen(filenameout, "w");    /* Create and open the file for output. */
  657.   if (data == NULL) {
  658.     sprintf(string, "File %s can not be created.", filenameout);
  659.     PrintError(string);
  660.     return FALSE;
  661.   }
  662.   if (!(operation & DASHo0)) {
  663.  
  664.     /* Write the chart information to the file. */
  665.  
  666.     if (Mon < 1) {
  667.       fclose(data);
  668.       PrintError("Can't output chart with no time/space to file.");
  669.       return FALSE;
  670.     }
  671.     fprintf(data, "%d\n%d\n%d\n%.2f\n%.2f\n%.2f\n%.2f\n",
  672.       Mon, Day, Yea, Tim, Zon, Lon, Lat);
  673.   } else {
  674.  
  675.     /* However, if the -o0 switch is in effect, then write the actual */
  676.     /* positions of the planets and houses to the file instead.       */
  677.  
  678.     for (i = 1; i <= BASE; i++) {
  679.       j = (int) planet[i];
  680.       fprintf(data, "%c%c%c: %2d %2d %10.7f\n", OBJNAM(i),
  681.         j%30, j/30+1, FRACT(planet[i])*60.0);                /* Position */
  682.       k = planetalt[i];
  683.       fprintf(data, "[%c]: %3d %12.8f\n",                    /* Altitude */
  684.         ret[i] >= 0.0 ? 'D' : 'R', (int)(Sgn(k)*
  685.         floor(dabs(k))), (k-(real)(int)k)*60.0);          /* Retrograde? */
  686.       if (i == OBJECTS) {
  687.         if (operation & DASHu)    /* Skip minor cusps to write uranians  */
  688.           i = C_HI;
  689.         else
  690.           i = total;
  691.       }
  692.     }
  693.     for (i = 1; i <= SIGNS/2; i++) {   /* Write first six cusp positions */ 
  694.       j = (int) house[i];
  695.       fprintf(data, "H_%c: %2d %2d %10.7f\n",
  696.         'a'+i-1, j%30, j/30+1, FRACT(house[i])*60.0);
  697.     }
  698.   }
  699.  
  700.   /* Now write any extra strings that were on the command line after the -o */
  701.   /* specification but before the next switch, to the file as comments.     */
  702.  
  703.   for (i = 1; i < extracount; i++) {
  704.     extralines++;
  705.     fprintf(data, "%s\n", extralines[1]);
  706.   }
  707.   fclose(data);
  708.   return TRUE;
  709. }
  710.  
  711.  
  712. /*
  713. ******************************************************************************
  714. ** Program Dispatch Procedures.
  715. ******************************************************************************
  716. */
  717.  
  718. /* Initialize an Ansi color array with the color to print each object in. */
  719.  
  720. void InitColors()
  721. {
  722.   int i;
  723.  
  724.   objectansi[0] = elemansi[_EAR];
  725.   for (i = 1; i <= 10; i++)
  726.     objectansi[i] = signansi(ruler1[i]);
  727.   for (i = 11; i <= 15; i++)
  728.     objectansi[i] = MAGENTA;
  729.   for (i = 16; i <= 20; i++)
  730.     objectansi[i] = DKCYAN;
  731.   objectansi[_MC] = elemansi[_EAR]; objectansi[_ASC] = elemansi[_FIR];
  732.   objectansi[21] = elemansi[_AIR]; objectansi[22] = elemansi[_WAT];
  733.   objectansi[23] = elemansi[_EAR]; objectansi[24] = elemansi[_AIR];
  734.   for (i = U_LO; i <= U_HI; i++)
  735.     objectansi[i] = PURPLE;
  736.   for (i = S_LO; i <= S_HI; i++)
  737.     objectansi[i] = starbright[i-BASE] < 1.0 ? ORANGE : MAROON;
  738. }
  739.  
  740.  
  741. /* This is the dispatch procedure for all the generic table information      */
  742. /* routines, such as those displaying the -H switch list, the list of signs, */
  743. /* objects, default interpretations, and so on not requiring a date or time. */
  744.  
  745. int PrintTables()
  746. {
  747.   if (andisplay < 2)
  748.     return FALSE;
  749.   if (andisplay & DASHHc) {
  750.     DisplayCredits();
  751.     if (andisplay - (andisplay & DASHHc*2-1))
  752.       printl2();
  753.   }
  754.   if (andisplay & DASHH) {
  755.     DisplaySwitches();
  756.     if (andisplay - (andisplay & DASHH*2-1))
  757.       printl2();
  758.   }
  759.   if (andisplay & DASHH0) {
  760.     PrintSigns();
  761.     if (andisplay - (andisplay & DASHH0*2-1))
  762.       printl2();
  763.   }
  764.   if (andisplay & DASHO) {
  765.     PrintObjects((andisplay & DASHO0) > 0);
  766.     if (andisplay - (andisplay & DASHO*2-1))
  767.       printl2();
  768.   }
  769.   if (andisplay & DASHA) {
  770.     PrintAspects();
  771.     if (andisplay - (andisplay & DASHA*2-1))
  772.       printl2();
  773.   }
  774. #ifdef INTERPRET
  775.   if (andisplay & DASHI0) {
  776.     InterpretGeneral();
  777.     InterpretAspectGeneral();
  778.   }
  779. #endif
  780.  
  781.   /* If we also already have enough information to generate a chart,    */
  782.   /* then go on and do so, else exit. (So things like "-O -i file" will */
  783.   /* work, but things like just "-H" will print and exit right away.)   */
  784.  
  785.   if (autom)
  786.     printl2();
  787.   return !autom;
  788. }
  789.  
  790.  
  791. /* This is the dispatch procedure for the entire program. After all the   */
  792. /* command switches have been processed, this routine is called to        */
  793. /* actually call the various routines to generate and display the charts. */
  794.  
  795. void Action()
  796. {
  797.   char string[STRING];
  798.   int i;
  799.  
  800.   AnsiColor(DEFAULT);
  801.   InitColors();
  802.  
  803.   /* First let's adjust the restriction status of the minor cusps, uranians, */
  804.   /* and fixed stars based on whether -C, -u, and -U switches are in effect. */
  805.  
  806.   if (!(operation & DASHC))
  807.     for (i = C_LO; i <= C_HI; i++)
  808.       ignore[i] = ignore2[i] = TRUE;
  809.   if (!(operation & DASHu))
  810.     for (i = U_LO; i <= U_HI; i++)
  811.       ignore[i] = ignore2[i] = TRUE;
  812.   if (!universe)
  813.     for (i = S_LO; i <= S_HI; i++)
  814.       ignore[i] = ignore2[i] = TRUE;
  815.  
  816.   /* If the -os switch is in effect, open a file and set a global to */
  817.   /* internally 'redirect' all screen output to.                     */
  818.  
  819.   if (filenamescreen) {
  820.     S = fopen(filenamescreen, "w");
  821.     if (S == NULL) {
  822.       sprintf(string, "File %s can not be created.", filenamescreen);
  823.       PrintError(string);
  824.       S = stdout;
  825.     }
  826.   } else
  827.     S = stdout;
  828.  
  829.   if (PrintTables())    /* Print out any generic tables specified.        */
  830.     return;             /* If nothing else to do, we can exit right away. */
  831.  
  832.   /* If -+ or -- switches in effect, then add the specified delta value to */
  833.   /* the date and use that as a new date before proceeding to make chart.  */
  834.  
  835.   if (Delta != 0) {
  836.     JD = (real)MdyToJulian(MM, DD+Delta, YY);
  837.     JulianToMdy(JD, &MM, &DD, &YY);
  838.   }
  839.  
  840.   /* Here we either do a normal chart or some kind of relationship chart. */
  841.  
  842.   if (!relation) {
  843.     if (!autom && !InputData("tty"))  /* If chart info not in mem yet, then */
  844.       return;                         /* prompt the user for the time, etc. */
  845.     SetMain(MM, DD, YY, TT, ZZ, OO, AA);
  846.     CastChart(TRUE);
  847.   } else
  848.     CastRelation(TRUE);
  849.   SetSave(Mon, Day, Yea, Tim, Zon, Lon, Lat);
  850.  
  851. #ifdef GRAPH
  852.   if (operation & DASHX)    /* If any of the X window switches in effect, */
  853.     XAction();              /* then go make a graphics chart...           */
  854.   else
  855. #endif
  856.     PrintChart(prog);       /* Otherwise print chart on text screen.      */
  857.  
  858.   if (operation & DASHo)    /* If -o switch in effect, then write */
  859.     OutputData();           /* the chart information to a file.   */
  860.  
  861.   if (S != stdout)    /* If we were internally directing chart display to a */
  862.     fclose(S);        /* file as with the -os switch, close it here.        */
  863. }
  864.  
  865.  
  866. /* Reset a few variables to their default values they have upon startup of */
  867. /* the program. We don't reset all variables, just the most volatile ones. */
  868. /* This is called when in the -Q loop to reset things like which charts to */
  869. /* display, but leave setups such as object restrictions and orbs alone.   */
  870.  
  871. void InitVariables()
  872. {
  873.   filenamescreen = NULL;
  874.   relation = Delta = 0;
  875.   todisplay = exdisplay = andisplay = operation = 0x0;
  876.   interpret = progress = autom = FALSE;
  877. }
  878.  
  879.  
  880. /* This routine is called by the main program to actually prompt the user    */
  881. /* for command switches and parameters, entered in the same format as they   */
  882. /* would be on a Unix command line. This is only executed for certain non-   */
  883. /* Unix systems which don't allow passing of a command line to the program,  */
  884. /* or when -Q is in effect. The result of this routine is passed back to the */
  885. /* main program which then processes it just like in a Unix system.          */
  886.  
  887. #define MAXSWITCHES 32
  888.  
  889. int InputSwitches(line, argv)
  890. char *line, *argv[MAXSWITCHES];
  891. {
  892.   FILE *data;
  893.   int argc = 1, i = 0, j = 1;
  894.   char *c = line;
  895.  
  896.   data = S; S = stdout;
  897.   AnsiColor(WHITE);
  898.   fprintf(S, "** %s version %s ", appname, VERSION);
  899.   fprintf(S, "(See '%cHc' switch for copyrights and credits.) **\n", DASH);
  900.   AnsiColor(DEFAULT);
  901.   fprintf(S, "Enter all parameter options below. ");
  902.   fprintf(S, "(Enter '%cH' for help. Enter '.' to exit.)\n", DASH);
  903.   S = data;
  904.   InputString("Input command line", line);
  905.   argv[0] = APPNAME;
  906.  
  907.   /* Split the entered line up into its individual switch strings. */
  908.   while (*c) {
  909.     if (*c == ' ') {
  910.       if (j)
  911.         ;           /* Skip over the current run of spaces between strings. */
  912.       else {
  913.         *c = 0;     /* First space after a string, end it here. */
  914.         j = TRUE;
  915.       }
  916.     } else {
  917.       if (j) {
  918.         argv[argc++] = c;    /* First char after spaces, begin it here. */
  919.         j = FALSE;
  920.       } else
  921.         ;                    /* Skip over the current string. */
  922.     }
  923.     c++;
  924.   }
  925.   argv[argc] = NULL;    /* Set last string in switch array to Null. */
  926.   printl();
  927.   return argc;
  928. }
  929.  
  930.  
  931. /*
  932. ******************************************************************************
  933. ** Main Program.
  934. ******************************************************************************
  935. */
  936.  
  937. /* Process a command line switch passed to the program. Read each entry in */
  938. /* the argument list and set all the program modes and charts to display.  */
  939.  
  940. bool ProcessSwitches(argc, argv)
  941. int argc;
  942. char **argv;
  943. {
  944.   int pos, i, j;
  945.   real k;
  946.   char string[STRING], cpos, *c;
  947.  
  948.   argc--; argv++;
  949.   while (argc) {
  950.     pos  = 1 + (argv[0][0] == '-' || argv[0][0] == '/');  /* Leading dash? */
  951.     cpos = argv[0][pos];
  952.     switch (argv[0][pos-1]) {
  953.  
  954.     case 'H':
  955.       if (cpos == 'c')
  956.         andisplay ^= DASHHc;
  957.       else if (cpos == '0')
  958.         andisplay ^= DASHH0;
  959.       else
  960.         andisplay ^= DASHH;
  961.       break;
  962.  
  963.     case 'O':
  964.       if (cpos == '0')
  965.         andisplay ^= DASHO0;
  966.       andisplay ^= DASHO;
  967.       break;
  968.  
  969.     case 'Q':
  970.       if (cpos == '0')
  971.         operation ^= DASHQ0;
  972.       operation ^= DASHQ;
  973.       break;
  974.  
  975.     /* Switches which determine the type of chart to display: */
  976.  
  977.     case 'v':
  978.       if (cpos == '0')
  979.         exdisplay ^= DASHv0;
  980.       todisplay ^= DASHv;
  981.       break;
  982.  
  983.     case 'w':
  984.       if (cpos == '0')
  985.         exdisplay ^= DASHw0;
  986.       if (argc > 1 && (i = atoi(argv[1]))) {
  987.         argc--; argv++;
  988.         if (!IsValidWheel(i)) {
  989.           BadVal("w", i);
  990.           return FALSE;
  991.         }
  992.         wheelrows = i;
  993.       }
  994.       todisplay ^= DASHw;
  995.       break;
  996.  
  997.     case 'g':
  998.       if (cpos == '0')
  999.         exdisplay ^= DASHg0;
  1000.       else if (cpos == 'a') {
  1001.         exdisplay ^= DASHga;
  1002.         if (argv[0][pos+1] == '0')
  1003.           exdisplay ^= DASHg0;
  1004.       }
  1005. #ifdef X11
  1006.       else if (cpos == 'e') {
  1007.         if (argc <= 1) {
  1008.           TooFew("geometry");
  1009.           return FALSE;
  1010.         }
  1011.         chartx = atoi(argv[1]);
  1012.         if (argc > 2 && (charty = atoi(argv[2]))) {
  1013.           argc--; argv++;
  1014.         } else
  1015.           charty = chartx;
  1016.         if (!IsValidGraphx(chartx)) {
  1017.           BadVal("geometry", chartx);
  1018.           return FALSE;
  1019.         }
  1020.         if (!IsValidGraphy(charty)) {
  1021.           BadVal("geometry", charty);
  1022.           return FALSE;
  1023.         }
  1024.         argc--; argv++;
  1025.         break;
  1026.       }
  1027. #endif
  1028.       todisplay ^= DASHg;
  1029.       break;
  1030.  
  1031.     case 'm':
  1032.       if (cpos == '0') {
  1033.         exdisplay ^= DASHm0;
  1034.         if (argv[0][pos+1] == 'a')
  1035.           exdisplay ^= DASHga;
  1036.       } else if (cpos == 'a')
  1037.         exdisplay ^= DASHm0 | DASHga;
  1038.       todisplay ^= DASHm;
  1039.       break;
  1040.  
  1041.     case 'Z':
  1042.       if (cpos == '0')
  1043.         exdisplay ^= DASHZ0;
  1044.       else if (cpos == 'd')
  1045.         exdisplay ^= DASHZd;
  1046.       todisplay ^= DASHZ;
  1047.       break;
  1048.  
  1049.     case 'S':
  1050.       todisplay ^= DASHS;
  1051.       break;
  1052.  
  1053.     case 'j':
  1054.       if (cpos == '0')
  1055.         exdisplay ^= DASHj0;
  1056.       todisplay ^= DASHj;
  1057.       break;
  1058.  
  1059.     case 'L':
  1060.       if (cpos == '0')
  1061.         exdisplay ^= DASHL0;
  1062.       if (argc > 1 && (i = atoi(argv[1]))) {
  1063.         argc--; argv++;
  1064.         if (i < 1 || 160%i > 0) {
  1065.           BadVal("L", i);
  1066.           return FALSE;
  1067.         }
  1068.         graphstep = i;
  1069.       }
  1070.       todisplay ^= DASHL;
  1071.       break;
  1072.  
  1073.     case 'K':
  1074.       if (cpos == 'y')
  1075.         exdisplay ^= DASHKy;
  1076.       todisplay ^= DASHK;
  1077.       break;
  1078.  
  1079.     case 'd':
  1080.       if (cpos == 'p') {
  1081.         i = (argv[0][pos+1] == 'y');
  1082.         j = (argv[0][pos+i+1] == 'n');
  1083.         if (!j && argc <= 2-i) {
  1084.           TooFew("dp");
  1085.           return FALSE;
  1086.         }
  1087.         prog = TRUE;
  1088.         exdisplay |= DASHdm;
  1089.         Zon2 = defzone; Lon2 = deflong; Lat2 = deflat;
  1090.         if (j)
  1091.           GetTimeNow(&Mon2, &Day2, &Yea2, &Tim2, Zon2);
  1092.         if (i) {
  1093.           Mon2 = 0;
  1094.           if (!j)
  1095.             Yea2 = atoi(argv[1]);
  1096.         } else {
  1097.           if (!j) {
  1098.             Mon2 = atoi(argv[1]);
  1099.             Yea2 = atoi(argv[2]);
  1100.             if (!IsValidMon(Mon2)) {
  1101.               BadVal("dp", Mon2);
  1102.               return FALSE;
  1103.             }
  1104.           }
  1105.         }
  1106.         if (!IsValidYea(Yea2)) {
  1107.           BadVal("dp", Yea2);
  1108.           return FALSE;
  1109.         }
  1110.         if (!j) {
  1111.           argc -= 2-i; argv += 2-i;
  1112.         }
  1113.       } else if (cpos == 'm' || cpos == 'y') {
  1114.         Mon2 = (cpos == 'm');
  1115.         exdisplay ^= DASHdm;
  1116.       }
  1117. #ifdef X11
  1118.       else if (cpos == 'i') {    /* -display switch for X */
  1119.         if (argc <= 1) {
  1120.           TooFew("display");
  1121.           return FALSE;
  1122.         }
  1123.         dispname = argv[1];
  1124.         argc--; argv++;
  1125.         break;
  1126.       }
  1127. #endif
  1128.       else if (argc > 1 && (i = atoi(argv[1]))) {
  1129.         if (!IsValidDivision(i)) {
  1130.           BadVal("d", i);
  1131.           return FALSE;
  1132.         }
  1133.         divisions = i;
  1134.         argc--; argv++;
  1135.       }
  1136.       todisplay ^= DASHd;
  1137.       break;
  1138.  
  1139.     case 'D':
  1140.       todisplay ^= DASHD;
  1141.       break;
  1142.  
  1143.     case 'E':
  1144.       if (cpos == 'y')
  1145.         exdisplay ^= DASHEy;
  1146.       todisplay ^= DASHE;
  1147.       break;
  1148.  
  1149.     case 'e':
  1150.       todisplay ^= DASHe;
  1151.       exdisplay ^= DASHg0 | DASHj0 | DASHL0;
  1152.       break;
  1153.  
  1154.     case 't':
  1155.       todisplay ^= DASHt;
  1156.       Zon2 = defzone; Lon2 = deflong; Lat2 = deflat;
  1157.       if (cpos == 'p') {
  1158.         prog = TRUE;
  1159.         cpos = argv[0][++pos];
  1160.       }
  1161.       if (i = (cpos == 'y') + 2*(cpos == 'Y'))
  1162.         cpos = argv[0][++pos];
  1163. #ifdef TIME
  1164.       if (cpos == 'n') {
  1165.         GetTimeNow(&Mon2, &Day2, &Yea2, &Tim2, Zon2);
  1166.         if (i == 1)
  1167.           Mon2 = 0;
  1168.         else if (i > 1) {
  1169.           Mon2 = -1; Day2 = atoi(argv[1]);
  1170.         }
  1171.         break;
  1172.       }
  1173. #endif
  1174.       if (argc <= 2 - (i & 1)) {
  1175.         TooFew("t");
  1176.         return FALSE;
  1177.       }
  1178.       if (i) {
  1179.         if (i == 1)
  1180.           Mon2 = 0;
  1181.         else {
  1182.           Mon2 = -1; Day2 = atoi(argv[2]);
  1183.         }
  1184.       } else {
  1185.         Mon2 = atoi(argv[1]);
  1186.         if (!IsValidMon(Mon2)) {
  1187.           BadVal("t", Mon2);
  1188.           return FALSE;
  1189.         }
  1190.       }
  1191.       Yea2 = atoi(argv[2 - (i > 0)]);
  1192.       argc -= 2 - (i & 1); argv += 2 - (i & 1);
  1193.       break;
  1194.  
  1195.     case 'T':
  1196.       todisplay ^= DASHT;
  1197.       Zon2 = defzone; Lon2 = deflong; Lat2 = deflat;
  1198.       if (cpos == 'p') {
  1199.         prog = TRUE;
  1200.         cpos = argv[0][++pos];
  1201.       }
  1202. #ifdef TIME
  1203.       if (cpos == 'n') {
  1204.         GetTimeNow(&Mon2, &Day2, &Yea2, &Tim2, Zon2);
  1205.         break;
  1206.       }
  1207. #endif
  1208.       if (argc <= 3) {
  1209.         TooFew("T");
  1210.         return FALSE;
  1211.       }
  1212.       Mon2 = atoi(argv[1]);
  1213.       Day2 = atoi(argv[2]);
  1214.       Yea2 = atoi(argv[3]);
  1215.       if (!IsValidMon(Mon2)) {
  1216.         BadVal("T", Mon2);
  1217.         return FALSE;
  1218.       } else if (!IsValidDay(Day2, Mon2, Yea2)) {
  1219.         BadVal("T", Day2);
  1220.         return FALSE;
  1221.       } else if (!IsValidYea(Yea2)) {
  1222.         BadVal("T", Yea2);
  1223.         return FALSE;
  1224.       }
  1225.       argc -= 3; argv += 3;
  1226.       break;
  1227.  
  1228. #ifdef INTERPRET
  1229.     case 'I':
  1230.       if (argc > 1 && (i = atoi(argv[1]))) {
  1231.         argc--; argv++;
  1232.         if (!IsValidScreen(i)) {
  1233.           BadVal("I", i);
  1234.           return FALSE;
  1235.         }
  1236.         screenwidth = i;
  1237.       }
  1238.       if (cpos == '0') {
  1239.         andisplay ^= DASHI0;
  1240.         break;
  1241.       }
  1242.       interpret = !interpret;
  1243.       break;
  1244. #endif
  1245.  
  1246.     /* Switches which affect how the chart parameters are obtained: */
  1247.  
  1248. #ifdef TIME
  1249.     case 'n':
  1250.       InputData("now");
  1251.       if (cpos == 'd')
  1252.         TT = 0.0;
  1253.       else if (cpos == 'm') {
  1254.         DD = 1; TT = 0.0;
  1255.       } else if (cpos == 'y') {
  1256.         MM = DD = 1; TT = 0.0;
  1257.       }
  1258.       break;
  1259. #endif
  1260.  
  1261.     case 'z':
  1262.       if (argc <= 1 || (atoi(argv[1]) == 0 && argv[1][0] != '0'))
  1263.         defzone -= 1.0;
  1264.       else {
  1265.         defzone = atof(argv[1]);
  1266.         if (!IsValidZon(defzone)) {
  1267.           BadVal2("z", defzone);
  1268.           return FALSE;
  1269.         }
  1270.         argc--; argv++;
  1271.       }
  1272.       break;
  1273.  
  1274.     case 'l':
  1275.       if (argc <= 2) {
  1276.         TooFew("l");
  1277.         return FALSE;
  1278.       }
  1279.       deflong = atof(argv[1]);
  1280.       deflat  = atof(argv[2]);
  1281.       if (!IsValidLon(deflong)) {
  1282.         BadVal2("l", deflong);
  1283.         return FALSE;
  1284.       } else if (!IsValidLat(deflat)) {
  1285.         BadVal2("l", deflat);
  1286.         return FALSE;
  1287.       }
  1288.       argc -= 2; argv += 2;
  1289.       break;
  1290.  
  1291.     case 'q':
  1292.       i = (cpos == 'y' || cpos == 'j') + 2*(cpos == 'm') + 3*(cpos == 'd') +
  1293.         4*(cpos == '\0') + 7*(cpos == 'a');
  1294.       if (argc <= i) {
  1295.         TooFew("q");
  1296.         return FALSE;
  1297.       }
  1298.       autom = TRUE;
  1299.       if (cpos == 'j') {
  1300.         JD = atof(argv[1])+ROUND;
  1301.         TT = FRACT(JD);
  1302.         JulianToMdy(JD-TT, &MM, &DD, &YY);
  1303.         TT = DegToDec(TT * 24.0);
  1304.         ZZ = 0.0; OO = deflong; AA = deflat;
  1305.       } else {
  1306.         MM = i > 1 ? atoi(argv[1]) : 1;
  1307.         DD = i > 2 ? atoi(argv[2]) : 1;
  1308.         YY = atoi(argv[3-(i<3)-(i<2)]);
  1309.         TT = i > 3 ? atof(argv[4]) : (i < 3 ? 0.0 : 12.0);
  1310.         ZZ = i > 6 ? atof(argv[5]) : defzone;
  1311.         OO = i > 6 ? atof(argv[6]) : deflong;
  1312.         AA = i > 6 ? atof(argv[7]) : deflat;
  1313.         if (!IsValidMon(MM)) {
  1314.           BadVal("q", MM);
  1315.           return FALSE;
  1316.         } else if (!IsValidDay(DD, MM, YY)) {
  1317.           BadVal("q", DD);
  1318.           return FALSE;
  1319.         } else if (!IsValidYea(YY)) {
  1320.           BadVal("q", YY);
  1321.           return FALSE;
  1322.         } else if (!IsValidTim(TT)) {
  1323.           BadVal2("q", TT);
  1324.           return FALSE;
  1325.         } else if (!IsValidZon(ZZ)) {
  1326.           BadVal2("a", ZZ);
  1327.           return FALSE;
  1328.         } else if (!IsValidLon(OO)) {
  1329.           BadVal2("a", OO);
  1330.           return FALSE;
  1331.         } else if (!IsValidLat(AA)) {
  1332.           BadVal2("a", AA);
  1333.           return FALSE;
  1334.         }
  1335.       }
  1336.       argc -= i; argv += i;
  1337.       break;
  1338.  
  1339.     case 'i':
  1340.       if (argc <= 1) {
  1341.         TooFew("i");
  1342.         return FALSE;
  1343.       }
  1344.       if (!InputData(argv[1]))
  1345.         return FALSE;
  1346.       argc--; argv++;
  1347.       break;
  1348.  
  1349.     case 'o':
  1350.       if (argc <= 1) {
  1351.         TooFew("o");
  1352.         return FALSE;
  1353.       }
  1354.       if (cpos == 's') {
  1355.         filenamescreen = argv[1];
  1356.         argc--; argv++;
  1357.         break;
  1358.       } else if (cpos == '0')
  1359.         operation ^= DASHo0;
  1360.       operation ^= DASHo;
  1361.       filenameout = argv[1];
  1362.       extralines = argv;
  1363.       do {
  1364.         argc--; argv++;
  1365.         extracount++;
  1366.       } while (argc > 1 && argv[1][0] != '-' && argv[1][0] != '/');
  1367.       break;
  1368.  
  1369.     /* Switches which affect what information is used in a chart: */
  1370.  
  1371.     case 'R':
  1372.       if (cpos == 'T') {
  1373.         c = (char *)ignore2;
  1374.         cpos = argv[0][++pos];
  1375.       } else
  1376.         c = (char *)ignore;
  1377.       if (cpos == '0')
  1378.         for (i = 0; i <= total; i++)
  1379.           c[i] = TRUE;
  1380.       else if (cpos == '1') {
  1381.         for (i = 0; i <= total; i++)
  1382.           c[i] = FALSE;
  1383.         operation |= DASHC | DASHu;
  1384.         universe = TRUE;
  1385.       } else if (cpos == 'C')
  1386.         for (i = C_LO; i <= C_HI; i++)
  1387.           c[i] = !c[i];
  1388.       else if (cpos == 'u')
  1389.         for (i = U_LO; i <= U_HI; i++)
  1390.           c[i] = !c[i];
  1391.       else if (cpos == 'U')
  1392.         for (i = S_LO; i <= S_HI; i++)
  1393.           c[i] = !c[i];
  1394.       else if (argc <= 1 || (!atoi(argv[1]))) {
  1395.         for (i = 11; i <= 15; i++)
  1396.           c[i] = !c[i];
  1397.         c[_FOR] = !c[_FOR]; c[_VTX] = !c[_VTX];
  1398.       }
  1399.       while (argc > 1 && (i = atoi(argv[1])))
  1400.         if (!IsItem(i)) {
  1401.           BadVal("R", i);
  1402.           return FALSE;
  1403.         } else {
  1404.           c[i] = !c[i];
  1405.           argc--; argv++;
  1406.         }
  1407.       break;
  1408.  
  1409.     case 'C':
  1410.       operation ^= DASHC;
  1411.       break;
  1412.  
  1413.     case 'u':
  1414.       operation ^= DASHu;
  1415.       break;
  1416.  
  1417.     case 'U':
  1418.       if (cpos == 'n' || cpos == 'b' || cpos == 'z' || cpos == 'l')
  1419.         universe = cpos;
  1420.       else
  1421.         universe = !universe;
  1422.       break;
  1423.  
  1424.     case 'A':
  1425.       if (argc <= 1 || atoi(argv[1]) == 0) {
  1426.         andisplay ^= DASHA;
  1427.         break;
  1428.       }
  1429.       if (cpos != 'o' && cpos != 'm' && cpos != 'd' && cpos != 'a') {
  1430.         i = atoi(argv[1]);
  1431.         if (!IsValidAspect(i)) {
  1432.           BadVal("A", i);
  1433.           return FALSE;
  1434.         }
  1435.         aspects = i;
  1436.         argc--; argv++;
  1437.       } else {
  1438.         if (argc <= 2) {
  1439.           TooFew("A");
  1440.           return FALSE;
  1441.         }
  1442.         i = atoi(argv[1]);
  1443.         if (i < 1 || i > (cpos == 'o' || cpos == 'a' ? ASPECTS : BASE)) {
  1444.           BadVal("A", i);
  1445.           return FALSE;
  1446.         }
  1447.         k = atof(argv[2]);
  1448.         if (k < -DEGREES || k > DEGREES) {
  1449.           BadVal2("A", k);
  1450.           return FALSE;
  1451.         }
  1452.         if (cpos == 'o')
  1453.           aspectorb[i] = k;
  1454.         else if (cpos == 'm')
  1455.           planetorb[i] = k;
  1456.         else if (cpos == 'd')
  1457.           planetadd[i] = k;
  1458.         else
  1459.           aspectangle[i] = k;
  1460.         argc -= 2; argv += 2;
  1461.       }
  1462.       break;
  1463.  
  1464.     /* Switches which affect how a chart is computed: */
  1465.  
  1466.     case 'b':
  1467.       if (cpos == '0')
  1468.         seconds = !seconds;
  1469.       placalc = !placalc;
  1470.       break;
  1471.  
  1472.     case 'c':
  1473.       if (argc <= 1) {
  1474.         TooFew("c");
  1475.         return FALSE;
  1476.       }
  1477.       i = atoi(argv[1]);
  1478.       if (!IsValidSystem(i)) {
  1479.         BadVal("c", i);
  1480.         return FALSE;
  1481.       }
  1482.       housesystem = i;
  1483.       argc--; argv++;
  1484.       break;
  1485.  
  1486.     case 's':
  1487.       if (argc > 1 && (k = atof(argv[1])) != 0.0) {
  1488.         argc--; argv++;
  1489.         addfactor = k;
  1490.       }
  1491.       if (cpos != '0')
  1492.         operation ^= DASHs;
  1493.       else
  1494.         operation ^= DASHs0;
  1495.       break;
  1496.  
  1497.     case 'h':
  1498.       if (argc > 1 && (i = atoi(argv[1]))) {
  1499.         argc--; argv++;
  1500.       } else
  1501.         i = 1;
  1502.       if (i < 0 || i == _MOO || !IsObject(i) || i > U_HI) {
  1503.         BadVal("h", i);
  1504.         return FALSE;
  1505.       }
  1506.       centerplanet = i;
  1507.       c = objectname[0];
  1508.       objectname[0] = objectname[centerplanet];
  1509.       objectname[centerplanet] = c;
  1510.       if (centerplanet < _MOO)
  1511.         centerplanet = 1-centerplanet;
  1512.       break;
  1513.  
  1514.     case 'p':
  1515.       if (cpos == '0') {
  1516.         operation |= DASHp0;
  1517.         cpos = (argv[0][++pos]);
  1518.       }
  1519.       progress = TRUE;
  1520. #ifdef TIME
  1521.       if (cpos == 'n') {
  1522.         GetTimeNow(&Mon, &Day, &Yea, &Tim, defzone);
  1523.         Jdp = (real)MdyToJulian(Mon, Day, Yea) + Tim / 24.0;
  1524.         break;
  1525.       }
  1526. #endif
  1527.       if (cpos == 'd') {
  1528.         if (argc <= 1) {
  1529.           TooFew("pd");
  1530.           return FALSE;
  1531.         }
  1532.         progday = atof(argv[1]);
  1533.         if (progday == 0.0) {
  1534.           BadVal2("pd", progday);
  1535.           return FALSE;
  1536.         }
  1537.         argc--; argv++;
  1538.         break;
  1539.       }
  1540.       if (argc <= 3) {
  1541.         TooFew("p");
  1542.         return FALSE;
  1543.       }
  1544.       Mon = atoi(argv[1]);
  1545.       Day = atoi(argv[2]);
  1546.       Yea = atoi(argv[3]);
  1547.       if (!IsValidMon(Mon)) {
  1548.         BadVal("p", Mon);
  1549.         return FALSE;
  1550.       } else if (!IsValidDay(Day, Mon, Yea)) {
  1551.         BadVal("p", Day);
  1552.         return FALSE;
  1553.       } else if (!IsValidYea(Yea)) {
  1554.         BadVal("p", Yea);
  1555.         return FALSE;
  1556.       }
  1557.       Jdp = (real)MdyToJulian(Mon, Day, Yea) + defzone / 24.0;
  1558.       argc -= 3; argv += 3;
  1559.       break;
  1560.  
  1561.     case 'x':
  1562.       if (argc <= 1) {
  1563.         TooFew("x");
  1564.         return FALSE;
  1565.       }
  1566.       i = atoi(argv[1]);
  1567.       if (i < 1 || i > DEGREES) {
  1568.         BadVal("x", i);
  1569.         return FALSE;
  1570.       }
  1571.       multiplyfactor = i;
  1572.       argc--; argv++;
  1573.       break;
  1574.  
  1575.     case '1':
  1576.       if (argc > 1 && (i = atoi(argv[1]))) {
  1577.         argc--; argv++;
  1578.       } else
  1579.         i = _SUN;
  1580.       if (!IsItem(i)) {
  1581.         BadVal("1", i);
  1582.         return FALSE;
  1583.       }
  1584.       onasc = i;
  1585.       break;
  1586.  
  1587.     case '2':
  1588.       if (argc > 1 && (i = atoi(argv[1]))) {
  1589.         argc--; argv++;
  1590.       } else
  1591.         i = _SUN;
  1592.       if (!IsItem(i)) {
  1593.         BadVal("2", i);
  1594.         return FALSE;
  1595.       }
  1596.       onasc = -i;
  1597.       break;
  1598.  
  1599.     case '3':
  1600.       operation ^= DASH3;
  1601.       break;
  1602.  
  1603.     case 'f':
  1604.       operation ^= DASHf;
  1605.       break;
  1606.  
  1607.     case 'G':
  1608.       operation ^= DASHG;
  1609.       break;
  1610.  
  1611.     case 'F':
  1612.       if (argc <= 3) {
  1613.         TooFew("F");
  1614.         return FALSE;
  1615.       }
  1616.       i = atoi(argv[1]);
  1617.       if (!IsItem(i)) {
  1618.         BadVal("F", i);
  1619.         return FALSE;
  1620.       }
  1621.       force[i] = (atof(argv[2])-1.0)*30.0+DecToDeg(atof(argv[3]));
  1622.       if (force[i] < 0.0 || force[i] >= DEGREES) {
  1623.         BadVal2("F", force[i]);
  1624.         return FALSE;
  1625.       } else
  1626.         force[i] += DEGREES;
  1627.       argc -= 3; argv += 3;
  1628.       break;
  1629.  
  1630.     case '+':
  1631.       if (argc > 1 && (i = atoi(argv[1])) != 0) {
  1632.         argc--; argv++;
  1633.       } else
  1634.         i = 1;
  1635.       Delta += i * (cpos == 'y' ? 365 : (cpos == 'm' ? 30 : 1));
  1636.       break;
  1637.  
  1638.     case '-': case '\0':
  1639.       if (argc > 1 && (i = atoi(argv[1])) != 0) {
  1640.         argc--; argv++;
  1641.       } else
  1642.         i = 1;
  1643.       Delta -= i * (cpos == 'y' ? 365 : (cpos == 'm' ? 30 : 1));
  1644.       break;
  1645.  
  1646.     /* Switches for relationship and comparison charts: */
  1647.  
  1648.     case 'r':
  1649.       i = 2 + 2*(cpos >= 'a' && argv[0][pos+1] == '0');
  1650.       if (argc <= i) {
  1651.         TooFew("r");
  1652.         return FALSE;
  1653.       }
  1654.       if (cpos == 'c')
  1655.         relation = DASHrc;
  1656.       else if (cpos == 'm')
  1657.         relation = DASHrm;
  1658.       else if (cpos == 'd')
  1659.         relation = DASHrd;
  1660. #ifdef BIORHYTHM
  1661.       else if (cpos == 'b')
  1662.         relation = DASHrb;
  1663. #endif
  1664.       else if (cpos == '0')
  1665.         relation = DASHr0;
  1666.       else if (cpos == 'p')
  1667.         relation = DASHrp;
  1668.       else
  1669.         relation = DASHr;
  1670.       filename = argv[1]; filename2 = argv[2];
  1671.       if (i > 2) {
  1672.         ratio1 = atoi(argv[3]);
  1673.         ratio2 = atoi(argv[4]);
  1674.         if (ratio1 == ratio2)
  1675.           ratio1 = ratio2 = 1;
  1676.       }
  1677.       argc -= i; argv += i;
  1678.       break;
  1679.  
  1680. #ifdef TIME
  1681.     case 'y':
  1682.       if (argc <= 1) {
  1683.         TooFew("y");
  1684.         return FALSE;
  1685.       }
  1686.       if (cpos == 'd')
  1687.         relation = DASHrd;
  1688. #ifdef BIORHYTHM
  1689.       else if (cpos == 'b')
  1690.         relation = DASHrb;
  1691. #endif
  1692.       else if (cpos == 'p')
  1693.         relation = DASHrp;
  1694.       else
  1695.         relation = DASHr0;
  1696.       filename = argv[1]; filename2 = "now";
  1697.       argc--; argv++;
  1698.       break;
  1699. #endif
  1700.  
  1701.     /* Switches to access graphics options: */
  1702.  
  1703.     case 'k':
  1704.       ansi = !ansi;
  1705.       break;
  1706.  
  1707. #ifdef MSG
  1708.     case 'V':
  1709.       if (argc <= 1) {
  1710.         TooFew("V");
  1711.         return FALSE;
  1712.       }
  1713.       i = atoi(argv[1]);
  1714.       if (!IsValidTextrows(i)) {
  1715.         BadVal("V", i);
  1716.         return FALSE;
  1717.       }
  1718.       textrows = i;
  1719.       argc--; argv++;
  1720.       break;
  1721. #endif
  1722.  
  1723. #ifdef GRAPH
  1724.     case 'X':
  1725.       i = XProcessSwitches(argc, argv, pos);
  1726.       if (i < 0)
  1727.         return FALSE;
  1728.       operation |= DASHX;
  1729.       argc -= i; argv += i;
  1730.       break;
  1731. #endif
  1732.  
  1733.     case '.':               /* "-." is usually used to exit the -Q loop. */
  1734.       Terminate(_FORCE);
  1735.  
  1736.     case 'B':          /* For no useful reason, -B will sound a beep. */
  1737.       printc(BELL);
  1738.       break;
  1739.  
  1740.     default:
  1741.       sprintf(string, "Unknown switch '%s'.", argv[0]);
  1742.       PrintError(string);
  1743.       return FALSE;
  1744.     }
  1745.     argc--; argv++;
  1746.   }
  1747.   return TRUE;
  1748. }
  1749.  
  1750.  
  1751. #ifndef NOMAIN
  1752. /* The main program, the starting point for Astrolog, follows. This routine */
  1753. /* basically consists of a loop, inside which we read a command line, and   */
  1754. /* go process it, before actually calling a routine to do the neat stuff.   */
  1755.  
  1756. #ifdef SWITCHES
  1757. void main(argc, argv)
  1758. int argc;
  1759. char **argv;
  1760. {
  1761. #else
  1762. void main()
  1763. {
  1764.   int argc;
  1765.   char **argv;
  1766. #endif
  1767.   char commandline[256];
  1768.   char *pointers[MAXSWITCHES];
  1769.  
  1770.   InputDefaults();    /* Read in info from the astrolog.dat file. */
  1771. Begin:
  1772. #ifdef MSG
  1773.   if (textrows > 0) {
  1774.     _settextrows(textrows);
  1775.     textrows = -textrows;
  1776.   }
  1777. #endif
  1778.   if (noswitches) {                                 /* Go prompt for    */
  1779.     argc = InputSwitches(commandline, pointers);    /* switches if we   */
  1780.     argv = pointers;                                /* don't have them. */
  1781.   }
  1782.   progname = argv[0];
  1783.   if (ProcessSwitches(argc, argv)) {
  1784.     if (!noswitches && (operation & DASHQ0)) {
  1785.       noswitches = TRUE;
  1786.       goto Begin;
  1787.     }
  1788. #ifdef MSG
  1789.     if (textrows > 0) {
  1790.       _settextrows(textrows);
  1791.       textrows = -textrows;
  1792.     }
  1793. #endif
  1794.     Action();
  1795.   }
  1796.   if (operation & DASHQ) {    /* If -Q in effect, loop back and get switch */
  1797.     printl2();                /* information for another chart to display. */
  1798.     InitVariables();
  1799.     operation |= DASHQ;
  1800.     noswitches = TRUE;
  1801.     goto Begin;
  1802.   }
  1803.   Terminate(_OK);    /* The only standard place to exit Astrolog is here. */
  1804. }
  1805. #endif /* NOMAIN */
  1806.  
  1807. /* driver.c */
  1808.