home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Astrolog (Version 4.00) File: xgeneral.c
- **
- ** IMPORTANT NOTICE: the graphics database and chart display routines
- ** used in this program are Copyright (C) 1991-1993 by Walter D. Pullen
- ** (cruiser1@stein.u.washington.edu). Permission is granted to freely
- ** use and distribute these routines provided one doesn't sell,
- ** restrict, or profit from them in any way. Modification is allowed
- ** provided these notices remain with any altered or edited versions of
- ** the program.
- **
- ** The main planetary calculation routines used in this program have
- ** been Copyrighted and the core of this program is basically a
- ** conversion to C of the routines created by James Neely as listed in
- ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
- ** available from Matrix Software. The copyright gives us permission to
- ** use the routines for personal use but not to sell them or profit from
- ** them in any way.
- **
- ** The PostScript code within the core graphics routines are programmed
- ** and Copyright (C) 1992-1993 by Brian D. Willoughby
- ** (brianw@sounds.wa.com). Conditions are identical to those above.
- **
- ** The extended accurate ephemeris databases and formulas are from the
- ** calculation routines in the program "Placalc" and are programmed and
- ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
- ** (alois@azur.ch). The use of that source code is subject to
- ** regulations made by Astrodienst Zurich, and the code is not in the
- ** public domain. This copyright notice must not be changed or removed
- ** by any user of this program.
- **
- ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
- ** X Window graphics initially programmed 10/23-29/1991.
- ** PostScript graphics initially programmed 11/29-30/1992.
- ** Last code change made 12/31/1993.
- */
-
- #include "astrolog.h"
-
- #ifdef GRAPH
-
- int xpen, ypen;
-
-
- /*
- ******************************************************************************
- ** Bitmap File Routines.
- ******************************************************************************
- */
-
- /* Write the bitmap array to a previously opened file in a format that */
- /* can be read in by the Unix X commands bitmap and xsetroot. The 'mode' */
- /* parameter defines how much white space is put in the file. */
-
- void WriteXBitmap(data, name, mode)
- FILE *data;
- char *name, mode;
- {
- int x, y, i, temp = 0;
- uint value;
-
- fprintf(data, "#define %s_width %d\n" , name, chartx);
- fprintf(data, "#define %s_height %d\n", name, charty);
- fprintf(data, "static %s %s_bits[] = {",
- mode != 'V' ? "char" : "short", name);
- for (y = 0; y < charty; y++) {
- x = 0;
- do {
-
- /* Process each row, eight columns at a time. */
-
- if (y + x > 0)
- fprintf(data, ",");
- if (temp == 0)
- fprintf(data, "\n%s",
- mode == 'N' ? " " : (mode == 'C' ? " " : ""));
- value = 0;
- for (i = (mode != 'V' ? 7 : 15); i >= 0; i--)
- value = (value << 1) +
- (!(PGET(bm, x+i, y)^(xreverse*15))^xreverse && (x + i < chartx));
- if (mode == 'N')
- putc(' ', data);
- fprintf(data, "0x");
- if (mode == 'V')
- fprintf(data, "%c%c",
- INTTOHEX(value >> 12), INTTOHEX((value >> 8) & 15));
- fprintf(data, "%c%c",
- INTTOHEX((value >> 4) & 15), INTTOHEX(value & 15));
- temp++;
-
- /* Is it time to skip to the next line while writing the file yet? */
-
- if ((mode == 'N' && temp >= 12) ||
- (mode == 'C' && temp >= 15) ||
- (mode == 'V' && temp >= 11))
- temp = 0;
- x += (mode != 'V' ? 8 : 16);
- } while (x < chartx);
- }
- fprintf(data, "};\n");
- }
-
-
- /* Write the bitmap array to a previously opened file in a simple boolean */
- /* Ascii rectangle, one char per pixel, where '#' represents an off bit and */
- /* '-' an on bit. The output format is identical to the format generated by */
- /* the Unix bmtoa command, and it can be converted into a bitmap with atobm. */
-
- void WriteAscii(data)
- FILE *data;
- {
- int x, y, i;
-
- for (y = 0; y < charty; y++) {
- for (x = 0; x < chartx; x++) {
- i = PGET(bm, x, y);
- if (xcolor)
- putc(INTTOHEX(i), data);
- else
- putc(i ? '-' : '#', data);
- }
- putc('\n', data);
- }
- }
-
-
- /* Write the bitmap array to a previously opened file in the bitmap format */
- /* used in Microsoft Windows for its .bmp extension files. This is a pretty */
- /* efficient format, only requiring one bit per pixel and a small header. */
-
- void WriteBmp(data)
- FILE *data;
- {
- int x, y;
- dword value;
-
- /* BitmapFileHeader */
- PutByte('B'); PutByte('M');
- PutLong(14+40 + (xcolor ? 64 : 8) +
- (long)4*charty*((chartx-1 >> (xcolor ? 3 : 5))+1));
- PutWord(0); PutWord(0);
- PutLong(14+40 + (xcolor ? 64 : 8));
- /* BitmapInfo / BitmapInfoHeader */
- PutLong(40);
- PutLong(chartx); PutLong(charty);
- PutWord(1); PutWord(xcolor ? 4 : 1);
- PutLong(0 /*BI_RGB*/); PutLong(0);
- PutLong(0); PutLong(0);
- PutLong(0); PutLong(0);
- /* RgbQuad */
- if (xcolor)
- for (x = 0; x < 16; x++) {
- PutByte(RGBB(rgbbmp[x])); PutByte(RGBG(rgbbmp[x]));
- PutByte(RGBR(rgbbmp[x])); PutByte(0);
- }
- else {
- PutLong(0);
- PutByte(255); PutByte(255); PutByte(255); PutByte(0);
- }
- /* Data */
- for (y = charty-1; y >= 0; y--) {
- value = 0;
- for (x = 0; x < chartx; x++) {
- if ((x & (xcolor ? 7 : 31)) == 0 && x > 0) {
- PutLong(value);
- value = 0;
- }
- if (xcolor)
- value |= (dword)PGET(bm, x, y) << ((x & 7 ^ 1) << 2);
- else
- if (PGET(bm, x, y))
- value |= (dword)1 << (x & 31 ^ 7);
- }
- PutLong(value);
- }
- }
-
-
- /* Output the bitmap in memory to a file. This basically consists of just */
- /* calling some routine to actually write a bitmap to a file, although we */
- /* need to prompt the user for a filename if it wasn't specified beforehand. */
-
- void WriteFile()
- {
- char line[STRING];
- FILE *data;
-
- #ifdef PS
- if (psfile) {
- PSend();
- return;
- }
- #endif
- if (outputfile == NULL && (metafile || (xbitmap && bitmapmode == 'B')))
- fprintf(stdout, "(It is recommended to specify an extension of '.%s'.)\n",
- xbitmap ? "bmp" : "wmf");
- loop {
- if (outputfile == NULL) {
- sprintf(line, "Enter name of file to write %s to",
- xbitmap ? "bitmap" : "metafile");
- InputString(line, line);
- outputfile = line;
- }
- data = fopen(outputfile, "wb");
- if (data != NULL)
- break;
- else {
- PrintWarning("Couldn't create output file.");
- outputfile = NULL;
- }
- }
- if (xbitmap) {
- if (bitmapmode == 'B')
- WriteBmp(data);
- else if (bitmapmode == 'A')
- WriteAscii(data);
- else
- WriteXBitmap(data, outputfile, bitmapmode);
- }
- #ifdef META
- else
- WriteMeta(data);
- #endif
- fclose(data);
- }
-
-
- /*
- ******************************************************************************
- ** PostScript File Routines.
- ******************************************************************************
- */
-
- #ifdef PS
-
- /* Global variables used by the PostScript generator. */
-
- FILE *psdata;
- int strokecount = 0, currentlinecap = 0, currentdash = 0, currentfont = 0;
- real currentlinewidth = 1.0;
-
- /* Table of PostScript header alias lines used by the program. */
-
- char PSfunctions[] =
- "/languagelevel where{pop languagelevel}{1}ifelse\
- 2 lt{\n\
- /sf{exch findfont exch\
- dup type/arraytype eq{makefont}{scalefont}ifelse setfont}bind def\n\
- /rf{gsave newpath\n\
- 4 -2 roll moveto\
- dup 0 exch rlineto exch 0 rlineto neg 0 exch rlineto closepath\n\
- fill grestore}bind def\n\
- /rc{newpath\n\
- 4 -2 roll moveto\
- dup 0 exch rlineto exch 0 rlineto neg 0 exch rlineto closepath\n\
- clip newpath}bind def\n\
- }{/sf/selectfont load def/rf/rectfill load def\
- /rc/rectclip load def}ifelse\n\
- /center{0 begin gsave dup 4 2 roll\
- translate newpath 0 0 moveto\
- false charpath flattenpath pathbbox\
- /URy exch def/URx exch def/LLy exch def/LLx exch def\
- URx LLx sub 0.5 mul LLx add neg URy LLy sub 0.5 mul LLy add neg\
- 0 0 moveto rmoveto\
- show grestore end}bind def\n\
- /center load 0 4 dict put\n\
- /c{setrgbcolor}bind def\n\
- /d{moveto 0 0 rlineto}bind def\n\
- /l{4 2 roll moveto lineto}bind def\n\
- /t{lineto}bind def\n\
- /el{newpath matrix currentmatrix 5 1 roll translate scale\
- 0 0 1 0 360 arc setmatrix stroke}bind def\n";
-
-
- /* Write a command to flush the PostScript buffer. */
-
- void PSforcestroke()
- {
- if (strokecount > 0) { /* render any existing path */
- fprintf(psdata, "stroke\n");
- strokecount = 0;
- xpen = -1; /* Invalidate PolyLine cache */
- }
- }
-
-
- /* Indicate that a certain number of PostScript commands have been done. */
-
- void PSstroke(n)
- int n;
- {
- strokecount += n;
- if (strokecount > 5000) /* Whenever we reach a certain limit, flush. */
- PSforcestroke();
- }
-
-
- /* Set the type of line end to be used by PostScript commands. If linecap */
- /* is true, then the line ends are rounded, otherwise they are squared. */
-
- void PSlinecap(linecap)
- int linecap;
- {
- if (linecap != currentlinecap) {
- PSforcestroke();
- fprintf(psdata, "%d setlinecap\n", linecap);
- currentlinecap = linecap;
- }
- }
-
-
- /* Set the dash length to be used by PostScript line commands. */
-
- void PSdash(dashoff)
- int dashoff;
- {
- if (dashoff != currentdash) {
- PSforcestroke();
- if (dashoff)
- fprintf(psdata, "[%d %d", PSMUL, dashoff * PSMUL);
- else
- fprintf(psdata, "[");
- fprintf(psdata, "]0 setdash\n");
- currentdash = dashoff;
- }
- }
-
-
- /* Set a linewidth size to be used by PostScript figure primitive commands. */
-
- void PSlinewidth(linewidth)
- int linewidth;
- {
- real oldlinewidth = currentlinewidth;
-
- if (linewidth != currentlinewidth) {
- PSforcestroke();
- fprintf(psdata, "%d setlinewidth\n", linewidth);
- currentlinewidth = linewidth;
- }
- }
-
-
- /* Set a system font and size to be used by PostScript text commands. */
-
- void PSfont(psfont)
- int psfont;
- {
- int temp;
-
- if (psfont != currentfont && xfont) {
- if (psfont <= 2) {
- temp = psfont == 1 ? 32*PSMUL : 23*PSMUL;
- fprintf(psdata, "/Astro[%d 0 0 -%d 0 0]sf\n", temp, temp);
- } else if (psfont == 3) {
- temp = 26*PSMUL;
- fprintf(psdata, "/Times-Roman[%d 0 0 -%d 0 0]sf\n", temp, temp);
- } else {
- temp = 10*PSMUL;
- fprintf(psdata, "/Courier[%d 0 0 -%d 0 0]sf\n", temp, temp);
- }
- currentfont = psfont;
- }
- }
-
-
- /* Prompt the user for the name of a file to write the PostScript file to */
- /* (if not already specified), open it, and write out file header info. */
-
- void PSbegin()
- {
- char line[STRING];
-
- if (outputfile == NULL && epsfile)
- fprintf(stdout,
- "(It is recommended to specify an extension of '.eps'.)\n");
- loop {
- if (outputfile == NULL) {
- sprintf(line, "Enter name of file to write PostScript to");
- InputString(line, line);
- outputfile = line;
- }
- psdata = fopen(outputfile, "w");
- if (psdata != NULL)
- break;
- else {
- PrintWarning("Couldn't create output file.");
- outputfile = NULL;
- }
- }
- fprintf(psdata, "%%!PS-Adobe-2.0");
- if (epsfile)
- fprintf(psdata, " EPSF-2.0");
- fprintf(psdata, "\n%%%%Title: %s\n", outputfile);
- fprintf(psdata, "%%%%Creator: %s %s\n", appname, VERSION);
- fprintf(psdata, "%%%%CreationDate: %s\n", DATE);
- if (epsfile) {
- fprintf(psdata, "%%%%BoundingBox: 0 0 %d %d\n", chartx, charty);
- fprintf(psdata, "%%%%EndComments\n");
- fprintf(psdata, "%%%%BeginSetup\n");
- fprintf(psdata, PSfunctions, 6 * PSMUL, 6 * PSMUL);
- fprintf(psdata, "%%%%EndSetup\n");
- fprintf(psdata, "0 0 %d %d rc\n", chartx, charty);
- } else {
- fprintf(psdata, "%%%%Pages: 1 1\n");
- fprintf(psdata, "%%%%DocumentFonts: (atend)\n");
- fprintf(psdata, "%%%%BoundingBox: 9 9 603 783\n"); /* 8.5" x 11" */
- fprintf(psdata, "%%%%EndComments\n");
- fprintf(psdata, "%%%%BeginProcSet: common\n");
- fprintf(psdata, PSfunctions, 6 * PSMUL, 6 * PSMUL);
- fprintf(psdata, "%%%%EndProcSet\n");
- fprintf(psdata, "%%%%Page: 1 1\n");
- }
- PSfont(2);
- fprintf(psdata, "gsave\n");
- PSlinewidth(metawid/2);
- xpen = -1;
- }
-
-
- /* Write out trailing information to the PostScript file and close it. */
-
- void PSend()
- {
- PSforcestroke();
- if (epsfile)
- fprintf(psdata, "%%%%EOF\n");
- else {
- fprintf(psdata, "showpage\n");
- fprintf(psdata, "%%%%PageTrailer\n");
- fprintf(psdata, "%%%%Trailer\n");
- fprintf(psdata, "%%%%DocumentFonts: Times-Roman\n");
- if (xfont) {
- fprintf(psdata, "%%%%+ Courier\n");
- fprintf(psdata, "%%%%+ Astro\n");
- }
- }
- fclose(psdata);
- }
- #endif /* PS */
-
-
- /*
- ******************************************************************************
- ** Metafile Routines.
- ******************************************************************************
- */
-
- #ifdef META
-
- /* Global variables used by the metafile generator. */
-
- colpal metalinedes, metalineact = -1, /* Desired and actual line color. */
- metafilldes, metafillact = -1, /* Desired and actual fill color. */
- metafontdes = -1, metafontact = -1, /* Desired and actual text font. */
- metatxtcdes = -1, metatxtcact = -1, /* Desired and actual text color. */
- metatxtades = -1, metatxtaact = -1; /* Desired/actual text alignment. */
-
- /* Macros to output the various metafile commands we use. */
-
- #define MetaRecord(S, R) MetaLong((long)(S)); MetaWord(R)
- #define MetaSelectObject(O) MetaRecord(4, 0x12D); MetaWord(O)
- #define MetaDeleteObject(O) MetaRecord(4, 0x1F0); MetaWord(O)
- #define MetaSaveDc() MetaRecord(3, 0x01E)
- #define MetaRestoreDc() MetaRecord(4, 0x127); MetaWord(-1)
- #define MetaWindowOrg(X, Y) MetaRecord(5, 0x20B); MetaWord(Y); MetaWord(X)
- #define MetaWindowExt(X, Y) MetaRecord(5, 0x20C); MetaWord(Y); MetaWord(X)
- #define MetaCreatePen(S, W, C) MetaRecord(8, 0x2FA); MetaWord(S); \
- MetaWord(W); MetaWord(W); MetaLong(C)
- #define MetaCreateBrush(S, C) MetaRecord(7, 0x2FC); \
- MetaWord(S); MetaLong(C); MetaWord(0 /* Not used */);
- #define MetaCreateFont(S, X, Y, C) MetaRecord(12+(S), 0x2FB); MetaWord(Y); \
- MetaWord(X); MetaWord(0 /* Angle */); MetaWord(0 /* Not used */); \
- MetaWord(400 /* Normal Weight */); MetaWord(0 /* Italic, Underline */); \
- MetaWord(MAKEWORD(0 /* Strikeout */, C)); \
- MetaWord(MAKEWORD(4 /* TrueType */, 0 /* Clip */))
- #define MetaBkMode(M) MetaRecord(4, 0x102); MetaWord(M)
- #define MetaTextAlign(A) MetaRecord(4, 0x12E); MetaWord(A)
- #define MetaTextColor(C) MetaRecord(5, 0x209); MetaLong(C);
- #define MetaTextOut(X, Y, S) MetaRecord(7+((S)+1)/2, 0xA32); \
- MetaWord(Y); MetaWord(X); MetaWord(S); MetaWord(0 /* ETO */)
- #define MetaRectangle(X1, Y1, X2, Y2) MetaRecord(7, 0x41B); \
- MetaWord(Y2); MetaWord(X2); MetaWord(Y1); MetaWord(X1)
- #define MetaEllipse(X1, Y1, X2, Y2) MetaRecord(7, 0x418); \
- MetaWord(Y2); MetaWord(X2); MetaWord(Y1); MetaWord(X1)
- #define MetaEscape(S) MetaRecord((S), 0x626); \
- MetaWord(15 /* MFCOMMENT */); MetaWord(((S)-5)*2 /* Bytes in comment */);
-
-
- /* Output one 16 bit or 32 bit value into the metafile buffer stream. */
-
- void MetaWord(w)
- word w;
- {
- if ((byte PTR)metacur - bm >= MAXMETA) {
- PrintError("Metafile would be more than %ld bytes.", MAXMETA);
- Terminate(_FATAL);
- }
- *metacur = w;
- metacur++;
- }
-
- void MetaLong(l)
- long l;
- {
- MetaWord(LOWORD(l));
- MetaWord(HIWORD(l));
- }
-
-
- /* Output any necessary metafile records to make the current actual */
- /* settings of line color, fill color, etc, be those that we know are */
- /* desired. This is generally called by the primitives routines before */
- /* any figure record is actually written into a metafile. We wait until */
- /* the last moment before changing any settings to ensure that we don't */
- /* output any unnecessary records, e.g. two select colors in a row. */
-
- void MetaSelect()
- {
- if (metalinedes != metalineact) {
- MetaSelectObject(metalinedes);
- metalineact = metalinedes;
- }
- if (metafilldes != metafillact) {
- MetaSelectObject(16*4 + metafilldes);
- metafillact = metafilldes;
- }
- if (metafontdes != metafontact) {
- MetaSelectObject(16*5 + metafontdes);
- metafontact = metafontdes;
- }
- if (metatxtcdes != metatxtcact) {
- MetaTextColor(rgbbmp[metatxtcdes]);
- metatxtcact = metatxtcdes;
- }
- if (metatxtades != metatxtaact) {
- MetaTextAlign(metatxtades);
- metatxtaact = metatxtades;
- }
- xpen = -1; /* Invalidate PolyLine cache */
- }
-
-
- /* Output initial metafile header information into our metafile buffer. */
- /* We also setup and create all pen, brush, and font objects that may */
- /* possibly be used in the generation and playing of the picture. */
-
- void MetaInit()
- {
- int i, j, k;
-
- metacur = (word PTR)bm;
- /* Placable Metaheader */
- MetaLong(0x9AC6CDD7L);
- MetaWord(0); /* Not used */
- MetaWord(0); MetaWord(0);
- MetaWord(chartx); MetaWord(charty);
- MetaWord(chartx/6); /* Units per inch */
- MetaLong(0L); /* Not used */
- MetaWord(0x9AC6 ^ 0xCDD7 ^ chartx ^ charty ^ chartx/6); /* Checksum */
- /* Metaheader */
- MetaWord(1); /* Metafile type */
- MetaWord(9); /* Size of header in words */
- MetaWord(0x300); /* Windows version */
- MetaLong(0L); /* Size of entire metafile in words */
- MetaWord(16*5+1+(xfont>0)*4); /* Number of objects in metafile */
- MetaLong(17L); /* Size of largest record in words */
- MetaWord(0); /* Not used */
- /* Setup */
- MetaEscape(17);
- MetaLong(MAKEQUAD('A', 's', 't', 'r')); /* "Astr" */
- MetaWord(4); /* Creator */
- MetaLong(14L); /* Bytes in string */
- MetaLong(MAKEQUAD('A', 's', 't', 'r')); /* "Astr" */
- MetaLong(MAKEQUAD('o', 'l', 'o', 'g')); /* "olog" */
- MetaLong(MAKEQUAD(' ', '4', '.', '0')); /* " 3.2" */
- MetaWord(MAKEWORD('0', 0)); /* "0" */
- MetaSaveDc();
- MetaWindowOrg(0, 0);
- MetaWindowExt(chartx, charty);
- MetaBkMode(1 /* Transparent */);
- /* Colors */
- for (j = 1; j <= 4; j++)
- for (i = 0; i < 16; i++) {
- k = j <= 1 ? metawid : 0;
- MetaCreatePen(j <= 2 ? 0 : j-2 /* PS_SOLID; PS_DASH; PS_DOT */,
- k, rgbbmp[i]);
- }
- for (i = 0; i < 16; i++) {
- MetaCreateBrush(0 /* BS_SOLID */, rgbbmp[i]);
- }
- MetaCreateBrush(1 /* BS_NULL */, 0L);
- /* Fonts */
- if (xfont) {
- MetaCreateFont(5, 0, -8*SCALE, 2 /* Symbol Charset */);
- MetaWord(MAKEWORD(1 /* Draft */, 1 | 0x10 /* Fixed | Roman */));
- MetaLong(MAKEQUAD('W', 'i', 'n', 'g'));
- MetaLong(MAKEQUAD('d', 'i', 'n', 'g'));
- MetaWord(MAKEWORD('s', 0));
-
- MetaCreateFont(8, 0, -6*SCALE, 0 /* Ansi Charset */);
- MetaWord(MAKEWORD(0 /* Default */, 2 | 0x10 /* Variable | Roman */));
- MetaLong(MAKEQUAD('T', 'i', 'm', 'e'));
- MetaLong(MAKEQUAD('s', ' ', 'N', 'e'));
- MetaLong(MAKEQUAD('w', ' ', 'R', 'o'));
- MetaLong(MAKEQUAD('m', 'a', 'n', 0));
-
- MetaCreateFont(6, 6*METAMUL, 10*METAMUL, 0 /* Ansi Charset */);
- MetaWord(MAKEWORD(1 /* Draft */, 1 | 0x30 /* Fixed | Modern */));
- MetaLong(MAKEQUAD('C', 'o', 'u', 'r'));
- MetaLong(MAKEQUAD('i', 'e', 'r', ' '));
- MetaLong(MAKEQUAD('N', 'e', 'w', 0));
-
- MetaCreateFont(8, 0, -11*SCALE, 0 /* Ansi Charset */);
- MetaWord(MAKEWORD(0 /* Default */, 2 | 0 /* Variable | Don't Care */));
- MetaLong(MAKEQUAD('A', 's', 't', 'r'));
- MetaLong(MAKEQUAD('o', '-', 'S', 'e'));
- MetaLong(MAKEQUAD('m', 'i', 'B', 'o'));
- MetaLong(MAKEQUAD('l', 'd', 0, 0));
- }
- }
-
-
- /* Output trailing records to indicate the end of the metafile and then */
- /* actually write out the entire buffer to the specifed file. */
-
- void WriteMeta(data)
- FILE *data;
- {
- word PTR w;
- #if FALSE
- int i;
-
- for (i = 16*5+1+(xfont>0)*4; i >= 0; i--) {
- MetaDeleteObject(i);
- }
- #endif
- MetaRestoreDc();
- MetaRecord(3, NULL); /* End record */
- *(long PTR)(bm + 22 + 6) = ((long)((byte PTR)metacur - bm) - 22) / 2;
- for (w = (word PTR)bm; w < metacur; w++) {
- PutWord(*w);
- }
- }
- #endif /* META */
-
-
- /*
- ******************************************************************************
- ** Core Graphic Procedures.
- ******************************************************************************
- */
-
- /* Set the current color to use in drawing on the screen or bitmap array. */
-
- void DrawColor(col)
- colpal col;
- {
- #ifdef PS
- if (psfile) {
- if (colcur != col) {
- PSforcestroke(); /* Render existing path with current color */
- fprintf(psdata, "%.2f %.2f %.2f c\n",
- (real)RGBR(rgbbmp[col])/255.0, (real)RGBG(rgbbmp[col])/255.0,
- (real)RGBB(rgbbmp[col])/255.0);
- }
- colcur = col;
- return;
- }
- #endif
- #ifdef META
- if (metafile)
- metalinedes = col;
- #endif
- #ifdef X11
- else if (!xfile)
- XSetForeground(disp, gc, rgbind[col]);
- #endif
- #ifdef MSG
- else if (!xfile)
- _setcolor(col);
- #endif
- colcur = col;
- }
-
-
- /* Set a single point on the screen. This is the most basic graphic function */
- /* and is called by all the more complex routines. Based on what mode we are */
- /* in, we either set a cell in the bitmap array or a pixel on the window. */
-
- void DrawPoint(x, y)
- int x, y;
- {
- if (xfile) {
- if (xbitmap) {
- /* Force the coordinates to be within the bounds of the bitmap array. */
-
- if (x < 0)
- x = 0;
- else if (x >= chartx)
- x = chartx-1;
- if (y < 0)
- y = 0;
- else if (y >= charty)
- y = charty-1;
- PSET(bm, x, y, colcur);
- }
- #ifdef PS
- else if (psfile) {
- DrawColor(colcur);
- PSlinecap(TRUE);
- fprintf(psdata, "%d %d d\n", x, y);
- PSstroke(2);
- }
- #endif
- #ifdef META
- else {
- metafilldes = colcur;
- MetaSelect();
- MetaEllipse(x-metawid/2, y-metawid/2, x+metawid/2, y+metawid/2);
- }
- #endif
- }
- #ifdef X11
- else
- XDrawPoint(disp, pixmap, gc, x, y);
- #endif
- #ifdef MSG
- else
- _setpixel(offsetx + x, offsety + y);
- #endif
- }
-
-
- /* Draw dot a little larger than just a single pixel at specified location. */
-
- void DrawSpot(x, y)
- int x, y;
- {
- #ifdef PS
- if (psfile) {
- PSlinewidth(currentlinewidth*3);
- DrawPoint(x, y);
- PSlinewidth(currentlinewidth/3);
- return;
- }
- #endif
- #ifdef META
- if (metafile) {
- metafilldes = colcur;
- MetaSelect();
- MetaEllipse(x-metawid, y-metawid, x+metawid, y+metawid);
- return;
- }
- #endif
- DrawPoint(x, y);
- DrawPoint(x, y-1);
- DrawPoint(x-1, y);
- DrawPoint(x+1, y);
- DrawPoint(x, y+1);
- }
-
-
- /* Draw a filled in block, defined by the corners of its rectangle. */
-
- void DrawBlock(x1, y1, x2, y2)
- int x1, y1, x2, y2;
- {
- int x, y;
-
- if (xfile) {
- if (xbitmap) {
- for (y = y1; y <= y2; y++) /* For bitmap, we have to */
- for (x = x1; x <= x2; x++) /* just fill in the array. */
- PSET(bm, x, y, colcur);
- }
- #ifdef PS
- else if (psfile) {
- DrawColor(colcur);
- fprintf(psdata, "%d %d %d %d rf\n",
- x1-metawid/4, y1-metawid/4, x2-x1+metawid/4, y2-y1+metawid/4);
- }
- #endif
- #ifdef META
- else {
- metafilldes = colcur;
- MetaSelect();
- MetaRectangle(x1-metawid/2, y1-metawid/2, x2+metawid/2, y2+metawid/2);
- }
- #endif
- }
- #ifdef X11
- else
- XFillRectangle(disp, pixmap, gc, x1, y1, x2, y2);
- #endif
- #ifdef MSG
- else
- _rectangle(_GFILLINTERIOR,
- offsetx + x1, offsety + y1, offsetx + x2, offsety + y2);
- #endif
- }
-
-
- /* Draw a rectangle on the screen with specified thickness. This is just */
- /* like DrawBlock() except that we are only drawing the edges of the area. */
-
- void DrawBox(x1, y1, x2, y2, xsiz, ysiz)
- int x1, y1, x2, y2, xsiz, ysiz;
- {
- #ifdef META
- if (metafile)
- /* For thin boxes in metafiles, we can just output one rectangle record */
- /* instead of drawing each side separately as we have to do otherwise. */
- if (xsiz <= 1 && ysiz <= 1) {
- metafilldes = 16; /* Specify a hollow fill brush. */
- MetaSelect();
- MetaRectangle(x1, y1, x2, y2);
- return;
- }
- #endif
- DrawBlock(x1, y1, x2, y1 + ysiz - 1);
- DrawBlock(x1, y1 + ysiz, x1 + xsiz - 1, y2 - ysiz);
- DrawBlock(x2 - xsiz + 1, y1 + ysiz, x2, y2 - ysiz);
- DrawBlock(x1, y2 - ysiz + 1, x2, y2);
- }
-
-
- /* Clear and erase the graphics screen or bitmap contents. */
-
- void DrawClearScreen()
- {
- #ifdef PS
- if (psfile) {
- /* For PostScript charts first output page orientation information. */
- if (!epsfile) {
- if (modex == MODEL || modex == MODEW ||
- (modex == MODEZ && (todisplay & DASHZ0) == 0)) {
- /* Chartx and charty are reversed for Landscape mode. */
- fprintf(psdata, "%d %d translate\n",
- ((int)(8.5*72) + charty)/2, (chartx + 11*72)/2);
- fprintf(psdata, "-90 rotate\n");
- } else {
- /* Most charts are in Portrait mode */
- fprintf(psdata, "%d %d translate\n", (int)(8.5*72/2) - chartx/2,
- charty/2 + 11*72/2);
- }
- } else
- fprintf(psdata, "0 %d translate\n", charty);
- fprintf(psdata, "1 -1 scale\n");
- scale *= PSMUL; chartx *= PSMUL; charty *= PSMUL;
- fprintf(psdata, "1 %d div dup scale\n", PSMUL);
- }
- #endif
- #ifdef META
- if (metafile)
- MetaInit(); /* For metafiles first go write our header information. */
- #endif
-
- /* Hack: If a comparison relationship chart is set and we're in the -Z */
- /* horizon or -S space graphics chart modes (which normally is just the */
- /* same as single chart graphics) don't actually clear the screen. */
-
- if (relation <= DASHr0 && xnow > 0 && (modex == MODEZ || modex == MODES))
- return;
- #ifdef MSG
- if (!xfile)
- _clearscreen(_GCLEARSCREEN);
- #endif
- DrawColor(off);
- DrawBlock(0, 0, chartx - 1, charty - 1); /* Clear bitmap screen. */
- }
-
-
- /* Draw a line on the screen, specified by its endpoints. In addition, we */
- /* have specified a skip factor, which allows us to draw dashed lines. */
-
- void DrawDash(x1, y1, x2, y2, skip)
- int x1, y1, x2, y2, skip;
- {
- static word PTR poly;
- int x = x1, y = y1, xadd, yadd, yinc, xabs, yabs, i, j = 0;
-
- if (skip < 0)
- skip = 0;
- #ifdef ISG
- if (!xfile) {
- if (!skip) {
- #ifdef X11
- /* For non-dashed X window lines, let's have the Xlib do it for us. */
-
- XDrawLine(disp, pixmap, gc, x1, y1, x2, y2);
- #else
- /* For non-dashed lines, let's have the graphics library do it for us. */
-
- _moveto(offsetx + x1, offsety + y1);
- _lineto(offsetx + x2, offsety + y2);
- #endif
- return;
- }
- }
- #endif /* ISG */
-
- #ifdef PS
- if (psfile) {
-
- /* For PostScript charts we can save file size if we output a LineTo */
- /* command when the start vertex is the same as the end vertex of the */
- /* previous line drawn, instead of writing out both vertices. */
-
- PSlinecap(TRUE);
- PSdash(skip);
- if (xpen != x1 || ypen != y1)
- fprintf(psdata, "%d %d %d %d l\n", x1, y1, x2, y2);
- else
- fprintf(psdata, "%d %d t\n", x2, y2);
- xpen = x2; ypen = y2;
- PSstroke(2);
- return;
- }
- #endif
- #ifdef META
- if (metafile) {
-
- /* For metafile charts we can really save file size for consecutive */
- /* lines sharing endpoints by consolidating them into a PolyLine. */
-
- if (xpen != x1 || ypen != y1) {
- metalinedes = (metalinedes & 15) + 16*(skip > 3 ? 3 : skip);
- MetaSelect();
- poly = metacur;
- MetaRecord(8, 0x325); /* Polyline */
- MetaWord(2); MetaWord(x1); MetaWord(y1);
- } else {
- *poly += 2;
- (*(poly+3))++;
- /* Note: We should technically update the max record size in the */
- /* file header if need be here too, but it doesn't seem necessary. */
- }
- MetaWord(x2); MetaWord(y2);
- xpen = x2; ypen = y2;
- return;
- }
- #endif
-
- /* If none of the above cases hold, we have to draw the line dot by dot. */
-
- xadd = x2 - x1 >= 0 ? 1 : 3;
- yadd = y2 - y1 >= 0 ? 2 : 4;
- xabs = abs(x2 - x1);
- yabs = abs(y2 - y1);
-
- /* Technically what we're doing here is drawing a line which is more */
- /* horizontal then vertical. We always increment x by 1, and increment */
- /* y whenever a fractional variable passes a certain amount. For lines */
- /* that are more vertical than horizontal, we just swap x and y coords. */
-
- if (xabs < yabs) {
- SWAP(xadd, yadd);
- SWAP(xabs, yabs);
- }
- yinc = (xabs >> 1) - ((xabs & 1 ^ 1) && xadd > 2);
- for (i = xabs+1; i; i--) {
- if (j < 1)
- DrawPoint(x, y);
- j = j < skip ? j+1 : 0;
- switch (xadd) {
- case 1: x++; break;
- case 2: y++; break;
- case 3: x--; break;
- case 4: y--; break;
- }
- yinc += yabs;
- if (yinc - xabs >= 0) {
- yinc -= xabs;
- switch (yadd) {
- case 1: x++; break;
- case 2: y++; break;
- case 3: x--; break;
- case 4: y--; break;
- }
- }
- }
- }
-
-
- /* Draw a normal line on the screen; however, if the x coordinates are close */
- /* to either of the two given bounds, then we assume that the line runs off */
- /* one side and reappears on the other, so draw the appropriate two lines */
- /* instead. This is used by the Ley line and astro-graph routines, which */
- /* draw lines running around the world and hence off the edges of the maps. */
-
- void DrawWrap(x1, y1, x2, y2, xmin, xmax)
- int x1, y1, x2, y2;
- {
- int xmid, ymid, i;
-
- if (x1 < 0) { /* Special case for drawing world map. */
- DrawPoint(x2, y2);
- return;
- }
- xmid = (xmax-xmin) / 2;
-
- /* If endpoints aren't near opposite edges, just draw the line and return. */
-
- if (abs(x2-x1) < xmid) {
- DrawLine(x1, y1, x2, y2);
- return;
- }
- i = (xmax-xmin+1) + (x1 < xmid ? x1-x2 : x2-x1);
-
- /* Determine vertical coordinate where our line runs off edges of screen. */
-
- ymid = y1+(int)((real)(y2-y1)*
- (x1 < xmid ? (real)(x1-xmin) : (real)(xmax-x1))/(real)i + ROUND);
- DrawLine(x1, y1, x1 < xmid ? xmin : xmax, ymid);
- DrawLine(x2 < xmid ? xmin : xmax, ymid, x2, y2);
- }
-
-
- /* This routine, and its companion below, clips a line defined by its */
- /* endpoints to either above some line y=c, or below some line y=c. By */
- /* passing in parameters in different orders, we can clip to vertical */
- /* lines, too. These are used by the DrawClip() routine below. */
-
- void ClipLesser(x1, y1, x2, y2, s)
- int *x1, *y1, *x2, *y2, s;
- {
- *x1 -= (int)((long)(*y1-s)*(*x2-*x1)/(*y2-*y1));
- *y1 = s;
- }
-
- void ClipGreater(x1, y1, x2, y2, s)
- int *x1, *y1, *x2, *y2, s;
- {
- *x1 += (int)((long)(s-*y1)*(*x2-*x1)/(*y2-*y1));
- *y1 = s;
- }
-
-
- /* Draw a line on the screen. This is just like DrawLine() routine earlier; */
- /* however, first clip the endpoints to the window viewport before drawing. */
-
- void DrawClip(x1, y1, x2, y2, xl, yl, xh, yh, skip)
- int x1, y1, x2, y2, xl, yl, xh, yh, skip;
- {
- if (x1 < xl)
- ClipLesser (&y1, &x1, &y2, &x2, xl); /* Check left side of window. */
- if (x2 < xl)
- ClipLesser (&y2, &x2, &y1, &x1, xl);
- if (y1 < yl)
- ClipLesser (&x1, &y1, &x2, &y2, yl); /* Check top side of window. */
- if (y2 < yl)
- ClipLesser (&x2, &y2, &x1, &y1, yl);
- if (x1 > xh)
- ClipGreater(&y1, &x1, &y2, &x2, xh); /* Check right of window. */
- if (x2 > xh)
- ClipGreater(&y2, &x2, &y1, &x1, xh);
- if (y1 > yh)
- ClipGreater(&x1, &y1, &x2, &y2, yh); /* Check bottom of window. */
- if (y2 > yh)
- ClipGreater(&x2, &y2, &x1, &y1, yh);
- DrawDash(x1, y1, x2, y2, skip); /* Go draw the line. */
- }
-
-
- /* Draw a circle or ellipse inside the given bounding rectangle. */
-
- void DrawEllipse(x1, y1, x2, y2)
- int x1, y1, x2, y2;
- {
- int x, y, rx, ry, m, n, u, v, i;
-
- if (xfile) {
- x = (x1+x2)/2; y = (y1+y2)/2; rx = (x2-x1)/2; ry = (y2-y1)/2;
- if (xbitmap) {
- InitCircle();
- m = x + rx; n = y;
- for (i = 0; i <= DEGR; i += DEGINC) {
- u = x + (int)((real)rx*circ->x[i]); v = y + (int)((real)ry*circ->y[i]);
- u = MIN(u, x + rx-1); v = MIN(v, y + ry-1);
- DrawLine(m, n, u, v);
- m = u; n = v;
- }
- }
- #ifdef PS
- else if (psfile) {
- PSlinecap(FALSE);
- PSforcestroke();
- fprintf(psdata, "%d %d %d %d el\n", rx, ry, x, y);
- }
- #endif
- #ifdef META
- else {
- metafilldes = 16; /* Specify a hollow fill brush. */
- MetaSelect();
- MetaEllipse(x1+metawid/3, y1+metawid/3, x2+metawid/3, y2+metawid/3);
- }
- #endif
- }
- #ifdef X11
- else
- XDrawArc(disp, pixmap, gc, x1, y1, x2-x1, y2-y1, 0, 360*64);
- #endif
- #ifdef MSG
- else
- _ellipse(_GBORDER, offsetx + x1, offsety + y1, offsetx + x2, offsety + y2);
- #endif
- }
-
-
- /* Print a string of text on the graphic window at specified location. To */
- /* do this we either use Astrolog's own "font" (6x10) and draw each letter */
- /* separately, or else specify system fonts for PostScript and metafiles. */
-
- void DrawText(string, x, y, base)
- char *string;
- int x, y, base;
- {
- int s = scale, c = colcur, len;
-
- len = StringLen(string);
- scale = 100 * scalet;
- x += SCALE;
- if (base >= FALSE)
- x -= len*FONTX*SCALE/2;
- if (!base)
- y -= FONTY*SCALE/2;
- else
- y -= (FONTY-3)*SCALE;
- DrawColor(off);
- DrawBlock(x, y, x+FONTX*SCALE*len, y+(FONTY-1)*SCALE);
- DrawColor(c);
- #ifdef PS
- if (psfile && xfont) {
- PSfont(4);
- fprintf(psdata, "%d %d(%s)center\n",
- x + FONTX*SCALE*len/2, y + FONTY*SCALE/2, string);
- scale = s;
- return;
- }
- #endif
- while (*string) {
- #ifdef META
- if (metafile && xfont) {
- metafontdes = 3;
- metatxtcdes = colcur;
- metatxtades = 0x6 | 0 /* Center | Top */;
- MetaSelect();
- MetaTextOut(x, y, 1);
- MetaWord(MAKEWORD(*string, 0));
- } else
- #endif
- DrawTurtle(asciidraw[*string-' '], x, y);
- x += FONTX*SCALE;
- string++;
- }
- scale = s;
- }
-
-
- /* Draw the glyph of a sign at particular coordinates on the screen. */
- /* To do this we either use Astrolog's turtle vector representation or */
- /* we may specify a system font character for PostScript and metafiles. */
-
- void DrawSign(i, x, y)
- int i, x, y;
- {
- #ifdef PS
- if (psfile && xfont) {
- PSfont(1);
- fprintf(psdata, "%d %d(%c)center\n", x, y, 'A' + i - 1);
- return;
- }
- #endif
- #ifdef META
- if (metafile && xfont) {
- metafontdes = 1;
- metatxtcdes = colcur;
- metatxtades = 0x6 | 0x8 /* Center | Bottom */;
- MetaSelect();
- MetaTextOut(x, y+4*SCALE, 1);
- MetaWord(MAKEWORD('^' + i - 1, 0));
- return;
- }
- #endif
- DrawTurtle(signdraw[i], x, y);
- }
-
-
- /* Draw the number of a house at particular coordinates on the screen. */
- /* We either use a turtle vector or write a number in a system font. */
-
- void DrawHouse(i, x, y)
- int i, x, y;
- {
- #ifdef PS
- if (psfile && xfont) {
- PSfont(3);
- fprintf(psdata, "%d %d(%d)center\n", x, y, i);
- return;
- }
- #endif
- #ifdef META
- if (metafile && xfont) {
- metafontdes = 2;
- metatxtcdes = colcur;
- metatxtades = 0x6 | 0x8 /* Center | Bottom */;
- MetaSelect();
- MetaTextOut(x, y+3*SCALE, 1 + (i>9));
- MetaWord(MAKEWORD(i > 9 ? '1' : '0'+i, i > 9 ? '0'+i-10 : 0));
- return;
- }
- #endif
- DrawTurtle(housedraw[i], x, y);
- }
-
-
- /* Draw the glyph of an object at particular coordinates on the screen. */
-
- void DrawObject(i, x, y)
- int i, x, y;
- {
- char glyph[4];
- #ifdef PS
- static char objectchar[] = "dQRSTUVWXYZ < ba ";
- #endif
- #ifdef META
- char c = 0;
- #endif
-
- if (!xlabel) /* If we are inhibiting labels, then do nothing. */
- return;
-
- /* For other planet centered charts, we have to remember that that */
- /* particular planet's index now represents the Earth. If we are given */
- /* that index to draw, then change it so we draw the Earth instead. */
-
- if (modex != MODES &&
- ((i == centerplanet && i > _MOO) || (centerplanet == 0 && i == _SUN)))
- i = 0;
- DrawColor(objectcolor[i]);
- if (i <= BASE) {
- #ifdef PS
- if (psfile && xfont == 1 && objectchar[i] != ' ') {
- PSfont(2);
- fprintf(psdata, "%d %d(%c)center\n", x, y, objectchar[i]);
- return;
- }
- #endif
- #ifdef META
- if (metafile && xfont == 1) {
- if (i < _SUN)
- c = ';';
- else if (i <= _PLU) c = 'Q' + i - 1;
- else if (i == _NOD) c = '<';
- else if (i == _MC) c = 'b';
- else if (i == _ASC) c = 'a';
- }
- if (c) {
- metafontdes = 4;
- metatxtcdes = colcur;
- metatxtades = 0x6 | 0x8 /* Center | Bottom */;
- MetaSelect();
- MetaTextOut(x, y+5*SCALE, 1);
- MetaWord(MAKEWORD(c, 0));
- return;
- }
- #endif
- DrawTurtle(objectdraw[i], x, y);
-
- /* Normally we can just go draw the glyph; however, stars don't have */
- /* glyphs, so for these draw their three letter abbreviation. */
-
- } else {
- sprintf(glyph, "%c%c%c", OBJNAM(i));
- DrawText(glyph, x, y, FALSE);
- }
- }
-
-
- /* Draw the glyph of an aspect at particular coordinates on the screen. */
- /* Again we either use Astrolog's turtle vector or a system Astro font. */
-
- void DrawAspect(i, x, y)
- int i, x, y;
- {
- #ifdef PS
- static char aspectchar[] = "!\"#$'&%()+- ";
- #endif
- #ifdef META
- char c = 0;
- #endif
-
- #ifdef PS
- if (psfile && xfont == 1 && aspectchar[i-1] != ' ') {
- PSfont(2);
- fprintf(psdata, "%d %d(%c)center\n", x, y, aspectchar[i-1]);
- return;
- }
- #endif
- #ifdef META
- if (metafile && xfont == 1) {
- if (i <= _TRI)
- c = '!' + i - 1;
- else if (i == _SEX) c = '\'';
- else if (i == _INC) c = '&';
- else if (i == _SSX) c = '%';
- else if (i == _SSQ) c = '(';
- else if (i == _SES) c = ')';
- else if (i == _QUI) c = '+';
- else if (i == _BQN) c = '-';
- }
- if (c) {
- metafontdes = 4;
- metatxtcdes = colcur;
- metatxtades = 0x6 | 0x8 /* Center | Bottom */;
- MetaSelect();
- MetaTextOut(x, y+5*SCALE, 1);
- MetaWord(MAKEWORD(c, 0));
- return;
- }
- #endif
- DrawTurtle(aspectdraw[i], x, y);
- }
-
-
- /* Convert a string segment to a positive number, updating the string to */
- /* point beyond the number chars. Return 1 if the string doesn't point to */
- /* a numeric value. This is used by the DrawTurtle() routine to extract */
- /* motion vector quantities from draw strings, e.g. the "12" in "U12". */
-
- int IntInString(str)
- char **str;
- {
- int num = 0, i = 0;
-
- loop {
- if (**str < '0' || **str > '9')
- return num > 0 ? num : (i < 1 ? 1 : 0);
- num = num*10+(**str)-'0';
- (*str)++;
- i++;
- }
- }
-
-
- /* This routine is used to draw complicated objects composed of lots of line */
- /* segments on the screen, such as all the glyphs and coastline pieces. It */
- /* is passed in a string of commands defining what to draw in relative */
- /* coordinates. This is a copy of the format of the BASIC draw command found */
- /* in PC's. For example, "U5R10D5L10" means go up 5 dots, right 10, down 5, */
- /* and left 10 - draw a box twice as wide as it is high. */
-
- void DrawTurtle(lin, x0, y0)
- char *lin;
- int x0, y0;
- {
- int i, j, x, y, deltax, deltay, blank, noupdate;
- char cmd;
-
- turtlex = x0; turtley = y0;
- while (cmd = CAP(*lin)) {
- lin++;
-
- /* 'B' prefixing a command means just move the cursor, and don't draw. */
-
- if (blank = cmd == 'B') {
- cmd = CAP(*lin);
- lin++;
- }
-
- /* 'N' prefixing a command means don't update cursor when done drawing. */
-
- if (noupdate = cmd == 'N') {
- cmd = CAP(*lin);
- lin++;
- }
-
- /* Here we process the eight directional commands. */
-
- switch (cmd) {
- case 'U': deltax = 0; deltay = -1; break; /* Up */
- case 'D': deltax = 0; deltay = 1; break; /* Down */
- case 'L': deltax = -1; deltay = 0; break; /* Left */
- case 'R': deltax = 1; deltay = 0; break; /* Right */
- case 'E': deltax = 1; deltay = -1; break; /* NorthEast */
- case 'F': deltax = 1; deltay = 1; break; /* SouthEast */
- case 'G': deltax = -1; deltay = 1; break; /* SouthWest */
- case 'H': deltax = -1; deltay = -1; break; /* NorthWest */
- default: PrintError("Bad turtle subcommand."); /* Shouldn't happen. */
- }
- x = turtlex;
- y = turtley;
- j = IntInString(&lin)*SCALE; /* Figure out how far to draw. */
- if (blank) {
- turtlex += deltax*j;
- turtley += deltay*j;
- } else {
- if (psfile || metafile) {
- turtlex += deltax*j;
- turtley += deltay*j;
- DrawLine(x, y, turtlex, turtley);
- } else {
- DrawPoint(turtlex, turtley);
- for (i = 0; i < j; i++) {
- turtlex += deltax;
- turtley += deltay;
- DrawPoint(turtlex, turtley);
- }
- }
- if (noupdate) {
- turtlex = x;
- turtley = y;
- }
- }
- }
- }
- #endif /* GRAPH */
-
- /* xgeneral.c */
-