home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / Apps / Astro / astrolog / Source / charts.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-12  |  33.9 KB  |  1,049 lines

  1. /*
  2. ** Astrolog (Version 4.10) File: charts.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.  
  41. /*
  42. ******************************************************************************
  43. ** Single Chart Display Subprograms.
  44. ******************************************************************************
  45. */
  46.  
  47. /* Fill out tables based on the number of unrestricted planets in signs by  */
  48. /* element, signs by mode, as well as other values such as the number of    */
  49. /* objects in yang vs. yin signs, in various house hemispheres (north/south */
  50. /* and east/west), and the number in first six signs vs. second six signs.  */
  51. /* This is used by the -v chart listing and the sidebar in graphics charts. */
  52.  
  53. void CreateElemTable(elemode, elem, mo, tot, pos, abo, lef, lea)
  54. int elemode[4][3], *elem, *mo, *tot, *pos, *abo, *lef, *lea;
  55. {
  56.   int i, j;
  57.  
  58.   *tot = *pos = *abo = *lef = *lea = 0;    /* Initialize arrays     */
  59.   for (i = 0; i < 4; i++)                  /* and variables to zero */
  60.     elem[i] = 0;
  61.   for (j = 0; j < 3; j++)
  62.     mo[j] = 0;
  63.   for (i = 0; i < 4; i++)
  64.     for (j = 0; j < 3; j++)
  65.       elemode[i][j] = 0;
  66.  
  67.   /* Calculate number of objects in each element, mode, hemisphere, etc. */
  68.  
  69.   for (i = 1; i <= total; i++) if (!ignore[i]) {
  70.     (*tot)++;
  71.     j = ZTOS(planet[i]);
  72.     elemode[(j-1)&3][(j-1)%3]++;
  73.     elem[(j-1)&3]++; mo[(j-1)%3]++;
  74.     *pos += (j & 1);
  75.     *lea += (j < _LIB);
  76.     j = inhouse[i];
  77.     *abo += (j >= _LIB);
  78.     *lef += (j < _CAN || j >= _CAP);
  79.   }
  80. }
  81.  
  82.  
  83. /* Print the straight listing of planet and house positions and specified */
  84. /* by the -v switch, along with the element table, etc.                   */
  85.  
  86. void ChartLocation()
  87. {
  88.   int elemode[4][3], elem[4], mo[3], pos, abo, lef, lea;
  89.   int count, i, j, k;
  90.  
  91.   CreateElemTable(elemode, elem, mo, &count, &pos, &abo, &lef, &lea);
  92.  
  93.   /* Print header showing time and date of the chart being displayed. */
  94.  
  95.   AnsiColor(WHITE);
  96.   fprintf(S, "%s %s chart ", appname, VERSION);
  97.   if (Mon == -1)
  98.     fprintf(S, "(no time or space)\n");
  99.   else if (relation == DASHrc)
  100.     fprintf(S, "(composite)\n");
  101.   else {
  102.     i = (int) (FRACT(dabs(Tim))*100.0+ROUND/60.0);
  103.     fprintf(S, "for %s %s",
  104.       CharDate(Mon, Day, Yea, TRUE), CharTime((int)Tim, i));
  105.     fprintf(S, " (%s GMT) %s\n", CharZone(Zon),
  106.       CharLocation(Lon, Lat, 100.0));
  107.   }
  108.  
  109. #ifdef INTERPRET
  110.   if (interpret) {            /* Print an interpretation if -I in effect. */
  111.     if (relation == DASHr)
  112.       InterpretSynastry();    /* Print synastry interpretaion for -r -I.  */
  113.     else
  114.       InterpretLocation();    /* Do normal interpretation for just -v -I. */
  115.     return;
  116.   }
  117. #endif
  118.   AnsiColor(DEFAULT);
  119.   fprintf(S, "Body  Locat. Ret. Decl. Rul.      House  Rul. Veloc.    ");
  120.   fprintf(S, "%s Houses.\n\n", systemname[housesystem]);
  121.  
  122.   /* Ok, now print out each location of each object. */
  123.  
  124.   for (i = 1, j = 1; i <= BASE; i++, j++) {
  125.     if (i > OBJECTS && (i <= C_HI || ignore[i]))
  126.       continue;
  127.     while (i <= OBJECTS && j <= OBJECTS && ignore[j])
  128.       j++;
  129.     if (i <= OBJECTS && j > OBJECTS)
  130.       PrintTab(' ', 51);
  131.     else {
  132.       if (i > OBJECTS)
  133.         j = i;
  134.       AnsiColor(objectansi[j]);
  135.       fprintf(S, "%-4.4s: ", objectname[j]);
  136.       PrintZodiac(planet[j]);
  137.       fprintf(S, " %c ", ret[j] >= 0.0 ? ' ' : 'R');
  138.       if (j <= THINGS || j > OBJECTS)
  139.         PrintAltitude(planetalt[i]);
  140.       else
  141.         fprintf(S, "_______");
  142.       fprintf(S, " (%c)", Dignify(j, ZTOS(planet[i])));
  143.       k = inhouse[j];
  144.       AnsiColor(signansi(k));
  145.       fprintf(S, " [%2d%c%c house]", k, post[k][0], post[k][1]);
  146.       AnsiColor(DEFAULT);
  147.       fprintf(S, " [%c] ", Dignify(j, k));
  148.       if ((j != _MOO || placalc) && (IsObject(j) || (j == _NOD && placalc)))
  149.         fprintf(S, RTOD(dabs(ret[j])) < 10.0 ? "%c%5.3f" : "%c%5.2f",
  150.           ret[i] < 0.0 ? '-' : '+', RTOD(dabs(ret[j])));
  151.       else
  152.         fprintf(S, "______");
  153.     }
  154.  
  155.     /* For some lines, we have to append the house cusp positions. */
  156.  
  157.     if (i <= SIGNS) {
  158.       fprintf(S, "  -  ");
  159.       AnsiColor(signansi(i));
  160.       fprintf(S, "House cusp %2d: ", i);
  161.       PrintZodiac(house[i]);
  162.     }
  163.  
  164.     /* For some lines, we have to append the element table information. */
  165.  
  166.     if (i == SIGNS+2)
  167.       fprintf(S, "     Car Fix Mut TOT");
  168.     else if (i > SIGNS+2 && i < SIGNS+7) {
  169.       k = i-(SIGNS+2)-1;
  170.       AnsiColor(elemansi[k]);
  171.       fprintf(S, "  %c%c%c%3d %3d %3d %3d",
  172.         element[k][0], element[k][1], element[k][2],
  173.         elemode[k][0], elemode[k][1], elemode[k][2], elem[k]);
  174.       AnsiColor(DEFAULT);
  175.     } else if (i == SIGNS+7)
  176.       fprintf(S, "  TOT %2d %3d %3d %3d", mo[0], mo[1], mo[2], count);
  177.     else if (i == OBJECTS)
  178.       PrintTab(' ', 23);
  179.     else if (i >= U_LO)
  180.       fprintf(S, "  Uranian #%d", i-U_LO+1);
  181.     switch (i-SIGNS-1) {
  182.     case 1: fprintf(S, "   +:%2d", pos);       break;
  183.     case 2: fprintf(S, "   -:%2d", count-pos); break;
  184.     case 3: fprintf(S, "   M:%2d", abo);       break;
  185.     case 4: fprintf(S, "   N:%2d", count-abo); break;
  186.     case 5: fprintf(S, "   A:%2d", lef);       break;
  187.     case 6: fprintf(S, "   D:%2d", count-lef); break;
  188.     case 7: fprintf(S,    "<:%2d", lea);       break;
  189.     }
  190.     printl();
  191.   }
  192.  
  193.   /* Do another loop to print out the stars in their specified order. */
  194.  
  195.   if (universe) for (i = S_LO; i <= S_HI; i++) if (!ignore[i]) {
  196.     j = BASE+starname[i-BASE];
  197.     AnsiColor(objectansi[j]);
  198.     fprintf(S, "%.4s: ", objectname[j]);
  199.     PrintZodiac(planet[j]);
  200.     fprintf(S, "   ");
  201.     PrintAltitude(planetalt[j]);
  202.     k = inhouse[j];
  203.     AnsiColor(signansi(k));
  204.     fprintf(S, "     [%2d%c%c house]", k, post[k][0], post[k][1]);
  205.     AnsiColor(DEFAULT);
  206.     fprintf(S, "     ______  Star #%2d: %5.2f\n", i-BASE, starbright[j-BASE]);
  207.   }
  208. }
  209.  
  210.  
  211. /* Print out the aspect and midpoint grid for a chart, as specified with the */
  212. /* -g switch. (Each grid row takes up 4 lines of text.)                      */
  213.  
  214. void ChartGrid()
  215. {
  216.   int x, y, r, x1, y1, temp;
  217.  
  218. #ifdef INTERPRET
  219.   if (interpret) {    /* Print interpretation instead if -I in effect. */
  220.     InterpretGrid();
  221.     return;
  222.   }
  223. #endif
  224.  
  225.   for (y1 = 0, y = 1; y <= total; y++) if (!ignore[y])
  226.     for (r = 1; r <= 4; r++) {
  227.       for (x1 = 0, x = 1; x <= total; x++) if (!ignore[x]) {
  228.         if (y1 > 0 && x1 > 0 && y+r > 2)
  229.           printc(r > 1 ? BOXV : BOXC);
  230.         if (r > 1) {
  231.           temp = grid->n[x][y];
  232.  
  233.           /* Print aspect rows. */
  234.  
  235.           if (x < y) {
  236.             if (temp);
  237.               AnsiColor(aspectansi[temp]);
  238.             if (r == 2)
  239.               fprintf(S, "%s", temp ? aspectabbrev[temp] : "   ");
  240.             else if (!temp)
  241.               fprintf(S, "   ");
  242.             else {
  243.               if (r == 3) {
  244.                 if (grid->v[x][y] < 6000)
  245.                   fprintf(S, "%c%2d", exdisplay & DASHga ?
  246.                     (grid->v[x][y] < 0 ? 'a' : 's') :
  247.                     (grid->v[x][y] < 0 ? '-' : '+'), abs(grid->v[x][y])/60);
  248.                 else
  249.                   fprintf(S, "%3d", abs(grid->v[x][y])/60);
  250.               } else
  251.                 fprintf(S, "%02d'", abs(grid->v[x][y])%60);
  252.             }
  253.  
  254.           /* Print midpoint rows. */
  255.  
  256.           } else if (x > y) {
  257.             AnsiColor(signansi(temp));
  258.             if (r == 2) {
  259.               temp = grid->n[x][y];
  260.               fprintf(S, "%c%c%c", SIGNAM(temp));
  261.             } else if (r == 3) {
  262.               fprintf(S, "%2d%c", grid->v[x][y]/60, DEGR0);
  263.             } else
  264.               fprintf(S, "%02d'", grid->v[x][y]%60);
  265.  
  266.           /* Print the diagonal of object names. */
  267.  
  268.           } else {
  269.             AnsiColor(REVERSE);
  270.             if (r == 2) {
  271.               AnsiColor(objectansi[y]);
  272.               fprintf(S, "%c%c%c", OBJNAM(y));
  273.             } else {
  274.               temp = ZTOS(planet[y]);
  275.               AnsiColor(signansi(temp));
  276.               if (r == 3)
  277.                 fprintf(S, "%2d%c", (int)planet[y] - (temp-1)*30, DEGR0);
  278.               else
  279.                 fprintf(S, "%c%c%c", SIGNAM(temp));
  280.             }
  281.           }
  282.           AnsiColor(DEFAULT);
  283.         } else
  284.           if (y1 > 0)
  285.             PrintTab(BOXH, 3);
  286.         x1++;
  287.         if (column80 && x1 >= 20)
  288.           x = total;
  289.       }
  290.       if (y+r > 2)
  291.         printl();
  292.       y1++;
  293.     }
  294. }
  295.  
  296.  
  297. /* This is a subprocedure of DisplayGrands(). Here we print out one aspect */
  298. /* configuration found by the parent procedure.                            */
  299.  
  300. void PrintGrand(nam, i1, i2, i3, i4)
  301. char nam;
  302. int i1, i2, i3, i4;
  303. {
  304.   switch (nam) {
  305.   case '.': AnsiColor(aspectansi[_CON]); fprintf(S, "Stellium   "); break;
  306.   case 't': AnsiColor(aspectansi[_TRI]); fprintf(S, "Grand Trine"); break;
  307.   case 's': AnsiColor(aspectansi[_OPP]); fprintf(S, "T-Square   "); break;
  308.   case 'y': AnsiColor(aspectansi[_INC]); fprintf(S, "Yod        "); break;
  309.   case 'g': AnsiColor(aspectansi[_SQU]); fprintf(S, "Grand Cross"); break;
  310.   case 'c': AnsiColor(aspectansi[_SEX]); fprintf(S, "Cradle     "); break;
  311.   default: ;
  312.   }
  313.   AnsiColor(DEFAULT);
  314.   fprintf(S, " %s ", nam == '.' || nam == 't' || nam == 'g' ? "with" : "from");
  315.   AnsiColor(objectansi[i1]);
  316.   fprintf(S, "%c%c%c: ", OBJNAM(i1));
  317.   PrintZodiac(planet[i1]);
  318.   fprintf(S, " %s ", nam == '.' || nam == 't' ? "and" : "to ");
  319.   AnsiColor(objectansi[i2]);
  320.   fprintf(S, "%c%c%c: ", OBJNAM(i2));
  321.   PrintZodiac(planet[i2]);
  322.   fprintf(S, " %s ", nam == 'g' || nam == 'c' ? "to " : "and");
  323.   AnsiColor(objectansi[i3]);
  324.   fprintf(S, "%c%c%c: ", OBJNAM(i3));
  325.   PrintZodiac(planet[i3]);
  326.   if (nam == 'g' || nam == 'c') {
  327.     fprintf(S, " to ");
  328.     AnsiColor(objectansi[i4]);
  329.     fprintf(S, "%c%c%c: ", OBJNAM(i4));
  330.     PrintZodiac(planet[i4]);
  331.   }
  332.   printl();
  333. }
  334.  
  335.  
  336. /* Scan the aspect grid of a chart and print out any major configurations, */
  337. /* as specified with the -g0 switch.                                       */
  338.  
  339. void DisplayGrands()
  340. {
  341.   int count = 0, i, j, k, l;
  342.  
  343.   for (i = 1; i <= total; i++) if (!ignore[i])
  344.     for (j = 1; j <= total; j++) if (j != i && !ignore[j])
  345.       for (k = 1; k <= total; k++) if (k != i && k != j && !ignore[k]) {
  346.  
  347.         /* Is there a Stellium among the current three planets? */
  348.  
  349.         if (i < j && j < k && grid->n[i][j] == _CON &&
  350.             grid->n[i][k] == _CON && grid->n[j][k] == _CON) {
  351.           count++;
  352.           PrintGrand('.', i, j, k, l);
  353.  
  354.         /* Is there a Grand Trine? */
  355.  
  356.         } else if (i < j && j < k && grid->n[i][j] == _TRI &&
  357.             grid->n[i][k] == _TRI && grid->n[j][k] == _TRI) {
  358.           count++;
  359.           PrintGrand('t', i, j, k, l);
  360.  
  361.         /* Is there a T-Square? */
  362.  
  363.         } else if (j < k && grid->n[j][k] == _OPP &&
  364.             grid->n[MIN(i, j)][MAX(i, j)] == _SQU &&
  365.             grid->n[MIN(i, k)][MAX(i, k)] == _SQU) {
  366.           count++;
  367.           PrintGrand('s', i, j, k, l);
  368.  
  369.         /* Is there a Yod? */
  370.  
  371.         } else if (j < k && grid->n[j][k] == _SEX &&
  372.             grid->n[MIN(i, j)][MAX(i, j)] == _INC &&
  373.             grid->n[MIN(i, k)][MAX(i, k)] == _INC) {
  374.           count++;
  375.           PrintGrand('y', i, j, k, l);
  376.         }
  377.         for (l = 1; l <= total; l++) if (!ignore[l]) {
  378.  
  379.           /* Is there a Grand Cross among the current four planets? */
  380.  
  381.           if (i < j && i < k && i < l && j < l && grid->n[i][j] == _SQU &&
  382.               grid->n[MIN(j, k)][MAX(j, k)] == _SQU &&
  383.               grid->n[MIN(k, l)][MAX(k, l)] == _SQU &&
  384.               grid->n[i][l] == _SQU &&
  385.               MinDistance(planet[i], planet[k]) > 150.0 &&
  386.               MinDistance(planet[j], planet[l]) > 150.0) {
  387.             count++;
  388.             PrintGrand('g', i, j, k, l);
  389.  
  390.           /* Is there a Cradle? */
  391.  
  392.           } else if (i < l && grid->n[MIN(i, j)][MAX(i, j)] == _SEX &&
  393.               grid->n[MIN(j, k)][MAX(j, k)] == _SEX &&
  394.               grid->n[MIN(k, l)][MAX(k, l)] == _SEX &&
  395.               MinDistance(planet[i], planet[l]) > 150.0) {
  396.             count++;
  397.             PrintGrand('c', i, j, k, l);
  398.           }
  399.         }
  400.       }
  401.   if (!count)
  402.     fprintf(S, "No major configurations in aspect grid.\n");
  403. }
  404.  
  405.  
  406. /* This is subprocedure of ChartWheel(). Here we print out the location */
  407. /* of a particular house cusp as well as what house cusp number it is.  */
  408.  
  409. void PrintHouse(i, left)
  410. int i, left;
  411. {
  412.   if (!left)
  413.     PrintZodiac(house[i]);
  414.   AnsiColor(signansi(i));
  415.   fprintf(S, "<%d>", i);
  416.   if (left)
  417.     PrintZodiac(house[i]);
  418.   else
  419.     AnsiColor(DEFAULT);
  420. }
  421.  
  422.  
  423. /* Another subprocedure of ChartWheel(). Here we print out one line in a */
  424. /* particular house cell (which may be blank).                           */
  425.  
  426. void PrintWheelSlot(obj, wheelcols)
  427. int obj, wheelcols;
  428. {
  429.   if (obj) {
  430.     AnsiColor(objectansi[obj]);
  431.     fprintf(S, " %c%c%c ", OBJNAM(obj));  /* Print planet and its position. */
  432.     PrintZodiac(planet[obj]);
  433.     fprintf(S, "%c ", ret[obj] < 0.0 ? 'r' : ' ');
  434.     PrintTab(' ', WHEELCOLS-14-1);
  435.   } else
  436.     PrintTab(' ', wheelcols-1);       /* This particular line is blank. */
  437. }
  438.  
  439.  
  440. /* Display all the objects in a wheel format on the screen, as specified */
  441. /* with the -w switch. The wheel is divided into the 12 houses and the   */
  442. /* planets are placed accordingly.                                       */
  443.  
  444. void ChartWheel()
  445. {
  446.   byte wheel[SIGNS][WHEELROWS];
  447.   int wheelcols, count = 0, i, j, k, l;
  448.  
  449.   /* If the seconds (-b0) flag is set, we'll print all planet and house    */
  450.   /* locations to the nearest zodiac second instead of just to the minute. */
  451.  
  452.   seconds = -seconds;
  453.   wheelcols = WHEELCOLS + (seconds < 0)*4;
  454.  
  455.   for (i = 0; i < SIGNS; i++)
  456.     for (j = 0; j < wheelrows; j++)    /* Clear out array from the */
  457.       wheel[i][j] = 0;                 /* last time we used it.    */
  458.  
  459.   /* This section of code places each object in the wheel house array. */
  460.  
  461.   for (i = 1; i <= total && count < wheelrows*12; i++) {
  462.     if (ignore[i] || !(i < _MC || i == OBJECTS || i > C_HI))
  463.       continue;
  464.  
  465.     /* Try to put object in its proper house. If no room, */
  466.     /* then overflow over to the succeeding house.        */
  467.  
  468.     for (j = inhouse[i]-1; j < SIGNS; j = j < SIGNS ? (j+1)%SIGNS : j) {
  469.  
  470.       /* Now try to find the proper place in the house to put the object. */
  471.       /* This is in sorted order, although a check is made for 0 Aries.   */
  472.  
  473.       if (wheel[j][wheelrows-1] > 0)
  474.         continue;
  475.       l = house[j+1] > house[Mod12(j+2)];
  476.       for (k = 0; wheel[j][k] > 0 &&
  477.            (planet[i] >= planet[wheel[j][k]] ||
  478.             (l && planet[i] < DEGHALF && planet[wheel[j][k]] > DEGHALF)) &&
  479.            !(l && planet[i] > DEGHALF && planet[wheel[j][k]] < DEGHALF); k++)
  480.         ;
  481.  
  482.       /* Actually insert object in proper place. */
  483.  
  484.       if (wheel[j][k] <= 0)
  485.         wheel[j][k] = i;
  486.       else {
  487.         for (l = wheelrows-1; l > k; l--)
  488.           wheel[j][l] = wheel[j][l-1];
  489.         wheel[j][k] = i;
  490.       }
  491.       count++;
  492.       j = SIGNS;
  493.     }
  494.   }
  495.  
  496.   /* Now, if this is really the -w switch and not -w0, then reverse the */
  497.   /* order of objects in western houses for more intuitive reading.     */
  498.  
  499.   if (!(exdisplay & DASHw0))
  500.     for (i = 3; i < 9; i++)
  501.       for (j = 0; j < wheelrows/2; j++) {
  502.         k = wheelrows-1-j;
  503.         l = wheel[i][j]; wheel[i][j] = wheel[i][k]; wheel[i][k] = l;
  504.       }
  505.  
  506.   /* Here we actually print the wheel and the objects in it. */
  507.  
  508.   printc(BOXNW); PrintTab(BOXH, WHEELCOLS-8); PrintHouse(11, TRUE);
  509.   PrintTab(BOXH, WHEELCOLS-11); PrintHouse(10, TRUE);
  510.   PrintTab(BOXH, WHEELCOLS-10); PrintHouse(9, TRUE);
  511.   PrintTab(BOXH, wheelcols-4); fprintf(S, "%c\n", BOXNE);
  512.   for (i = 0; i < wheelrows; i++) {
  513.     for (j = 10; j >= 7; j--) {
  514.       printc(BOXV); PrintWheelSlot(wheel[j][i], wheelcols);
  515.     }
  516.     fprintf(S, "%c\n", BOXV);
  517.   }
  518.   PrintHouse(12, TRUE); PrintTab(BOXH, WHEELCOLS-11);
  519.   printc(BOXC); PrintTab(BOXH, wheelcols-1); printc(BOXJN);
  520.   PrintTab(BOXH, wheelcols-1); printc(BOXC); PrintTab(BOXH, WHEELCOLS-10);
  521.   PrintHouse(8, FALSE); printl();
  522.   for (i = 0; i < wheelrows; i++) {
  523.     printc(BOXV); PrintWheelSlot(wheel[11][i], wheelcols); printc(BOXV);
  524.  
  525.     /* For some rows, we have to insert the chart header information. */
  526.  
  527.     if (i) {
  528.       PrintTab(' ', wheelcols-11-(i == 2 && !eurotime));
  529.       if (i == 1)
  530.         fprintf(S, "%s (%s) chart", appname, VERSION);
  531.       else if (i == 2) {
  532.         j = DayOfWeek(Mon, Day, Yea);
  533.         k = (int) (FRACT(dabs(Tim))*100.0+ROUND);
  534.         fprintf(S, "%c%c%c %s %s", DAYNAM(j), CharDate(Mon, Day, Yea, 2),
  535.           CharTime((int)floor(Tim), k));
  536.       } else if (i == 3) {
  537.         fprintf(S, "%c%02d:", Zon > 0.0 ? '-' : '+', (int)dabs(Zon));
  538.         j = (int) (FRACT(dabs(Zon))*100.0+ROUND);
  539.         fprintf(S, "%02d %s", j, CharLocation(Lon, Lat, 100.0));
  540.       } else
  541.         PrintTab(' ', 21);
  542.       PrintTab(' ', wheelcols-11-(i == 2 && !eurotime));
  543.  
  544.     } else
  545.       PrintTab(' ', wheelcols*2-1);
  546.     printc(BOXV); PrintWheelSlot(wheel[6][i], wheelcols);
  547.     fprintf(S, "%c\n", BOXV);
  548.   }
  549.   PrintHouse(1, TRUE); PrintTab(BOXH, WHEELCOLS-10);
  550.   printc(BOXJW); PrintTab(' ', wheelcols-11);
  551.   fprintf(S, "%s", systemname[housesystem]);
  552.   PrintTab(' ', 14-StringLen(systemname[housesystem]));
  553.   fprintf(S, "Houses."); PrintTab(' ', wheelcols-11); printc(BOXJE);
  554.   PrintTab(BOXH, WHEELCOLS-10); PrintHouse(7, FALSE); printl();
  555.   for (i = 0; i < wheelrows; i++) {
  556.     printc(BOXV); PrintWheelSlot(wheel[0][i], wheelcols); printc(BOXV);
  557.     if (i == 0) {
  558.       PrintTab(' ', wheelcols-12);
  559.       fprintf(S, "Julian Day = %10.2f", JulianDayFromTime(T));
  560.       PrintTab(' ', wheelcols-12);
  561.     } else
  562.       PrintTab(' ', wheelcols*2-1);
  563.     printc(BOXV); PrintWheelSlot(wheel[5][i], wheelcols);
  564.     fprintf(S, "%c\n", BOXV);
  565.   }
  566.   PrintHouse(2, TRUE); PrintTab(BOXH, WHEELCOLS-10);
  567.   printc(BOXC); PrintTab(BOXH, wheelcols-1); printc(BOXJS);
  568.   PrintTab(BOXH, wheelcols-1); printc(BOXC);
  569.   PrintTab(BOXH, WHEELCOLS-10); PrintHouse(6, FALSE); printl();
  570.   for (i = 0; i < wheelrows; i++) {
  571.     for (j = 1; j <= 4; j++) {
  572.       printc(BOXV); PrintWheelSlot(wheel[j][i], wheelcols);
  573.     }
  574.     fprintf(S, "%c\n", BOXV);
  575.   }
  576.   printc(BOXSW); PrintTab(BOXH, wheelcols-4); PrintHouse(3, FALSE);
  577.   PrintTab(BOXH, WHEELCOLS-10); PrintHouse(4, FALSE);
  578.   PrintTab(BOXH, WHEELCOLS-10); PrintHouse(5, FALSE);
  579.   PrintTab(BOXH, WHEELCOLS-7); fprintf(S, "%c\n", BOXSE);
  580.   seconds = -seconds;
  581. }
  582.  
  583.  
  584. /* Display all aspects between objects in the chart, one per line, in       */
  585. /* sorted order based on the total "power" of the aspect, as specified with */
  586. /* the -m0 switch. The same influences used for -I charts are used here.    */
  587.  
  588. void ChartAspect()
  589. {
  590.   int pcut = 30000, icut, jcut, phi, ihi, jhi, ahi, p, i, j, k, count = 0;
  591.   real ip, jp;
  592.  
  593.   loop {
  594.     phi = -1;
  595.  
  596.     /* Search for the next most powerful aspect in the aspect grid. */
  597.  
  598.     for (i = 2; i <= total; i++) if (!ignore[i])
  599.       for (j = 1; j < i; j++) if (!ignore[j])
  600.         if (k = grid->n[j][i]) {
  601.           ip = i <= OBJECTS ? objectinf[i] : 2.5;
  602.           jp = j <= OBJECTS ? objectinf[j] : 2.5;
  603.           p = (int) (aspectinf[k]*(ip+jp)/2.0*
  604.             (1.0-dabs((real)(grid->v[j][i]))/60.0/aspectorb[k])*1000.0);
  605.           if ((p < pcut || (p == pcut && (i > icut ||
  606.             (i == icut && j > jcut)))) && p > phi) {
  607.             ihi = i; jhi = j; phi = p; ahi = k;
  608.           }
  609.         }
  610.     if (phi < 0)    /* Exit when no less powerful aspect found. */
  611.       break;
  612.     pcut = phi; icut = ihi; jcut = jhi;
  613.     count++;                               /* Display the current aspect.   */
  614. #ifdef INTERPRET
  615.     if (interpret) {                       /* Interpret it if -I in effect. */
  616.       InterpretAspect(jhi, ihi);
  617.       continue;
  618.     }
  619. #endif
  620.     fprintf(S, "%3d: ", count);
  621.     PrintAspect(jhi, ZTOS(planet[jhi]), (int)Sgn(ret[jhi]), ahi,
  622.       ihi, ZTOS(planet[ihi]), (int)Sgn(ret[ihi]), 'a');
  623.     k = grid->v[jhi][ihi];
  624.     AnsiColor(k < 0 ? WHITE : LTGRAY);
  625.     fprintf(S, " - orb: %c%d%c%02d'",
  626.       exdisplay & DASHga ? (k < 0 ? 'a' : 's') : (k < 0 ? '-' : '+'),
  627.       abs(k)/60, DEGR1, abs(k)%60);
  628.     AnsiColor(DKGREEN);
  629.     fprintf(S, " - power:%6.2f\n", (real) phi/1000.0);
  630.     AnsiColor(DEFAULT);
  631.   }
  632. }
  633.  
  634.  
  635. /* Display locations of all midpoints between objects in the chart, */
  636. /* one per line, in sorted zodiac order from zero Aries onward, as  */
  637. /* specified with the -m switch.                                    */
  638.  
  639. void ChartMidpoint()
  640. {
  641.   int mcut = -1, icut, jcut, mlo, ilo, jlo, m, i, j, count = 0;
  642.  
  643.   loop {
  644.     mlo = 21600;
  645.  
  646.     /* Search for the next closest midpoint farther down in the zodiac. */ 
  647.  
  648.     for (i = 1; i < total; i++) if (!ignore[i])
  649.       for (j = i+1; j <= total; j++) if (!ignore[j]) {
  650.         m = (grid->n[j][i]-1)*30*60 + grid->v[j][i];
  651.         if ((m > mcut || (m == mcut && (i > icut ||
  652.           (i == icut && j > jcut)))) && m < mlo) {
  653.           ilo = i; jlo = j; mlo = m;
  654.         }
  655.       }
  656.     if (mlo >= 21600)    /* Exit when no midpoint farther in zodiac found. */
  657.       break;
  658.     mcut = mlo; icut = ilo; jcut = jlo;
  659.     count++;                               /* Display the current midpoint. */
  660. #ifdef INTERPRET
  661.     if (interpret) {                       /* Interpret it if -I in effect. */
  662.       InterpretMidpoint(ilo, jlo);
  663.       continue;
  664.     }
  665. #endif
  666.     fprintf(S, "%4d: ", count);
  667.     PrintZodiac((real) mlo/60.0);
  668.     printc(' ');
  669.     PrintAspect(ilo, ZTOS(planet[ilo]), (int)Sgn(ret[ilo]), 0,
  670.       jlo, ZTOS(planet[jlo]), (int)Sgn(ret[jlo]), 'm');
  671.     AnsiColor(DEFAULT);
  672.     m = (int)(MinDistance(planet[ilo], planet[jlo])*60.0);
  673.     fprintf(S, "-%4d%c%02d' degree span.\n", m/60, DEGR1, m%60);
  674.   }
  675. }
  676.  
  677.  
  678. /* Display locations of the objects on the screen with respect to the local */
  679. /* horizon, as specified with the -Z switch.                                */
  680.  
  681. void ChartHorizon()
  682. {
  683.   real lon, lat, sx, sy, vx, vy,
  684.     lonz[TOTAL+1], latz[TOTAL+1], azi[TOTAL+1], alt[TOTAL+1];
  685.   int prime, i, j, k, tot;
  686.  
  687.   /* Set up some initial variables. */
  688.  
  689.   prime = (exdisplay & DASHZ0) > 0;
  690.   lon = DTOR(Mod(Lon)); lat = DTOR(Lat);
  691.   tot = universe ? total : BASE;
  692.  
  693.   /* First find zenith location on Earth of each object. */
  694.  
  695.   for (i = 1; i <= tot; i++) {
  696.     lonz[i] = DTOR(planet[i]); latz[i] = DTOR(planetalt[i]);
  697.     EclToEqu(&lonz[i], &latz[i]);
  698.   }
  699.  
  700.   /* Then, convert this to local horizon altitude and azimuth. */
  701.  
  702.   for (i = 1; i <= tot; i++) if (i != _MC) {
  703.     lonz[i] = DTOR(Mod(RTOD(lonz[_MC]-lonz[i]+lon)));
  704.     lonz[i] = DTOR(Mod(RTOD(lonz[i]-lon+PI/2.0)));
  705.     EquToLocal(&lonz[i], &latz[i], PI/2.0-lat);
  706.     azi[i] = DEGREES-RTOD(lonz[i]); alt[i] = RTOD(latz[i]);
  707.   }
  708.  
  709.   /* If the -Z0 switch flag is in effect, convert from altitude/azimuth  */
  710.   /* coordinates to prime vertical coordinates that we'll print instead. */
  711.  
  712.   if (prime) {
  713.     for (i = 1; i <= tot; i++) {
  714.       azi[i] = DTOR(azi[i]); alt[i] = DTOR(alt[i]);
  715.       CoorXform(&azi[i], &alt[i], PI/2.0);
  716.       azi[i] = RTOD(azi[i]); alt[i] = RTOD(alt[i]);
  717.     }
  718.   }
  719.  
  720.   /* Now, actually print the location of each object. */
  721.  
  722.   fprintf(S,
  723.     "Body Altitude Azimuth  Azi. Vector   %s Vector    Moon Vector\n\n",
  724.     centerplanet ? " Sun" : " Earth");
  725.   for (k = 1; k <= tot; k++) {
  726.     i = k <= BASE ? k : BASE+starname[k-BASE];
  727.     if (ignore[i] || !IsThing(i))
  728.       continue;
  729.     AnsiColor(objectansi[i]);
  730.     fprintf(S, "%-4.4s: ", objectname[i]);
  731.     PrintAltitude(alt[i]);
  732.  
  733.     /* Determine directional vector based on azimuth. */
  734.  
  735.     j = (int) (FRACT(azi[i])*60.0);
  736.     fprintf(S, " %3d%c%02d'", (int) azi[i], DEGR1, j);
  737.     sx = cos(DTOR(azi[i])); sy = sin(DTOR(azi[i]));
  738.     if (dabs(sx) < dabs(sy)) {
  739.       vx = dabs(sx / sy); vy = 1.0;
  740.     } else {
  741.       vy = dabs(sy / sx); vx = 1.0;
  742.     }
  743.     fprintf(S, " (%.2f%c", vy,
  744.       sy < 0.0 ? (prime ? 'u' : 's') : (prime ? 'd' : 'n'));
  745.     fprintf(S, " %.2f%c)", vx,
  746.       sx > 0.0 ? 'e' : 'w');
  747.  
  748.     /* Determine distance vector of current object from Sun and Moon. */
  749.  
  750.     vx = azi[1]-azi[i]; vy = azi[2]-azi[i];
  751.     fprintf(S, " [%6.1f%6.1f] [%6.1f%6.1f]",
  752.       dabs(vx) < DEGHALF ? vx : Sgn(vx)*(DEGREES-dabs(vx)), alt[1]-alt[i],
  753.       dabs(vy) < DEGHALF ? vy : Sgn(vy)*(DEGREES-dabs(vy)), alt[2]-alt[i]);
  754.     if (i >= U_LO) {
  755.       if (i <= U_HI)
  756.         fprintf(S, "  Uranian #%d", i-U_LO+1);
  757.       else
  758.         fprintf(S, "  Star #%2d", i-S_LO+1);
  759.     }
  760.     printl();
  761.   }
  762.   AnsiColor(DEFAULT);
  763. }
  764.  
  765.  
  766. /* Display x,y,z locations of each body (in AU) with respect to the Sun */
  767. /* (or whatever the specified center planet is), as in the -S switch.   */
  768. /* These values were already determined when calculating the planet     */
  769. /* positions themselves, so this procedure is basically just a loop.    */
  770.  
  771. void ChartSpace()
  772. {
  773.   real x, y, z;
  774.   int i;
  775.  
  776.   fprintf(S, "Body     Angle    X axis    Y axis    Z axis    Length\n");
  777.   for (i = 0; i <= BASE; i++) {
  778.     if (ignore[i] || (i == _MOO && !placalc) || !IsObject(i))
  779.       continue;
  780.     AnsiColor(objectansi[i]);
  781.     fprintf(S, "%c%c%c%c: ", OBJNAM(i),
  782.       objectname[i][3] ? objectname[i][3] : ' ');
  783.     x = spacex[i]; y = spacey[i]; z = spacez[i];
  784.     fprintf(S, "[%7.2f] [%7.3f] [%7.3f] [%7.3f] [%7.3f]",
  785.       planet[i], x, y, z, sqrt(x*x+y*y+z*z));
  786.     if (i >= U_LO) {
  787.       if (i <= U_HI)
  788.         fprintf(S, "  Uranian #%d", i-U_LO+1);
  789.       else
  790.         fprintf(S, "  Star #%2d", i-S_LO+1);
  791.     }
  792.     printl();
  793.   }
  794.   AnsiColor(DEFAULT);
  795. }
  796.  
  797.  
  798. /* Print the locations of the astro-graph lines on the Earth as specified */
  799. /* with the -L switch. This includes Midheaven and Nadir lines, zenith    */
  800. /* positions, and locations of Ascendant and Descendant lines.            */
  801.  
  802. void ChartAstroGraph()
  803. {
  804.   crosstruct PTR c;
  805.   real planet1[TOTAL+1], planet2[TOTAL+1], mc[TOTAL+1], ic[TOTAL+1],
  806.     as[TOTAL+1], ds[TOTAL+1], as1[TOTAL+1], ds1[TOTAL+1],
  807.     lo = Lon, longm, w, x, y, z, ad, oa, am, od, dm;
  808.   int occurcount = 0, tot = total, i, j, k, l, m, n;
  809.  
  810.   if (exdisplay & DASHL0)
  811.     {
  812.     Allocate(c, sizeof(crosstruct), crosstruct PTR);
  813.     if (c == NULL
  814. #ifdef PC
  815.       /* For PC's the array better not cross a segment boundary. */
  816.       || HIWORD(LOWORD(c) + sizeof(crosstruct)) > 0
  817. #endif
  818.       ) {
  819.       PrintError("Not enough memory for crossing table.");
  820.       return;
  821.     }
  822.   }
  823.  
  824. #ifdef MATRIX
  825.   for (i = 1; i <= total; i++) {
  826.     planet1[i] = DTOR(planet[i]);
  827.     planet2[i] = DTOR(planetalt[i]);      /* Calculate zenith location on */
  828.     EclToEqu(&planet1[i], &planet2[i]);   /* Earth of each object.        */
  829.   }
  830.  
  831.   /* Print header. */
  832.  
  833.   fprintf(S, "Object :");
  834.   for (j = 0, i = 1; i <= total; i++)
  835.     if (!ignore[i] && IsThing(i)) {
  836.       AnsiColor(objectansi[i]);
  837.       fprintf(S, " %c%c%c", OBJNAM(i));
  838.       j++;
  839.       if (column80 && j >= 17) {
  840.         tot = i;
  841.         i = total;
  842.       }
  843.     }
  844.   AnsiColor(DEFAULT);
  845.   fprintf(S, "\n------ :");
  846.   for (i = 1; i <= tot; i++)
  847.     if (!ignore[i] && IsThing(i))
  848.       fprintf(S, " ###");
  849.  
  850.   /* Print the longitude locations of the Midheaven lines. */
  851.  
  852.   fprintf(S, "\nMidheav: ");
  853.   if (lo < 0.0)
  854.     lo += DEGREES;
  855.   for (i = 1; i <= tot; i++)
  856.     if (!ignore[i] && IsThing(i)) {
  857.     AnsiColor(objectansi[i]);
  858.     x = DTOR(MC)-planet1[i];
  859.     if (x < 0.0)
  860.       x += 2.0*PI;
  861.     if (x > PI)
  862.       x -= 2.0*PI;
  863.     z = lo+RTOD(x);
  864.     if (z > DEGHALF)
  865.       z -= DEGREES;
  866.     mc[i] = z;
  867.     fprintf(S, "%3.0f%c", dabs(z), z < 0.0 ? 'e' : 'w');
  868.   }
  869.   AnsiColor(DEFAULT);
  870.  
  871.   /* The Nadir lines are just always 180 degrees away from the Midheaven. */
  872.  
  873.   fprintf(S, "\nNadir  : ");
  874.   for (i = 1; i <= tot; i++)
  875.     if (!ignore[i] && IsThing(i)) {
  876.     AnsiColor(objectansi[i]);
  877.     z = mc[i] + DEGHALF;
  878.     if (z > DEGHALF)
  879.       z -= DEGREES;
  880.     ic[i] = z;
  881.     fprintf(S, "%3.0f%c", dabs(z), z < 0.0 ? 'e' : 'w');
  882.   }
  883.   AnsiColor(DEFAULT);
  884.  
  885.   /* Print the Zenith latitude locations. */
  886.  
  887.   fprintf(S, "\nZenith : ");
  888.   for (i = 1; i <= tot; i++)
  889.     if (!ignore[i] && IsThing(i)) {
  890.       AnsiColor(objectansi[i]);
  891.       y = RTOD(planet2[i]);
  892.       fprintf(S, "%3.0f%c", dabs(y), y < 0.0 ? 's' : 'n');
  893.       as[i] = ds[i] = as1[i] = ds1[i] = LARGE;
  894.     }
  895.   printl2();
  896.  
  897.   /* Now print the locations of Ascendant and Descendant lines. Since these */
  898.   /* are curvy, we loop through the latitudes, and for each object at each  */
  899.   /* latitude, print the longitude location of the line in question.        */
  900.  
  901.   longm = DTOR(Mod(MC+lo));
  902.   for (j = 80; j >= -80; j -= graphstep) {
  903.     AnsiColor(DEFAULT); 
  904.     fprintf(S, "Asc@%2d%c: ", j >= 0 ? j : -j, j < 0 ? 's' : 'n');
  905.     for (i = 1; i <= tot; i++)
  906.       if (!ignore[i] && IsThing(i)) {
  907.       AnsiColor(objectansi[i]);
  908.       ad = tan(planet2[i])*tan(DTOR(j));
  909.       if (ad*ad > 1.0) {
  910.         fprintf(S, " -- ");
  911.         as1[i] = ds1[i] = ret2[i] = LARGE;
  912.       } else {
  913.         ad = ASIN(ad);
  914.         oa = planet1[i]-ad;
  915.         if (oa < 0.0)
  916.           oa += 2.0*PI;
  917.         am = oa-PI/2.0;
  918.         if (am < 0.0)
  919.           am += 2.0*PI;
  920.         z = longm-am;
  921.         if (z < 0.0)
  922.           z += 2.0*PI;
  923.         if (z > PI)
  924.           z -= 2.0*PI;
  925.         as1[i] = as[i];
  926.         as[i] = z = RTOD(z);
  927.         ret2[i] = ad;
  928.         fprintf(S, "%3.0f%c", dabs(z), z < 0.0 ? 'e' : 'w');
  929.       }
  930.     }
  931.  
  932.     /* Again, the Descendant position is related to the Ascendant's,  */
  933.     /* being a mirror image, so it can be calculated somewhat easier. */
  934.  
  935.     AnsiColor(DEFAULT);
  936.     fprintf(S, "\nDsc@%2d%c: ", j >= 0 ? j : -j, j < 0 ? 's' : 'n');
  937.     for (i = 1; i <= tot; i++)
  938.       if (!ignore[i] && IsThing(i)) {
  939.       AnsiColor(objectansi[i]);
  940.       ad = ret2[i];
  941.       if (ad == LARGE)
  942.         fprintf(S, " -- ");
  943.       else {
  944.         od = planet1[i]+ad;
  945.         dm = od+PI/2.0;
  946.         z = longm-dm;
  947.         if (z < 0.0)
  948.           z += 2.0*PI;
  949.         if (z > PI)
  950.           z -= 2.0*PI;
  951.         ds1[i] = ds[i];
  952.         ds[i] = z = RTOD(z);
  953.         fprintf(S, "%3.0f%c", dabs(z), z < 0.0 ? 'e' : 'w');
  954.       }
  955.     }
  956.     printl();
  957. #endif /* MATRIX */
  958.  
  959.     /* Now, if the -L0 switch is in effect, then take these line positions, */
  960.     /* which we saved in an array above as we were printing them, and       */
  961.     /* calculate and print the latitude crossings.                          */
  962.  
  963.     if (exdisplay & DASHL0)
  964.       for (l = 1; l <= total; l++) if (!ignore[l] && IsThing(l))
  965.         for (k = 1; k <= total; k++) {
  966.           if (ignore[k] || !IsThing(k))
  967.             continue;
  968.           for (n = 0; n <= 1; n++) {
  969.             x = n ? ds1[l] : as1[l];
  970.             y = n ? ds[l] : as[l];
  971.             for (m = 0; m <= 1; m++) {
  972.  
  973.             /* Check if Ascendant/Descendant cross Midheaven/Nadir. */
  974.  
  975.             z = m ? ic[k] : mc[k];
  976.             if (occurcount < MAXCROSS &&
  977.               dabs(x-y) < DEGHALF && Sgn(z-x) != Sgn(z-y)) {
  978.               c->obj1[occurcount] = n ? -l : l;
  979.               c->obj2[occurcount] = m ? -k : k;
  980.               c->lat[occurcount] = (real)j+5.0*dabs(z-y)/dabs(x-y);
  981.               c->lon[occurcount] = z;
  982.               occurcount++;
  983.             }
  984.  
  985.             /* Check if Ascendant/Descendant cross another Asc/Des. */
  986.  
  987.             w = m ? ds1[k] : as1[k];
  988.             z = m ? ds[k] : as[k];
  989.             if (occurcount < MAXCROSS && k > l &&
  990.                 dabs(x-y)+dabs(w-z) < DEGHALF && Sgn(w-x) != Sgn(z-y)) {
  991.               c->obj1[occurcount] = n ? -l : l;
  992.               c->obj2[occurcount] = 100+(m ? -k : k);
  993.               c->lat[occurcount] = (real)j+5.0*
  994.                 dabs(y-z)/(dabs(x-w)+dabs(y-z));
  995.               c->lon[occurcount] = MIN(x, y)+dabs(x-y)*
  996.                 dabs(y-z)/(dabs(x-w)+dabs(y-z));
  997.               occurcount++;
  998.             }
  999.           }
  1000.         }
  1001.     }
  1002.   }
  1003.   if ((exdisplay & DASHL0) == 0)
  1004.     return;
  1005.   printl();
  1006.  
  1007.   /* Now, print out all the latitude crossings we found.  */
  1008.   /* First, we sort them in order of decreasing latitude. */
  1009.  
  1010.   for (i = 1; i < occurcount; i++) {
  1011.     j = i-1;
  1012.     while (j >= 0 && c->lat[j] < c->lat[j+1]) {
  1013.       SWAP(c->obj1[j], c->obj1[j+1]); SWAP(c->obj2[j], c->obj2[j+1]);
  1014.       SwapReal(&c->lat[j], &c->lat[j+1]); SwapReal(&c->lon[j], &c->lon[j+1]);
  1015.       j--;
  1016.     }
  1017.   }
  1018.   for (i = 1; i < occurcount; i++) {
  1019.     j = abs(c->obj1[i]);
  1020.     AnsiColor(objectansi[j]);
  1021.     fprintf(S, "%c%c%c ", OBJNAM(j));
  1022.     AnsiColor(elemansi[c->obj1[i] > 0 ? _FIR : _AIR]);
  1023.     fprintf(S, "%s ", c->obj1[i] > 0 ? "Ascendant " : "Descendant");
  1024.     AnsiColor(WHITE);
  1025.     fprintf(S, "crosses ");
  1026.     j = abs(c->obj2[i] - (c->obj2[i] < 50 ? 0 : 100));
  1027.     AnsiColor(objectansi[j]);
  1028.     fprintf(S, "%c%c%c ", OBJNAM(j));
  1029.     AnsiColor(elemansi[c->obj2[i] < 50 ?
  1030.       (c->obj2[i] > 0 ? _EAR : _WAT) : (c->obj2[i] > 100 ? _FIR : _AIR)]);
  1031.     fprintf(S, "%s ", c->obj2[i] < 50 ? (c->obj2[i] > 0 ? "Midheaven " :
  1032.       "Nadir     ") : (c->obj2[i] > 100 ? "Ascendant " : "Descendant"));
  1033.     j = (int) (FRACT(dabs(c->lon[i]))*60.0);
  1034.     AnsiColor(DEFAULT);
  1035.     fprintf(S, "at %3d%c%02d'%c, ", (int) dabs(c->lon[i]), DEGR1,
  1036.       j, c->lon[i] < 0.0 ? 'E' : 'W');
  1037.     j = (int) (FRACT(dabs(c->lat[i]))*60.0);
  1038.     fprintf(S, "%2d%c%02d'%c\n", (int) dabs(c->lat[i]), DEGR1,
  1039.       j, c->lat[i] < 0.0 ? 'S' : 'N');
  1040.   }
  1041.   Deallocate(c);
  1042.   if (!occurcount) {
  1043.     AnsiColor(DEFAULT);
  1044.     fprintf(S, "No latitude crossings.\n");
  1045.   }
  1046. }
  1047.  
  1048. /* charts.c */
  1049.