Annotation of pmsdk/samples/bio/biopaint.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.