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