/*                                                               -*- C -*-
** Astrolog (Version 4.40) File: astrolog.c
**
** IMPORTANT NOTICE: The graphics database and chart display routines
** used in this program are Copyright (C) 1991-1995 by Walter D. Pullen
** (astara@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 1/29/1995.
*/

/* $VER: $Id: astrolog.c,v 1.2 1995/07/02 22:20:03 tf Exp $ */

#include "astrolog.h"

/*
******************************************************************************
** Program Dispatch Procedures.
******************************************************************************
*/

/* Initialize the Ansi color arrays with the color to print each object in. */

void InitColors()
{
  int i;

  kObjA[0] = kElemA[eEar];
  for (i = 1; i <= 10; i++)
    kObjA[i] = kSignA(ruler1[i]);
  for (i = 11; i <= 15; i++)
    kObjA[i] = kMainA[8];
  for (i = 16; i <= 20; i++)
    kObjA[i] = kMainA[6];
  for (i = 1; i <= cSign; i++)
    kObjA[cuspLo+i-1] = kSignA(i);
  for (i = uranLo; i <= uranHi; i++)
    kObjA[i] = kRainbowA[7];
  for (i = starLo; i <= starHi; i++)
    kObjA[i] = starbright[i-oNorm] < 1.0 ? kRainbowA[2] : kMainA[4];
}


/* This is the dispatch procedure for the entire program. After all the   */
/* command switches have been processed, this routine is called to        */
/* actually call the various routines to generate and display the charts. */

void Action()
{
  char sz[cchSzDef];
  int i;

  is.fSzPersist = fFalse;
  is.cchRow = 0;
  AnsiColor(kDefault);
  InitColors();

  if (fSouthNode)
  {
    szObjName[oSou] = "S.Node";

#ifdef INTERPRET
    szMindPart[oSou] = "karmic past, and area of experience but little growth";
#endif
    ruler1[oSou] = sLeo;
  }
  if (us.fParallel) {
    szAspectAbbrev[aCon] = "Par"; szAspectAbbrev[aOpp] = "CPr";
  }

  /* First let's adjust the restriction status of the cusps, uranians, and */
  /* fixed stars based on whether -C, -u, and -U switches are in effect.   */

  if (!us.fCusp)
    for (i = cuspLo; i <= cuspHi; i++)
      ignore[i] = ignore2[i] = fTrue;

  if (!us.fUranian)
    for (i = uranLo; i <= uranHi; i++)
      ignore[i] = ignore2[i] = fTrue;

  if (!us.nStar)
    for (i = starLo; i <= starHi; i++)
      ignore[i] = ignore2[i] = fTrue;

  /* If the -os switch is in effect, open a file and set a global to */
  /* internally 'redirect' all screen output to.                     */

  if (is.szFileScreen) 
  {
    S = fopen(is.szFileScreen, "w");
    if (S == NULL)  
    {
      sprintf(sz, "File %s can not be created.", is.szFileScreen);
      PrintError(sz);
      S = stdout;
    }
  } 
  else S = stdout;

  if (FPrintTables())    /* Print out any generic tables specified.        */
    return;              /* If nothing else to do, we can exit right away. */

  if (is.fMult) 
  {
    PrintL2();
    is.fMult = fFalse;
  }

  /* If -+ or -- switches in effect, then add the specified delta value to */
  /* the date and use that as a new date before proceeding to make chart.  */

  if (us.dayDelta != 0) 
  {
    is.JD = (real)MdyToJulian(MM, DD+us.dayDelta, YY);
    JulianToMdy(is.JD, &MM, &DD, &YY);
  }

  /* Here we either do a normal chart or some kind of relationship chart. */

  if (!us.nRel) 
  {
    /* If chart info not in memory yet, then prompt the user for it. */
    if (!is.fHaveInfo && !FInputData(szTtyCore))
      return;

    CastChart(fTrue);
    ciMain = ciCore;
  }
  else CastRelation(fTrue);

  ciSave = ciMain;

#ifdef GRAPH
  if (us.fGraphics)         /* If any of the X window switches in effect, */
    FActionX();             /* then go make a graphics chart...           */
  else
#endif
    PrintChart(is.fProgress);    /* Otherwise print chart on text screen. */

  if (us.fWriteFile)        /* If -o switch in effect, then write */
    FOutputData();          /* the chart information to a file.   */

  if (S != stdout)    /* If we were internally directing chart display to a */
    fclose(S);        /* file as with the -os switch, close it here.        */

  if (grid)
    DeallocateFar(grid);
}


/* Reset a few variables to their default values they have upon startup of */
/* the program. We don't reset all variables, just the most volatile ones. */
/* This is called when in the -Q loop to reset things like which charts to */
/* display, but leave setups such as object restrictions and orbs alone.   */

void InitVariables()
{
  us.fInterpret = us.fProgress = is.fHaveInfo = is.fMult = fFalse;
  us.nRel = us.dayDelta = 0;
  is.szFileScreen = NULL;
  ClearB((lpbyte)&us.fListing, (int)((lpbyte)&us.fLoop - (lpbyte)&us.fListing));
}


/*
******************************************************************************
** Command Switch Procedures.
******************************************************************************
*/

/* Given a string representing a command line (e.g. a macro string), go    */
/* parse it into its various switches and parameters, then go process them */
/* and change program settings. Basically a wrapper for other functions.   */

bool FProcessCommandLine(szLine)
char *szLine;
{
  char szCommandLine[cchSzMax], *rgsz[MAXSWITCHES];
  int argc, cb, fT;

  if (szLine == NULL)
    return fTrue;

  if (Mon != -1)
    ciCore = ciMain;

  cb = CchSz(szLine)+1;
  CopyRgb((byte *)szLine, (byte *)szCommandLine, cb);
  argc = NParseCommandLine(szCommandLine, rgsz);
  fT = FProcessSwitches(argc, rgsz);
  ciMain = ciCore;
  return fT;
}


/* Given string representing a command line, convert it to an "argv" format */
/* of an array of strings, one for each switch or parameter, i.e. exactly   */
/* like the format of the command line as given when the program starts.    */

