Category : OS/2 Files
Archive   : BIOR.ZIP
Filename : BIOPAINT.C
biopaint.c - WM_PAINT processing and calendar conversion routines
Created by Microsoft Corporation, 1989
*/
#define INCL_WIN
#define INCL_GPI
#include
#include "bio.h"
#include
#include
/* Read-only global variables */
extern double Born;
extern long Day, SelectDay;
extern BOOL bBorn;
extern FONTMETRICS tmFontInfo;
extern int LinesPerPage;
extern RECTL rclClient;
extern SHORT cxDateField;
/* Read-only static variables */
static double Cycle[] = { 23.0, 28.0, 33.0 };
static char cDayOfWeek[] = "MTWTFSS";
extern LONG Color[];
/* APPPaint() - Parent window WM_PAINT processing routine.
*
* Purpose:
* Routine to graph biorhythm cycles and tabulate dates.
*
* Arguments:
* hWnd - Handle of Window owning message
* message - Message itself
* mp1 - Extra message-dependent info
* mp2 - Extra message-dependent info
*
* Globals (static):
* Cycle[] - Array holding period for phy/emot/int: 23,28,33
* cDayOfWeek[] - Array of chars holding first letter of days of week.
* Color[] - Set of colored pens used to identify cycles.
*
* Globals (referenced):
* Born - Birthdate in julian days. Read from WIN.INI.
* SelectDay - Current day being tracked, day is highlighted.
* This is stored as the number of days from birthdate.
* Initialized to present day in WM_CREATE processing.
* Day - Day number from date born which is top line being
* displayed. Initially three days before SelectDay.
* bBorn - Boolean indicating whether valid birtdate entered or
* rclClient - Size of client area defined by WM_SIZE message
* LinesPerPage - Number of system font lines on client area, defined
* by WM_SIZE message handling
* tmFontInfo - Text Metric structure defined during WM_CREATE
*
* Description:
* Tabulates dates and graphs cycles. On color displays, weekends
* are written in red. The update rectangle is used to minimize
* repaint time of affected client area.
*/
VOID APIENTRY APPPaint( hWnd )
HWND hWnd;
{
HPS hPS;
POINTL ptl;
int y, i;
int start, last;
char szDay[16];
int Amplitude, offset;
int year, month;
double day;
RECTL rc, rcClip;
int DayOfWeek;
HRGN hrgnClip;
POINTL ptlTextBox[5];
hPS = WinBeginPaint( hWnd, NULL, &rcClip );
/* Erase client area */
WinQueryWindowRect( hWnd, &rc );
WinFillRect( hPS, &rc, CLR_WHITE );
/* Label parts of table and graph. */
ptl.y = rclClient.yTop - tmFontInfo.lMaxBaselineExt + /* Top line */
tmFontInfo.lMaxDescender;
ptl.x = 0;
GpiCharStringAt( hPS, &ptl, 7L, (PCH)" DATE" );
ptl.x = cxDateField + tmFontInfo.lAveCharWidth;
GpiCharStringAt( hPS, &ptl, 3L, (PCH)"LOW" );
GpiQueryTextBox( hPS, 4L, "HIGH", TXTBOX_COUNT, ptlTextBox );
ptl.x = rclClient.xRight - ptlTextBox[TXTBOX_CONCAT].x - tmFontInfo.lAveCharWidth;
GpiCharStringAt( hPS, &ptl, 4L, (PCH)"HIGH" );
/* Underline labels from left to right across client area */
ptl.y = rclClient.yTop - tmFontInfo.lMaxBaselineExt;
ptl.x = 0;
GpiMove( hPS, &ptl );
ptl.x = rclClient.xRight;
GpiLine( hPS, &ptl );
/* Draw a vertical line separator between dates and cycles */
ptl.y = rclClient.yTop;
ptl.x = cxDateField;
GpiMove( hPS, &ptl );
ptl.y = rclClient.yBottom;
GpiLine( hPS, &ptl );
/* Draw a dotted vertical center line to reference cycles */
GpiSetLineType( hPS, LINETYPE_DOT );
ptl.x = (cxDateField + rclClient.xRight) / 2;
GpiMove( hPS, &ptl );
ptl.y = rclClient.yTop;
GpiLine( hPS, &ptl );
/* (Should not have to restore line type after EndPaint) */
GpiSetLineType( hPS, LINETYPE_DEFAULT );
/* Update only the range of lines which fall into update rectangle */
start = (int)((rclClient.yTop - rcClip.yTop) / tmFontInfo.lMaxBaselineExt);
if (start<1)
start = 1;
last = (int)((rclClient.yTop - rcClip.yBottom) / tmFontInfo.lMaxBaselineExt);
if (last>(LinesPerPage-1))
last = LinesPerPage-1;
/* Set clip rectangle to completely draw entire rectangle representing
each date affected. Start drawing one day before and after
(outside clip rectangle) so that cycle lines will connect correctly
with unaffected lines. */
rcClip.yTop = rclClient.yTop - start*tmFontInfo.lMaxBaselineExt;
start--;
last++;
rcClip.yBottom = rclClient.yTop - last*tmFontInfo.lMaxBaselineExt + 1;
hrgnClip = GpiCreateRegion( hPS, 1L, &rcClip );
GpiSetClipRegion( hPS, hrgnClip, &hrgnClip );
/* List days and date */
for (y=start; y<=last; y++) {
/* Get the calendar date from julian day */
calendar( Born+Day+y-1, &year, &month, &day );
/* Get offset into days of the week initials array */
DayOfWeek = (int)((LONG)(Born+Day+y) % 7);
/* Assemble each of the parts in a buffer */
sprintf(szDay, " %02d-%02d-%02d",
month, (int)day, year - (trunc4((double)year / 100)*100) );
/* If color available, draw weekends in red */
if (DayOfWeek > 4)
GpiSetColor( hPS, CLR_RED );
ptl.x = 0;
ptl.y = rclClient.yTop - ((y+1)*tmFontInfo.lMaxBaselineExt -
tmFontInfo.lMaxDescender);
GpiCharStringAt( hPS, &ptl, 1L, (PCH)&cDayOfWeek[DayOfWeek] );
GpiQueryWidthTable( hPS, (LONG)'W', 1L, &ptl.x );
GpiCharStringAt( hPS, &ptl, 9L, (PCH)szDay );
GpiSetColor( hPS, CLR_BLACK );
}
/* Amplitude of sin wave is half client area minus space for dates */
Amplitude = (int)((rclClient.xRight - cxDateField - tmFontInfo.lAveCharWidth) >> 1);
/* Move to right, make room for column of dates */
offset = (int)(Amplitude + cxDateField + tmFontInfo.lAveCharWidth - (tmFontInfo.lAveCharWidth>>1));
for (i=0; i<3 && bBorn; i++ ) {
GpiSetColor( hPS, Color[i] );
for (y=start; y<=last; y++) {
ptl.x = (int)(sin( (y+Day-1)/Cycle[i]*2*3.14159 ) * Amplitude + offset);
ptl.y = rclClient.yTop - (y*tmFontInfo.lMaxBaselineExt +
tmFontInfo.lMaxBaselineExt/2);
if ((y+Day-1 > 0) && (y>start))
GpiLine( hPS, &ptl );
else
GpiMove( hPS, &ptl );
}
}
/* Draw highlight on selected day if visible. */
if ((SelectDay >= Day) && (SelectDay - Day < LinesPerPage - 1)) {
rc.xRight = rclClient.xRight;
rc.xLeft = rclClient.xLeft;
rc.yTop = rclClient.yTop - (int)(SelectDay - Day + 1) * tmFontInfo.lMaxBaselineExt;
rc.yBottom = rc.yTop - tmFontInfo.lMaxBaselineExt + 1;
WinInvertRect( hPS, &rc );
}
WinEndPaint( hPS );
return;
}
/* julian() - Compute julian date from Gregorian calendar date.
*
* Purpose:
* Provide a standard time base.
*
* Arguments:
* year - Calendar year
* month - Calendar month
* day - Calendar day and fraction
*
* Return Value:
* double - Julian date converted
*
* Description:
* Convert Gregorian dates to Julian Days. Refer to Alamanac for
* Computers (1978), p. B2, Naval Observatory Pub.
*
* Limits:
* Valid between ~1900 and 2099.
*
*/
double PASCAL julian (year, month, day)
int year, month;
double day;
{
double dj;
double fracDay, intDay;
fracDay = modf(day, &intDay);
dj = (long)367*year - 7*(year + (month+9) / 12) / 4 + 275*month / 9 +
intDay + 1721013.5 + fracDay;
return dj;
}
/* calendar() - Compute Gregorian calendar date from julian date.
*
* Purpose:
* Provide a standard time base.
*
* Arguments:
* juldate - Julian date to convert
* year - Calendar year result
* month - Calendar month result
* day - Calendar day and fraction result
*
* Return Value:
* void
*
* Globals (modified):
* none
*
* Globals (referenced):
* none
*
* Description:
* Convert Julian Days to Gregorian date. Refer to Astronomical
* Formulae for Calculators (1979), p. 23, by Jean Meeus.
*
* Limits:
* Valid for positive Julian Day values.
*
*/
void PASCAL calendar (juldate, year, month, day)
double juldate;
int *year;
int *month;
double *day;
{
long b, c, d, e, z, alf;
juldate = juldate + 0.5;
z = trunc4(juldate);
alf = trunc4((z - 1867216.25)/36524.25);
b = z + 1 + alf - alf / 4 + 1524;
c = trunc4((b - 122.1)/365.25);
d = 365*c + c / 4;
e = trunc4((b - d)/30.6001);
*day = b - d - trunc4(30.6001*e) + juldate - z;
if (e > 13)
*month = (int)e - 13;
else
*month = (int)e - 1;
if (*month > 2)
*year = (int)c - 4716;
else
*year = (int)c - 4715;
}
long PASCAL trunc4( dflValue )
double dflValue;
{
double intValue;
modf(dflValue, &intValue);
return (long)intValue;
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/