File:  [OS/2 SDKs] / pmsdk / samples / bio / biopaint.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 12:28:34 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: pmsdk-1989, HEAD
Microsoft OS/2 SDK PM 02-24-1989

/*
    biopaint.c	-   WM_PAINT processing and calendar conversion routines

    Created by Microsoft Corporation, 1989
*/
#define INCL_WIN
#define INCL_GPI
#include <os2.h>

#include "bio.h"
#include <math.h>
#include <stdio.h>

/* 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;
}

unix.superglobalmegacorp.com

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