int NParseCommandLine(szLine, argv)
char *szLine;
char **argv;
{
  int argc = 1, fSpace = fTrue, fQuote = fFalse;
  char *pch = szLine;

  /* Split the entered line up into its individual switch strings. */
  while (*pch >= ' ' || *pch == chTab) 
  {
    if (*pch == ' ' || *pch == chTab) 
    {
      if (fSpace)
        /* Skip over the current run of spaces between strings. */
        ;
      else 
      {
        /* First space after a string, end parameter here. */
        if (!fQuote) 
        {
          *pch = chNull;
          fSpace = fTrue;
        }
      }
    }

    else /* not space or tab */
    {
      if (fSpace)
      {
        /* First character after run of spaces, begin parameter here. */
        if (argc >= MAXSWITCHES-1)
        {
          PrintWarning("Too many items - rest of line ignored.");
          break;
        }
        fQuote = (*pch == '"');
        argv[argc++] = pch + fQuote;
        fSpace = fFalse;
      } 
      else /* Skip over the current string. */
        if (fQuote && *pch == '"')
        {
          *pch = chNull;
          fSpace = fTrue;
        }
    }
    pch++;
  }
  argv[0] = szAppNameCore;
  argv[argc] = NULL;         /* Set last string in switch array to Null. */
  return argc;
}


/* This routine is called by the main program to interactively prompt the  */
/* user for command switches and parameters, entered in the same format as */
/* they would be on a command line. This needs to be called with certain   */
/* systems which don't allow passing of a command line to the program,     */
/* or when -Q is in effect. The result of this routine is returned to the  */
/* main program which then processes it as done with a real command line.  */

int NPromptSwitches(line, argv)
char *line, *argv[MAXSWITCHES];
{
  FILE *data;
  char sz[cchSzDef];

  data = S; S = stdout;
  is.cchRow = 0;

  AnsiColor(kWhite);
  sprintf(sz, "** %s version %s ", szAppName, szVersionCore); PrintSz(sz);
  sprintf(sz, "(See '%cHc' switch for copyrights and credits.) **\n", chSwitch); PrintSz(sz);

  AnsiColor(kDefault);
  PrintSz("Enter all parameter options below. ");
  sprintf(sz, "(Enter '%cH' for help. Enter '.' to exit.)\n", chSwitch);
  PrintSz(sz);
  S = data;
  InputString("Input command line", line);
  PrintL();
  return NParseCommandLine(line, argv);
}


/* This subprocedure is like FProcessSwitches() below, except that we only */
/* process one switch, which we know to be one of the obscure -Y types.    */

