|
|
1.1 root 1: /* APPPaint() - Parent window WM_PAINT processing routine.
2: *
3: * Created by Microsoft Corp., 1988
4: *
5: * Purpose:
6: * Routine to graph biorythm cycles and tabulate dates.
7: *
8: * Arguments:
9: * hWnd - Handle of Window owning message
10: * message - Message itself
11: * mp1 - Extra message-dependent info
12: * mp2 - Extra message-dependent info
13: *
14: * Return Value:
15: * void
16: *
17: * Globals (modified):
18: * none
19: *
20: * Globals (static):
21: * Cycle[] - Array holding period for phy/emot/int: 23,28,33
22: * cDayOfWeek[] - Array of chars holding first letter of days of week.
23: * Color[] - Set of colored pens used to identify cycles.
24: *
25: * Globals (referenced):
26: * Born - Bithdate in julian days. Read from WIN.INI.
27: * SelectDay - Current day being tracked, day is highlighted. Is
28: * in units of days from birth date. Date of present
29: * day initially used in WM_CREATE.
30: * Day - Day number from date born which is top line being
31: * displayed. Initially three days before SelectDay.
32: * bBorn - Boolean indicating whether valid birtdate entered or
33: * rectClient - Size of client area defined by WM_SIZE message
34: * LinesPerPage - Number of system font lines on client area, defined
35: * by WM_SIZE message handling
36: * tmFontInfo - Text Metric structure defined during WM_CREATE
37: *
38: * Description:
39: * Tabulates dates and graphs cycles. On color displays, weekends
40: * are written in red. The update rectangle is used to minimize
41: * repaint time of affected client area.
42: *
43: * Limits:
44: * N/A
45: */
46:
47: #define INCL_WIN
48: #define INCL_GPI
49: #include <os2.h>
50:
51: #include "bio.h"
52: #include <math.h>
53: #include <stdio.h>
54:
55: /* Read-only global variables */
56: extern double Born;
57: extern long Day, SelectDay;
58: extern BOOL bBorn;
59: extern FONTMETRICS tmFontInfo;
60: extern int LinesPerPage;
61: extern RECTL rectClient;
62:
63: /* Read-only static variables */
64: static double Cycle[] = { 23.0, 28.0, 33.0 };
65: static char cDayOfWeek[] = "MTWTFSS";
66: extern LONG Color[];
67:
68: VOID FAR PASCAL APPPaint( hWnd )
69: HWND hWnd;
70: {
71: HPS hPS;
72: POINTL ptl;
73: int y, i;
74: int start, last;
75: char szDay[16];
76: int Amplitude, offset;
77: int year, month;
78: double day;
79: RECTL rc, rcClip;
80: int DayOfWeek;
81: HRGN hrgnClip;
82:
83: hPS = WinBeginPaint( hWnd, NULL, &rcClip );
84:
85: /* Erase client area */
86: WinQueryWindowRect( hWnd, &rc );
87: WinFillRect( hPS, &rc, CLR_WHITE );
88:
89: /* Label parts of table and graph. */
90: ptl.y = rectClient.yTop - tmFontInfo.lMaxBaselineExt + /* Top line */
91: tmFontInfo.lMaxDescender;
92: ptl.x = 0;
93: GpiCharStringAt( hPS, &ptl, 6L, (PCH)" DATE" );
94: ptl.x = 11 * tmFontInfo.lAveCharWidth;
95: GpiCharStringAt( hPS, &ptl, 3L, (PCH)"LOW" );
96: ptl.x = rectClient.xRight - 5 * tmFontInfo.lAveCharWidth;
97: GpiCharStringAt( hPS, &ptl, 4L, (PCH)"HIGH" );
98:
99: /* Underline labels from left to right across client area */
100: ptl.y = rectClient.yTop - tmFontInfo.lMaxBaselineExt;
101: ptl.x = 0;
102: GpiMove( hPS, &ptl );
103: ptl.x = rectClient.xRight;
104: GpiLine( hPS, &ptl );
105:
106: /* Draw a vertical line separator between dates and cycles */
107: ptl.y = rectClient.yTop;
108: ptl.x = 10 * tmFontInfo.lAveCharWidth;
109: GpiMove( hPS, &ptl );
110: ptl.y = rectClient.yBottom;
111: GpiLine( hPS, &ptl );
112:
113: /* Draw a dotted vertical center line to reference cycles */
114: GpiSetLineType( hPS, LINETYPE_DOT );
115: ptl.x = (10 * tmFontInfo.lAveCharWidth + rectClient.xRight) / 2;
116: GpiMove( hPS, &ptl );
117: ptl.y = rectClient.yTop;
118: GpiLine( hPS, &ptl );
119: /* (Should not have to restore line type after EndPaint) */
120: GpiSetLineType( hPS, LINETYPE_DEFAULT );
121:
122: /* Update only the range of lines which fall into update rectangle */
123: start = (int)((rectClient.yTop - rcClip.yTop) / tmFontInfo.lMaxBaselineExt);
124: if (start<1)
125: start = 1;
126: last = (int)((rectClient.yTop - rcClip.yBottom) / tmFontInfo.lMaxBaselineExt);
127: if (last>(LinesPerPage-1))
128: last = LinesPerPage-1;
129:
130: /* Set clip rectangle to completely draw entire rectangle representing
131: each date affected. Start drawing one day before and after
132: (outside clip rectangle) so that cycle lines will connect correctly
133: with unaffected lines. */
134: rcClip.yTop = rectClient.yTop - start*tmFontInfo.lMaxBaselineExt;
135: start--;
136: last++;
137: rcClip.yBottom = rectClient.yTop - last*tmFontInfo.lMaxBaselineExt + 1;
138: hrgnClip = GpiCreateRegion( hPS, 1L, &rcClip );
139: GpiSetClipRegion( hPS, hrgnClip );
140:
141: /* List days and date */
142: for (y=start; y<=last; y++) {
143: /* Get the calendar date from julian day */
144: calendar( Born+Day+y-1, &year, &month, &day );
145: /* Get offset into days of the week initials array */
146: DayOfWeek = (int)((LONG)(Born+Day+y) % 7);
147: /* Assemble each of the parts in a buffer */
148: sprintf(szDay, "%c %02d-%02d-%02d", cDayOfWeek[DayOfWeek],
149: month, (int)day, year - (trunc4((double)year / 100)*100) );
150: /* If color available, draw weekends in red */
151: if (DayOfWeek > 4)
152: GpiSetColor( hPS, CLR_RED );
153: ptl.x = 0;
154: ptl.y = rectClient.yTop - ((y+1)*tmFontInfo.lMaxBaselineExt -
155: tmFontInfo.lMaxDescender);
156: GpiCharStringAt( hPS, &ptl, 10L, (PCH)szDay );
157: GpiSetColor( hPS, CLR_BLACK );
158: }
159:
160: /* Amplitude of sin wave is half client area minus space for dates */
161: Amplitude = (int)((rectClient.xRight - 11 * tmFontInfo.lAveCharWidth) / 2);
162: /* Move to right, make room for column of dates */
163: offset = (int)(Amplitude + 11 * tmFontInfo.lAveCharWidth - 4);
164: for (i=0; i<3 && bBorn; i++ ) {
165: GpiSetColor( hPS, Color[i] );
166: for (y=start; y<=last; y++) {
167: ptl.x = (int)(sin( (y+Day-1)/Cycle[i]*2*3.14159 ) * Amplitude + offset);
168: ptl.y = rectClient.yTop - (y*tmFontInfo.lMaxBaselineExt +
169: tmFontInfo.lMaxBaselineExt/2);
170: if ((y+Day-1 > 0) && (y>start))
171: GpiLine( hPS, &ptl );
172: else
173: GpiMove( hPS, &ptl );
174: }
175: }
176:
177: /* Draw highlight on selected day if visible. */
178: if ((SelectDay >= Day) && (SelectDay - Day < LinesPerPage - 1)) {
179: rc.xRight = rectClient.xRight;
180: rc.xLeft = rectClient.xLeft;
181: rc.yTop = rectClient.yTop - (int)(SelectDay - Day + 1) * tmFontInfo.lMaxBaselineExt;
182: rc.yBottom = rc.yTop - tmFontInfo.lMaxBaselineExt + 1;
183: WinInvertRect( hPS, &rc );
184: }
185:
186: WinEndPaint( hPS );
187:
188: return;
189: }
190:
191:
192: /* julian() - Compute julian date from Gregorian calendar date.
193: *
194: * Purpose:
195: * Provide a standard time base.
196: *
197: * Arguments:
198: * year - Calendar year
199: * month - Calendar month
200: * day - Calendar day and fraction
201: *
202: * Return Value:
203: * double - Julian date converted
204: *
205: * Globals (modified):
206: * none
207: *
208: * Globals (referenced):
209: * none
210: *
211: * Description:
212: * Convert Gregorian dates to Julian Days. Refer to Alamanac for
213: * Computers (1978), p. B2, Naval Observatory Pub.
214: *
215: * Limits:
216: * Valid between ~1900 and 2099.
217: *
218: */
219:
220: double PASCAL julian (year, month, day)
221: int year, month;
222: double day;
223: {
224: double dj;
225: double fracDay, intDay;
226:
227: fracDay = modf(day, &intDay);
228: dj = (long)367*year - 7*(year + (month+9) / 12) / 4 + 275*month / 9 +
229: intDay + 1721013.5 + fracDay;
230: return dj;
231: }
232:
233:
234: /* calendar() - Compute Gregorian calendar date from julian date.
235: *
236: * Purpose:
237: * Provide a standard time base.
238: *
239: * Arguments:
240: * juldate - Julian date to convert
241: * year - Calendar year result
242: * month - Calendar month result
243: * day - Calendar day and fraction result
244: *
245: * Return Value:
246: * void
247: *
248: * Globals (modified):
249: * none
250: *
251: * Globals (referenced):
252: * none
253: *
254: * Description:
255: * Convert Julian Days to Gregorian date. Refer to Astronomical
256: * Formulae for Calculators (1979), p. 23, by Jean Meeus.
257: *
258: * Limits:
259: * Valid for positive Julian Day values.
260: *
261: */
262:
263: void PASCAL calendar (juldate, year, month, day)
264: double juldate;
265: int *year;
266: int *month;
267: double *day;
268: {
269: long b, c, d, e, z, alf;
270:
271: juldate = juldate + 0.5;
272: z = trunc4(juldate);
273: alf = trunc4((z - 1867216.25)/36524.25);
274: b = z + 1 + alf - alf / 4 + 1524;
275: c = trunc4((b - 122.1)/365.25);
276: d = 365*c + c / 4;
277: e = trunc4((b - d)/30.6001);
278: *day = b - d - trunc4(30.6001*e) + juldate - z;
279: if (e > 13)
280: *month = (int)e - 13;
281: else
282: *month = (int)e - 1;
283: if (*month > 2)
284: *year = (int)c - 4716;
285: else
286: *year = (int)c - 4715;
287: }
288:
289: long PASCAL trunc4( dflValue )
290: double dflValue;
291: {
292: double intValue;
293: modf(dflValue, &intValue);
294: return (long)intValue;
295: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.