int NProcessSwitchesRare(argc, argv, pos, fOr, fAnd, fNot)
int argc, pos;
bool fOr, fAnd, fNot;
char **argv;
{
  int darg = 0, i, j, k;
  real r;
  char ch1, ch2;
  OE oe;
  lpbyte lpb;
  int FAR *lpn;
  lpreal lpr;
#ifdef INTERPRET
  char *sz;
#endif

  ch1 = argv[0][pos+1]; ch2 = argv[0][pos+2];

  switch (argv[0][pos]) {
  case chNull:
    SwitchF(us.fSwitchRare);
    break;

  case 'n':
    SwitchF(us.fTrueNode);
    break;

  case 'd':
    SwitchF(us.fEuroDate);
    break;

  case 't':
    SwitchF(us.fEuroTime);
    break;

  case 'C':
    SwitchF(us.fSmartCusp);
    break;

  case '8':
    SwitchF(us.fClip80);
    break;

  case 'Q':
    if (argc <= 1) 
    {
      ErrorArgc("YQ");
      return tcError;
    }

    i = atoi(argv[1]);

    if (i < 0)
    {
      ErrorValN("YQ", i);
      return tcError;
    }
    us.nScrollRow = i;
    darg++;
    break;

  case 'o':
    SwitchF(us.fWriteOld);
    break;

#ifdef ARABIC
  case 'P':
    if (argc <= 1) 
    {
      ErrorArgc("YP");
      return tcError;
    }
    i = atoi(argv[1]);

    if (!FBetween(i, -1, 1)) 
    {
      ErrorValN("YP", i);
      return tcError;
    }
    us.nArabicNight = i;
    darg++;
    break;
#endif

  case 'E':
    if (argc <= 17) 
    {
      ErrorArgc("YE");
      return tcError;
    }
    i = NParseSz(argv[1], pmObject);

    if (!FHelio(i))
    {
      ErrorValN("YE", i);
      return tcError;
    }

    oe.sma = atof(argv[2]);
    oe.ec0 = atof(argv[3]);  oe.ec1 = atof(argv[4]);  oe.ec2 = atof(argv[5]);
    oe.in0 = atof(argv[6]);  oe.in1 = atof(argv[7]);  oe.in2 = atof(argv[8]);
    oe.ap0 = atof(argv[9]);  oe.ap1 = atof(argv[10]); oe.ap2 = atof(argv[11]);
    oe.an0 = atof(argv[12]); oe.an1 = atof(argv[13]); oe.an2 = atof(argv[14]);
    oe.ma0 = atof(argv[15]); oe.ma1 = atof(argv[16]); oe.ma2 = atof(argv[17]);

    rgoe[IoeFromObj(i)] = oe;
    darg += 17;
    break;

  case 'R':
    if (argc <= 2) 
    {
      ErrorArgc("YR");
      return tcError;
    }

    i = NParseSz(argv[1], pmObject); j = NParseSz(argv[2], pmObject);

    if (ch1 == '0') 
    {
      ignore[0]  = i != 0;
      ignore2[0] = j != 0;
      darg += 2;
      break;
    }

    if (!FItem(i))
    {
      ErrorValN("YR", i);
      return tcError;
    }

    if (!FItem(j) || j < i) 
    {
      ErrorValN("YR", j);
      return tcError;
    }

    if (argc <= 3+j-i) 
    {
      ErrorArgc("YR");
      return tcError;
    }

    lpb = (lpbyte)((ch1 == 'T') ? ignore2 : ignore);

    for (k = i; k <= j; k++)
      lpb[k] = atoi(argv[3+k-i]) != 0;

    darg += 3+j-i;
    break;

  case 'A':
    if (argc <= 2)
    {
      ErrorArgc("YA");
      return tcError;
    }

    k = (ch1 == 'm' || ch1 == 'd') ? pmObject : pmAspect;
    i = NParseSz(argv[1], k); j = NParseSz(argv[2], k);
    k = (ch1 == 'm' || ch1 == 'd') ? cObj : cAspect;

    if (!FBetween(i, 1, k))
    {
      ErrorValN("YA", i);
      return tcError;
    }

    if (!FBetween(j, 1, k) || j < i)
    {
      ErrorValN("YA", j);
      return tcError;
    }

    if (argc <= 3+j-i)
    {
      ErrorArgc("YA");
      return tcError;
    }

    lpr = (lpreal)(ch1 == 'm' ? planetorb : (ch1 == 'd' ? planetadd : aspectorb));

    for (k = i; k <= j; k++)
      lpr[k] = atof(argv[3+k-i]);

    darg += 3+j-i;
    break;

  case 'j':
    if (argc <= 2 + 2*(ch1 == '0')) 
    {
      ErrorArgc("Yj");
      return tcError;
    }
    if (ch1 == '0') 
    {
      objectinf[oNorm+1] = atof(argv[1]);
      objectinf[oNorm+2] = atof(argv[2]);
      houseinf[cSign+1]  = atof(argv[3]);
      houseinf[cSign+2]  = atof(argv[4]);
      darg += 4;
      break;
    }
    k = ch1 == 'C' ? pmSign : (ch1 == 'A' ? pmAspect : pmObject);
    i = NParseSz(argv[1], k); j = NParseSz(argv[2], k);
    k = ch1 == 'C' ? cSign : (ch1 == 'A' ? cAspect : cObj);
    if (!FBetween(i, 1, k)) {
      ErrorValN("Yj", i);
      return tcError;
    }
    if (!FBetween(j, 1, k) || j < i) 
    {
      ErrorValN("Yj", j);
      return tcError;
    }
    if (argc <= 3+j-i) 
    {
      ErrorArgc("Yj");
      return tcError;
    }

    lpr = (lpreal)(ch1 == 'C' ? houseinf : (ch1 == 'A' ? aspectinf :
                                           (ch1 == 'T' ? transitinf : objectinf)) );
    for (k = i; k <= j; k++)
      lpr[k] = atof(argv[3+k-i]);

    darg += 3+j-i;
    break;

#ifdef INTERPRET
  case 'I':
    if (argc <= 2) 
    {
      ErrorArgc("YI");
      return tcError;
    }
    i = NParseSz(argv[1], ch1 == 'A' ? pmAspect : (ch1 == chNull ? pmObject : pmSign));
    j = ch1 == 'A' ? cAspect : (ch1 == chNull ? oNorm : cSign);

    if (!FBetween(i, 1, j)) 
    {
      ErrorValN("YI", i);
      return tcError;
    }

    if (ch1 == 'A' && ch2 == '0')
      ch1 = '0';
    sz = SzPersist(argv[2]);

    switch (ch1) {
    case 'A':    szInteract[i]  = sz; break;
    case '0':    szTherefore[i] = sz; break;
    case chNull: szMindPart[i]  = sz; break;
    case 'C':    szLifeArea[i]  = sz; break;
    case 'v':    szDesire[i]    = sz; break;
    default:     szDesc[i]      = sz;
    }
    darg += 2;
    break;
#endif

  case 'k':
    if (argc <= 2 + 2*(ch1 == 'C')) 
    {
      ErrorArgc("Yk");
      return tcError;
    }

    if (ch1 == 'C') 
    {
      kElemA[eFir] = NParseSz(argv[1], pmColor) & 15;
      kElemA[eEar] = NParseSz(argv[2], pmColor) & 15;
      kElemA[eAir] = NParseSz(argv[3], pmColor) & 15;
      kElemA[eWat] = NParseSz(argv[4], pmColor) & 15;
      darg += 4;
      break;
    }
    k = ch1 == 'A' ? pmAspect : 0;
    i = NParseSz(argv[1], k); j = NParseSz(argv[2], k);
    k = ch1 == 'A' ? cAspect : (ch1 == '0' ? 7 : 8);

    if (!FBetween(i, ch1 != chNull, k)) {
      ErrorValN("Yk", i);
      return tcError;
    }

    if (!FBetween(j, ch1 != chNull, k) || j < i) {
      ErrorValN("Yk", j);
      return tcError;
    }

    if (argc <= 3+j-i) 
    {
      ErrorArgc("Yk");
      return tcError;
    }

    lpn = (int FAR *)(ch1 == 'A' ? kAspA : (ch1 == '0' ? kRainbowA : kMainA));

    for (k = i; k <= j; k++)
      lpn[k] = NParseSz(argv[3+k-i], pmColor) & 15;

    darg += 3+j-i;
    break;

  case 'F':
    if (argc <= 8) 
    {
      ErrorArgc("YF");
      return tcError;
    }
    i = NParseSz(argv[1], pmObject);

    if (!FItem(i))
    {
      ErrorValN("YF", i);
      return tcError;
    }

    r = Mod((real)(atoi(argv[2]) + (NParseSz(argv[3], pmSign)-1)*30) + atof(argv[4])/60.0);

    if (!FCusp(i))
      planet[i] = r;
    else
    {
      j = Mod12(i-(cuspLo-1)+6);
      if (FBetween(i, cuspLo-1+4, cuspLo-1+9)) {
        house[i-(cuspLo-1)] = r;
        house[j] = Mod(r + rDegHalf);
      } else {
        planet[i] = r;
        planet[cuspLo-1+j] = Mod(r + rDegHalf);
      }
    }

    j = atoi(argv[5]);
    r = (j < 0 ? -1.0 : 1.0)*((real)abs(j) + atof(argv[6])/60.0);
    planetalt[i] = Mod((r + rDegQuad) * 2.0) / 2.0 - rDegQuad;
    ret[i] = RFromD(atof(argv[7]));
    if (i <= oNorm)
      SphToRec(atof(argv[8]), planet[i], planetalt[i], &spacex[i], &spacey[i], &spacez[i]);
    MM = -1;
    darg += 8;
    break;

#ifdef GRAPH
  case 'X':
    return NProcessSwitchesRareX(argc, argv, pos+1);
#endif

  default:
    ErrorSwitch(argv[0]);
    return tcError;
  }
  return darg;    /* Return the value to be added to argc. */
}


/* Process a command switch line passed to the program. Read each entry in */
/* the argument list and set all the program modes and charts to display.  */

bool FProcessSwitches(argc, argv)
int argc;
char **argv;
{
  int ich, i, j;
  bool fNot, fOr, fAnd;
  real rT;
  char ch1, ch2, *pch;

  argc--; argv++;

  while (argc)
  {
    ch1 = argv[0][0];
    fNot = fOr = fAnd = fFalse;
    switch (ch1) {
    case '=': fOr  = fTrue; break;
    case '_': fAnd = fTrue; break;
    case ':':               break;
    default:  fNot = fTrue; break;
    }

    ich = 1 + ( FChSwitch(argv[0][0]) ? 1:0 );    /* Leading dash? */
    ch1 = argv[0][ich];
    ch2 = ch1 == chNull ? chNull : argv[0][ich+1];

    /*printf("parsing `%c'... in \"%s\"\n",argv[0][ich-1],argv[0]);*/

    switch (argv[0][ich-1]) {

    case 'H':
      if (ch1 == 'c')
        SwitchF(us.fCredit);
      else if (ch1 == 'Y')
        SwitchF(us.fSwitchRare);
#ifdef ISG
      else if (ch1 == 'X')
        SwitchF(us.fKeyGraph);
#endif
      else if (ch1 == 'C')
        SwitchF(us.fSign);
      else if (ch1 == 'O')
        SwitchF(us.fObject);
      else if (ch1 == 'A')
        SwitchF(us.fAspect);
      else if (ch1 == 'F')
        SwitchF(us.fConstel);
      else if (ch1 == 'S')
        SwitchF(us.fOrbitData);
      else if (ch1 == 'I')
        SwitchF(us.fMeaning);
      else if (ch1 == 'e') 
      {
        SwitchF(us.fCredit); SwitchF(us.fSwitch); SwitchF(us.fSwitchRare);
        SwitchF(us.fKeyGraph); SwitchF(us.fSign); SwitchF(us.fObject);
        SwitchF(us.fAspect); SwitchF(us.fConstel); SwitchF(us.fOrbitData);
        SwitchF(us.fMeaning);
      } else
        SwitchF(us.fSwitch);
      break;

    case 'Q':
      if (ch1 == '0')
        SwitchF(us.fLoopInit);
      SwitchF(us.fLoop);
      break;

    case 'M':
      i = (ch1 == '0');
      if (argc <= 1+i) {
        ErrorArgc("M");
        return fFalse;
      }
      j = atoi(argv[1]);
      if (!FValidMacro(j)) {
        ErrorValN("M", j);
        return fFalse;
      }
      j--;
      if (i)
        szMacro[j] = SzPersist(argv[2]);
      else
        FProcessCommandLine(szMacro[j]);
      argc -= 1+i; argv += 1+i;
      break;

    case 'Y':
      i = NProcessSwitchesRare(argc, argv, ich, fOr, fAnd, fNot);
      if (i < 0)
        return fFalse;
      argc -= i; argv += i;
      break;

    /* Switches which determine the type of chart to display: */

    case 'v':
      if (ch1 == '0')
        SwitchF(us.fVelocity);
      SwitchF(us.fListing);
      break;

    case 'w':
      if (ch1 == '0')
        SwitchF(us.fWheelReverse);
      if (argc > 1 && (i = atoi(argv[1]))) {
        argc--; argv++;
        if (!FValidWheel(i)) {
          ErrorValN("w", i);
          return fFalse;
        }
        us.nWheelRows = i;
      }
      SwitchF(us.fWheel);
      break;

    case 'g':
      if (ch1 == '0' || ch2 == '0')
        SwitchF(us.fGridConfig);
      if (ch1 == 'a')
        SwitchF(us.fAppSep);
      else if (ch1 == 'p')
        SwitchF(us.fParallel);
#ifdef X11
      else if (ch1 == 'e') 
      {
        if (argc <= 1) 
        {
          ErrorArgc("geometry");
          return fFalse;
        }
        gs.xWin = atoi(argv[1]);
        if (argc > 2 && (gs.yWin = atoi(argv[2]))) 
        {
          argc--; argv++;
        } 
        else
          gs.yWin = gs.xWin;

        if (!FValidGraphx(gs.xWin)) 
        {
          ErrorValN("geometry", gs.xWin);
          return fFalse;
        }
        if (!FValidGraphy(gs.yWin)) 
        {
          ErrorValN("geometry", gs.yWin);
          return fFalse;
        }
        argc--; argv++;
        break;
      }
#endif
      SwitchF(us.fGrid);
      break;

    case 'a':
      SwitchF(us.fAspList);
      if (ch1 == '0') 
      {
        SwitchF(us.fAspSummary);
        ch1 = ch2;
      }
      if (ch1 == 'a')
        SwitchF(us.fAppSep);
      else if (ch1 == 'p')
        SwitchF(us.fParallel);
      break;

    case 'm':
      if (ch1 == '0')
        SwitchF(us.fMidSummary);
      SwitchF(us.fMidpoint);
      break;

    case 'Z':
      if (ch1 == '0')
        SwitchF(us.fPrimeVert);
      else if (ch1 == 'd')
        SwitchF(us.fHorizonSearch);
      SwitchF(us.fHorizon);
      break;

    case 'S':
      SwitchF(us.fOrbit);
      break;

    case 'j':
      if (ch1 == '0')
        SwitchF(us.fInfluenceSign);
      SwitchF(us.fInfluence);
      break;

    case 'L':
      if (ch1 == '0')
        SwitchF(us.fLatitudeCross);
      if (argc > 1 && (i = atoi(argv[1]))) 
      {
        argc--; argv++;
        if (i < 1 || 160%i > 0)
        {
          ErrorValN("L", i);
          return fFalse;
        }
        us.nAstroGraphStep = i;
      }
      SwitchF(us.fAstroGraph);
      break;

    case 'K':
      if (ch1 == 'y')
        SwitchF(us.fCalendarYear);
      SwitchF(us.fCalendar);
      break;

    case 'd':
      if (ch1 == 'p') 
      {
        i = (ch2 == 'y') + 2*(ch2 == 'Y');
#ifdef TIME
        j = i < 2 && (argv[0][ich+i+1] == 'n');
#else
        j = fFalse;
#endif
        if (!j && argc <= 2-(i&1)) {
          ErrorArgc("dp");
          return fFalse;
        }
        is.fProgress = us.fInDayMonth = fTrue;
        Dst2 = us.dstDef; Zon2 = us.zonDef;
        Lon2 = us.lonDef; Lat2 = us.latDef;
#ifdef TIME
        if (j)
          GetTimeNow(&Mon2, &Day2, &Yea2, &Tim2, Zon2-Dst2);
#endif
        if (i) {
          Mon2 = 0;
          if (!j)
            Yea2 = NParseSz(argv[1], pmYea);
          us.nEphemYears = i == 2 ? atoi(argv[2]) : 1;
        } else {
          if (!j) {
            Mon2 = NParseSz(argv[1], pmMon);
            Yea2 = NParseSz(argv[2], pmYea);
            if (!FValidMon(Mon2)) {
              ErrorValN("dp", Mon2);
              return fFalse;
            }
          }
        }
        if (!FValidYea(Yea2)) 
        {
          ErrorValN("dp", Yea2);
          return fFalse;
        }
        if (!j) {
          i = 2-(i&1);
          argc -= i; argv += i;
        }
      } 
      else if (ch1 == 'm' || ch1 == 'y' || ch1 == 'Y') 
      {
        if (ch1 == 'y')
          us.nEphemYears = 1;
        else if (ch1 == 'Y') {
          if (argc <= 1) {
            ErrorArgc("dY");
            return fFalse;
          }
          i = atoi(argv[1]);
          if (i < 1) {
            ErrorValN("dY", i);
            return fFalse;
          }
          us.nEphemYears = i;
        }
        SwitchF(us.fInDayMonth);
        Mon2 = (ch1 == 'm');
      }
#ifdef X11
      else if (ch1 == 'i') {    /* -display switch for X */
        if (argc <= 1) {
          ErrorArgc("display");
          return fFalse;
        }
        gs.szDisplay = SzPersist(argv[1]);
        argc--; argv++;
        break;
      }
#endif
      else if (argc > 1 && (i = atoi(argv[1]))) {
        if (!FValidDivision(i)) {
          ErrorValN("d", i);
          return fFalse;
        }
        us.nDivision = i;
        argc--; argv++;
      }
      SwitchF(us.fInDay);
      break;

    case 'D':
      SwitchF(us.fInDayInf);
      break;

    case 'E':
      if (ch1 == 'Y' && argc <= 1) {
        ErrorArgc("E");
        return fFalse;
      }
      SwitchF(us.fEphemeris);
      if (ch1 == 'y')
        us.nEphemYears = us.fEphemeris ? 1 : 0;
      else if (ch1 == 'Y') {
        i = atoi(argv[1]);
        if (i < 1) {
          ErrorValN("EY", i);
          return fFalse;
        }
        us.nEphemYears = i;
      }
      break;

    case 'e':
      SwitchF(us.fListing); SwitchF(us.fWheel);
      SwitchF(us.fGrid); SwitchF(us.fAspList); SwitchF(us.fMidpoint);
      SwitchF(us.fHorizon); SwitchF(us.fOrbit);
      SwitchF(us.fAstroGraph); SwitchF(us.fInfluence); SwitchF(us.fCalendar);
      SwitchF(us.fInDay); SwitchF(us.fInDayInf);
      SwitchF(us.fEphemeris);
      SwitchF(us.fGridConfig); SwitchF(us.fInfluenceSign);
      SwitchF(us.fLatitudeCross);
      break;

    case 't':
      SwitchF(us.fTransit);
      Zon2 = us.zonDef; Dst2 = us.dstDef; Lon2 = us.lonDef; Lat2 = us.latDef;
      if (ch1 == 'p') {
        is.fProgress = fTrue;
        ch1 = argv[0][++ich];
      }
      if( (i = (ch1 == 'y') + 2*(ch1 == 'Y')) )
        ch1 = argv[0][++ich];
#ifdef TIME
      if (ch1 == 'n') {
        GetTimeNow(&Mon2, &Day2, &Yea2, &Tim2, Zon2-Dst2);
        if (i == 1)
          Mon2 = 0;
        else if (i > 1) {
          Mon2 = -1; Day2 = NParseSz(argv[1], pmDay);
        }
        break;
      }
#endif
      if (argc <= 2 - (i & 1)) {
        ErrorArgc("t");
        return fFalse;
      }
      if (i) {
        if (i == 1)
          Mon2 = 0;
        else {
          Mon2 = -1; Day2 = NParseSz(argv[2], pmDay);
        }
      } else {
        Mon2 = NParseSz(argv[1], pmMon);
        if (!FValidMon(Mon2)) {
          ErrorValN("t", Mon2);
          return fFalse;
        }
      }
      Yea2 = NParseSz(argv[2 - (i > 0)], pmYea);
      argc -= 2 - (i & 1); argv += 2 - (i & 1);
      break;

    case 'T':
      SwitchF(us.fTransitInf);
      Zon2 = us.zonDef; Dst2 = us.dstDef; Lon2 = us.lonDef; Lat2 = us.latDef;
      if (ch1 == 'p') {
        is.fProgress = fTrue;
        ch1 = argv[0][++ich];
      }
#ifdef TIME
      if (ch1 == 'n') {
        GetTimeNow(&Mon2, &Day2, &Yea2, &Tim2, Zon2-Dst2);
        break;
      }
#endif
      if (argc <= 3) {
        ErrorArgc("T");
        return fFalse;
      }
      Mon2 = NParseSz(argv[1], pmMon);
      Day2 = NParseSz(argv[2], pmDay);
      Yea2 = NParseSz(argv[3], pmYea);

      if (!FValidMon(Mon2)) {
        ErrorValN("T", Mon2);
        return fFalse;
      } else if (!FValidDay(Day2, Mon2, Yea2)) {
        ErrorValN("T", Day2);
        return fFalse;
      } else if (!FValidYea(Yea2)) {
        ErrorValN("T", Yea2);
        return fFalse;
      }
      argc -= 3; argv += 3;
      break;

#ifdef ARABIC
    case 'P':
      if (argc > 1 && (i = atoi(argv[1]))) {
        argc--; argv++;
        if (!FValidPart(i)) {
          ErrorValN("P", i);
          return fFalse;
        }
        us.nArabicParts = i;
      }
      if (ch1 == 'z' || ch1 == 'n' || ch1 == 'f') {
        us.nArabic = ch1;
        ch1 = ch2;
      } else
        SwitchF(us.nArabic);
      if (ch1 == '0')
        SwitchF(us.fArabicFlip);
      break;
#endif

#ifdef INTERPRET
    case 'I':
      if (argc > 1 && (i = atoi(argv[1]))) {
        argc--; argv++;
        if (!FValidScreen(i)) {
          ErrorValN("I", i);
          return fFalse;
        }
        us.nScreenWidth = i;
      }
      SwitchF(us.fInterpret);
      break;
#endif

    /* Switches which affect how the chart parameters are obtained: */

#ifdef TIME
    case 'n':
      FInputData(szNowCore);
      if (ch1 == 'd')
        TT = 0.0;
      else if (ch1 == 'm') {
        DD = 1; TT = 0.0;
      } else if (ch1 == 'y') {
        MM = DD = 1; TT = 0.0;
      }
      break;
#endif

    case 'z':
      if (ch1 == '0') {
        if (argc <= 1 || RParseSz(argv[1], pmZon) == rLarge) {
          i = us.dstDef != 0.0;
          SwitchF(i);
          SS = us.dstDef = i ? 1.0 : 0.0;
        } else {
          SS = us.dstDef = RParseSz(argv[1], pmZon);
          if (!FValidDst(us.dstDef)) {
            ErrorValR("z0", us.dstDef);
            return fFalse;
          }
          argc--; argv++;
        }
        break;
      } else if (ch1 == 'l') {
        if (argc <= 2) {
          ErrorArgc("zl");
          return fFalse;
        }
        OO = us.lonDef = RParseSz(argv[1], pmLon);
        AA = us.latDef = RParseSz(argv[2], pmLat);
        if (!FValidLon(us.lonDef)) {
          ErrorValR("zl", us.lonDef);
          return fFalse;
        } else if (!FValidLat(us.latDef)) {
          ErrorValR("zl", us.latDef);
          return fFalse;
        }
        argc -= 2; argv += 2;
        break;
      } else if (ch1 == 't') {
        if (argc <= 1) {
          ErrorArgc("zt");
          return fFalse;
        }
        TT = RParseSz(argv[1], pmTim);
        if (!FValidTim(TT)) {
          ErrorValR("zt", TT);
          return fFalse;
        }
        argc--; argv++;
        break;
      } else if (ch1 == 'd') {
        if (argc <= 1) {
          ErrorArgc("zd");
          return fFalse;
        }
        DD = NParseSz(argv[1], pmDay);
        if (!FValidDay(DD, MM, YY)) {
          ErrorValN("zd", DD);
          return fFalse;
        }
        argc--; argv++;
        break;
      } else if (ch1 == 'i') {
        if (argc <= 2) {
          ErrorArgc("zi");
          return fFalse;
        }
        ciCore.nam = SzPersist(argv[1]);
        ciCore.loc = SzPersist(argv[2]);
        argc -= 2; argv += 2;
        break;
      }
      if (argc <= 1 || RParseSz(argv[1], pmZon) == rLarge)
        ZZ -= 1.0;
      else {
        ZZ = us.zonDef = RParseSz(argv[1], pmZon);
        if (!FValidZon(us.zonDef)) {
          ErrorValR("z", us.zonDef);
          return fFalse;
        }
        argc--; argv++;
      }
      break;

    case 'q':
      i = (ch1 == 'y' || ch1 == 'j') + 2*(ch1 == 'm') + 3*(ch1 == 'd') +
        4*(ch1 == chNull) + 7*(ch1 == 'a') + 8*(ch1 == 'b');
      if (argc <= i) {
        ErrorArgc("q");
        return fFalse;
      }
      is.fHaveInfo = fTrue;
      if (ch1 == 'j') {
        is.JD = atof(argv[1])+rRound;
        TT = RFract(is.JD);
        JulianToMdy(is.JD-TT, &MM, &DD, &YY);
        TT = DegToDec(TT * 24.0);
        SS = ZZ = 0.0; OO = us.lonDef; AA = us.latDef;
      } else {
        MM = i > 1 ? NParseSz(argv[1], pmMon) : 1;
        DD = i > 2 ? NParseSz(argv[2], pmDay) : 1;
        YY = NParseSz(argv[3-(i<3)-(i<2)], pmYea);
        TT = i > 3 ? RParseSz(argv[4], pmTim) : (i < 3 ? 0.0 : 12.0);
        SS = i > 7 ? RParseSz(argv[5], pmDst) : (i > 6 ? 0.0 : us.dstDef);
        ZZ = i > 6 ? RParseSz(argv[5 + (i > 7)], pmZon) : us.zonDef;
        OO = i > 6 ? RParseSz(argv[6 + (i > 7)], pmLon) : us.lonDef;
        AA = i > 6 ? RParseSz(argv[7 + (i > 7)], pmLat) : us.latDef;
        if (!FValidMon(MM)) {
          ErrorValN("q", MM);
          return fFalse;
        } else if (!FValidDay(DD, MM, YY)) {
          ErrorValN("q", DD);
          return fFalse;
        } else if (!FValidYea(YY)) {
          ErrorValN("q", YY);
          return fFalse;
        } else if (!FValidTim(TT)) {
          ErrorValR("q", TT);
          return fFalse;
        } else if (!FValidDst(SS)) {
          ErrorValR("q", SS);
          return fFalse;
        } else if (!FValidZon(ZZ)) {
          ErrorValR("a", ZZ);
          return fFalse;
        } else if (!FValidLon(OO)) {
          ErrorValR("a", OO);
          return fFalse;
        } else if (!FValidLat(AA)) {
          ErrorValR("a", AA);
          return fFalse;
        }
      }
      argc -= i; argv += i;
      break;

    case 'i':
      if (argc <= 1) {
        ErrorArgc("i");
        return fFalse;
      }
      if (!FInputData(argv[1]))
        return fFalse;
      argc--; argv++;
      break;

    case '>':
      ch1 = 's';
      /* Fall through */

    case 'o':
      if (argc <= 1) {
        ErrorArgc("o");
        return fFalse;
      }
      if (ch1 == 's') {
        is.szFileScreen = SzPersist(argv[1]);
        argc--; argv++;
        break;
      } else if (ch1 == '0')
        SwitchF(us.fWritePos);
      SwitchF(us.fWriteFile);
      is.szFileOut = SzPersist(argv[1]);
      if (is.fSzPersist) {
        is.rgszComment = argv;
        do {
          argc--; argv++;
          is.cszComment++;
        } while (argc > 1 && !FChSwitch(argv[1][0]));
      }
      break;

    /* Switches which affect what information is used in a chart: */

    case 'R':
      if (ch1 == 'A') {
        while (argc > 1 && (i = NParseSz(argv[1], pmAspect)))
          if (!FAspect(i)) {
            ErrorValN("RA", i);
            return fFalse;
          } else {
            aspectorb[i] = -rDegHalf;
            argc--; argv++;
          }
        break;
      }
      if (ch1 == 'T') {
        pch = (char *)ignore2;
        ch1 = argv[0][++ich];
      } else
        pch = (char *)ignore;
      if (ch1 == '0')
        for (i = 1; i <= cObj; i++)
          pch[i] = fTrue;
      else if (ch1 == '1') {
        for (i = 1; i <= cObj; i++)
          pch[i] = fFalse;
        us.fCusp = us.fUranian = us.nStar = fTrue;
      } else if (ch1 == 'C')
        for (i = cuspLo; i <= cuspHi; i++)
          SwitchF(pch[i]);
      else if (ch1 == 'u')
        for (i = uranLo; i <= uranHi; i++)
          SwitchF(pch[i]);
      else if (ch1 == 'U')
        for (i = starLo; i <= starHi; i++)
          SwitchF(pch[i]);
      else if (argc <= 1 || (!NParseSz(argv[1], pmObject))) {
        for (i = oChi; i <= oVes; i++)
          SwitchF(pch[i]);
        for (i = oLil; i <= oEP; i++)
          SwitchF(pch[i]);
      }
      while (argc > 1 && (i = NParseSz(argv[1], pmObject)))
        if (!FItem(i)) {
          ErrorValN("R", i);
          return fFalse;
        } else {
          SwitchF(pch[i]);
          argc--; argv++;
        }
      break;

    case 'C':
      SwitchF(us.fCusp);
      break;

    case 'u':
      SwitchF(us.fUranian);
      break;

    case 'U':
      if (ch1 == 'n' || ch1 == 'b' || ch1 == 'z' || ch1 == 'l')
        us.nStar = ch1;
      else
        SwitchF(us.nStar);
      break;

    case 'A':
      if (ch1 != 'o' && ch1 != 'm' && ch1 != 'd' && ch1 != 'a') {
        if (argc <= 1) {
          ErrorArgc("A");
          return fFalse;
        }
        i = NParseSz(argv[1], pmAspect);
        if (!FValidAspect(i)) {
          ErrorValN("A", i);
          return fFalse;
        }
        us.nAsp = i;
        argc--; argv++;
      } else {
        if (argc <= 2) {
          ErrorArgc("A");
          return fFalse;
        }
        i = NParseSz(argv[1], ch1 == 'o' || ch1 == 'a' ? pmAspect : pmObject);
        if (i < 1 || i > (ch1 == 'o' || ch1 == 'a' ? cAspect : oNorm)) {
          ErrorValN("A", i);
          return fFalse;
        }
        rT = RParseSz(argv[2], 0);
        if (rT < -rDegMax || rT > rDegMax) {
          ErrorValR("A", rT);
          return fFalse;
        }
        if (ch1 == 'o')
          aspectorb[i] = rT;
        else if (ch1 == 'm')
          planetorb[i] = rT;
        else if (ch1 == 'd')
          planetadd[i] = rT;
        else
          aspectangle[i] = rT;
        argc -= 2; argv += 2;
      }
      break;

    /* Switches which affect how a chart is computed: */

    case 'b':
      if (ch1 == '0')
        SwitchF(us.fSeconds);
#ifdef PLACALC
      SwitchF(us.fPlacalc);
#endif
      is.fSeconds = us.fSeconds;
      break;

    case 'c':
      if (argc <= 1) {
        ErrorArgc("c");
        return fFalse;
      }
      i = NParseSz(argv[1], pmSystem);
      if (!FValidSystem(i)) {
        ErrorValN("c", i);
        return fFalse;
      }
      us.nHouseSystem = i;
      argc--; argv++;
      break;

    case 's':
      if (argc > 1 && ((rT = atof(argv[1])) != 0.0 || FNumCh(argv[1][0]))) {
        argc--; argv++;
        us.rZodiacOffset = rT;
      }
      if (ch1 == 'r')
        SwitchF(us.fEquator);
      else if (ch1 == 'h')
        us.nDegForm = 1;
      else if (ch1 == 'd')
        us.nDegForm = 2;
      else if (ch1 == 'z')
        us.nDegForm = 0;
      else
        SwitchF(us.fSiderial);
      break;

    case 'h':
      if (argc > 1 && (i = NParseSz(argv[1], pmObject))) {
        argc--; argv++;
      } else
        i = 1;
      if (i < 0 || i == oMoo || !FObject(i) || i > uranHi) {
        ErrorValN("h", i);
        return fFalse;
      }
      us.objCenter = i;
      pch = szObjName[0];
      szObjName[0] = szObjName[us.objCenter];
      szObjName[us.objCenter] = pch;
      if (us.objCenter < oMoo)
        us.objCenter = 1-us.objCenter;
      break;

    case 'p':
      if (fAnd) {
        us.fProgress = fFalse;
        break;
      }
      if (ch1 == '0') {
        SwitchF(us.fSolarArc);
        ch1 = (argv[0][++ich]);
      }
      us.fProgress = fTrue;
#ifdef TIME
      if (ch1 == 'n') {
        GetTimeNow(&Mon, &Day, &Yea, &Tim, us.zonDef - us.dstDef);
        is.JDp = MdytszToJulian(Mon, Day, Yea, Tim, us.dstDef, us.zonDef);
        break;
      }
#endif
      if (ch1 == 'd') {
        if (argc <= 1) {
          ErrorArgc("pd");
          return fFalse;
        }
        us.rProgDay = atof(argv[1]);
        if (us.rProgDay == 0.0) {
          ErrorValR("pd", us.rProgDay);
          return fFalse;
        }
        argc--; argv++;
        break;
      }
      if (argc <= 3) {
        ErrorArgc("p");
        return fFalse;
      }
      Mon = NParseSz(argv[1], pmMon);
      Day = NParseSz(argv[2], pmDay);
      Yea = NParseSz(argv[3], pmYea);
      if (!FValidMon(Mon)) {
        ErrorValN("p", Mon);
        return fFalse;
      } else if (!FValidDay(Day, Mon, Yea)) {
        ErrorValN("p", Day);
        return fFalse;
      } else if (!FValidYea(Yea)) {
        ErrorValN("p", Yea);
        return fFalse;
      }
      is.JDp = MdytszToJulian(Mon, Day, Yea, 0.0, us.dstDef, us.zonDef);
      argc -= 3; argv += 3;
      break;

    case 'x':
      if (argc <= 1) {
        ErrorArgc("x");
        return fFalse;
      }
      i = atoi(argv[1]);
      if (!FValidHarmonic(i)) {
        ErrorValN("x", i);
        return fFalse;
      }
      us.nHarmonic = i;
      argc--; argv++;
      break;

    case '1':
      if (argc > 1 && (i = NParseSz(argv[1], pmObject))) {
        argc--; argv++;
      } else
        i = oSun;
      if (!FItem(i)) {
        ErrorValN("1", i);
        return fFalse;
      }
      us.objOnAsc = fAnd ? 0 : i;
      break;

    case '2':
      if (argc > 1 && (i = NParseSz(argv[1], pmObject))) {
        argc--; argv++;
      } else
        i = oSun;
      if (!FItem(i)) {
        ErrorValN("2", i);
        return fFalse;
      }
      us.objOnAsc = fAnd ? 0 : -i;
      break;

    case '3':
      SwitchF(us.fDecan);
      break;

    case 'f':
      SwitchF(us.fFlip);
      break;

    case 'G':
      SwitchF(us.fGeodetic);
      break;

    case 'F':
      if (argc <= 3) {
        ErrorArgc("F");
        return fFalse;
      }
      i = NParseSz(argv[1], pmObject);
      if (!FItem(i)) {
        ErrorValN("F", i);
        return fFalse;
      }
      force[i] = (NParseSz(argv[2], pmSign)-1.0)*30.0+DecToDeg(atof(argv[3]));
      if (force[i] < 0.0 || force[i] >= rDegMax) {
        ErrorValR("F", force[i]);
        return fFalse;
      } else
        force[i] += rDegMax;
      argc -= 3; argv += 3;
      break;

    case '+':
      if (argc > 1 && (i = atoi(argv[1])) != 0) {
        argc--; argv++;
      } else
        i = 1;
      us.dayDelta += i * (ch1 == 'y' ? 365 : (ch1 == 'm' ? 30 : 1));
      break;

    case '-': case chNull:
      if (argc > 1 && (i = atoi(argv[1])) != 0) {
        argc--; argv++;
      } else
        i = 1;
      us.dayDelta -= i * (ch1 == 'y' ? 365 : (ch1 == 'm' ? 30 : 1));
      break;

    /* Switches for relationship and comparison charts: */

    case 'r':
      if (fAnd) {
        us.nRel = 0;
        break;
      }
      i = 2 + 2*((ch1 == 'c' || ch1 == 'm') && ch2 == '0');
      if (argc <= i) {
        ErrorArgc("r");
        return fFalse;
      }
      if (ch1 == 'c')
        us.nRel = rcComposite;
      else if (ch1 == 'm')
        us.nRel = rcMidpoint;
      else if (ch1 == 'd')
        us.nRel = rcDifference;
#ifdef BIORHYTHM
      else if (ch1 == 'b')
        us.nRel = rcBiorhythm;
#endif
      else if (ch1 == '0')
        us.nRel = rcDual;
      else if (ch1 == 't')
        us.nRel = rcTransit;
      else if (ch1 == 'p') {
        us.nRel = rcProgress;
        us.fSolarArc = (ch2 == '0');
      } else
        us.nRel = rcSynastry;
      is.szFile = SzPersist(argv[1]); is.szFile2 = SzPersist(argv[2]);
      if (is.fSzInteract) {
        if (!FInputData(is.szFile2))
          return fFalse;
        ciTwin = ciCore;
        if (!FInputData(is.szFile))
          return fFalse;
      }
      if (i > 2) {
        us.nRatio1 = atoi(argv[3]);
        us.nRatio2 = atoi(argv[4]);
        if (us.nRatio1 == us.nRatio2)
          us.nRatio1 = us.nRatio2 = 1;
      }
      argc -= i; argv += i;
      break;

#ifdef TIME
    case 'y':
      if (argc <= 1) {
        ErrorArgc("y");
        return fFalse;
      }
      if (ch1 == 'd')
        us.nRel = rcDifference;
#ifdef BIORHYTHM
      else if (ch1 == 'b')
        us.nRel = rcBiorhythm;
#endif
      else if (ch1 == 't')
        us.nRel = rcTransit;
      else if (ch1 == 'p') {
        us.nRel = rcProgress;
        if (ch2 == '0')
          SwitchF(us.fSolarArc);
      } else
        us.nRel = rcDual;
      is.szFile = SzPersist(argv[1]); is.szFile2 = szNowCore;
      argc--; argv++;
      break;
#endif

    /* Switches to access graphics options: */

    case 'k':
      if (ch1 == '0')
        us.fAnsi = 2;
      else
        SwitchF(us.fAnsi);
      break;

#ifdef PCG
    case 'V':
      if (argc <= 1) {
        ErrorArgc("V");
        return fFalse;
      }
      i = atoi(argv[1]);
      if (!FValidTextrows(i)) {
        ErrorValN("V", i);
        return fFalse;
      }
      gs.nTextRows = i;
      argc--; argv++;
      break;
#endif

#ifdef GRAPH
    case 'X':
      i = NProcessSwitchesX(argc, argv, ich, fOr, fAnd, fNot);
      if (i < 0)
        return fFalse;
      SwitchF2(us.fGraphics);
      argc -= i; argv += i;
      break;
#endif

    case ';':    /* The -; switch means don't process the rest of the line. */
      return fTrue;

    case '@':    /* The -@ switch is just a system flag indicator no-op. */
      break;

    case '.':                /* "-." is usually used to exit the -Q loop. */
      Terminate(tcForce);

    case 'B':                /* For no useful reason, -B sounds a beep. */
      putchar(chBell);
      break;

    default:
      ErrorSwitch(argv[0]);
      return fFalse;
    }
    argc--; argv++;
  }
  return fTrue;
}


/*
******************************************************************************
** Main Program.
******************************************************************************
*/

#ifndef NOMAIN
/* The main program, the starting point for Astrolog, follows. This routine */
/* basically consists of a loop, inside which we read a command line, and   */
/* go process it, before actually calling a routine to do the neat stuff.   */

#ifdef SWITCHES
int main(argc, argv)
int argc;
char **argv;
{
#else
int main()
{
  int argc;
  char **argv;
#endif
  char szCommandLine[cchSzMax], *rgsz[MAXSWITCHES];

  S= stdout;   /* auto-init */

  /* Read in info from the astrolog.dat file. */
  FProcessSwitchFile(DEFAULT_INFOFILE, NULL);

LBegin:
#ifdef PCG
  if (gs.nTextRows > 0) {
    PcSetTextRows(gs.nTextRows);
    neg(gs.nTextRows);
  }
#endif
  if (us.fNoSwitches) {                             /* Go prompt for    */
    argc = NPromptSwitches(szCommandLine, rgsz);    /* switches if we   */
    argv = rgsz;                                    /* don't have them. */
  }
  is.szProgName = argv[0];
  is.fSzPersist = fTrue;
  if (FProcessSwitches(argc, argv)) {
    if (!us.fNoSwitches && us.fLoopInit) {
      us.fNoSwitches = fTrue;
      goto LBegin;
    }
#ifdef PCG
    if (gs.nTextRows > 0) {
      PcSetTextRows(gs.nTextRows);
      neg(gs.nTextRows);
    }
#endif
    Action();
  }
  if (us.fLoop) {       /* If -Q in effect, loop back and get switch */
    PrintL2();          /* information for another chart to display. */
    InitVariables();
    us.fLoop = us.fNoSwitches = fTrue;
    goto LBegin;
  }
  Terminate(tcOK);    /* The only standard place to exit Astrolog is here. */
}
#endif /* NOMAIN */

/* astrolog.c */
