File:  [OS/2 SDKs] / os232sdk / toolkt20 / c / samples / semaph / sem_pnt.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 12:26:30 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: os2sdk-1990, HEAD
Microsoft OS/2 SDK 2.0 05-30-1990

/*==============================================================*\
 *  sem_pnt.c - routines for the painting of the main window    *
 *      Created 1990, Microsoft, IBM Corp.                      *
 *--------------------------------------------------------------*
 *                                                              *
 *  This module contains the code for the main client window    *
 *  painting                                                    *
 *                                                              *
 *--------------------------------------------------------------*
 *                                                              *
 *  This source file contains the following functions:          *
 *                                                              *
 *      DrawResource(PRECTL, COLOR) - Draws colored square      *
 *      DrawStats(USHORT) update the statistics for a thread    *
 *      ChangeResource(COLOR) - Changes resource color          *
 *      InitSemaphExample(VOID) - Sets initial colors           *
 *      SetRectPositions(HWND) - Calculate rectangle locations  *
 *      MyOffsetRect(PRECTL,SHORT,SHORT) - Offsets consumer     *
 *                                         rectangles from      *
 *                                         resource             *
 *      MainPaint(hwnd) - main WM_PAINT processing routine      *
 *                                                              *
\*==============================================================*/

/*--------------------------------------------------------------*\
 *  Include files, macros, defined constants, and externs       *
\*--------------------------------------------------------------*/

#define  LINT_ARGS
#define  INCL_PM
#define  INCL_BASE

#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sem_pnt.h"
#include "sem_main.h"
#include "sem_xtrn.h"
#include "semaph.h"

/*--------------------------------------------------------------*\
 *  Global variables                                            *
\*--------------------------------------------------------------*/
CHAR szWindowText[MAXTEXTLEN]="Sample";
USHORT  cNumUsers = NUMUSERS;
SQ aSquares[MAXRESOURCES];
LONG colors[MAXUSERS]= {
    CLR_WHITE, CLR_BLACK, CLR_BLUE, CLR_RED, CLR_PINK, CLR_GREEN,
    CLR_CYAN, CLR_YELLOW, CLR_DARKGRAY, CLR_DARKBLUE, CLR_DARKRED,
    CLR_DARKPINK, CLR_DARKGREEN, CLR_DARKCYAN, CLR_BROWN, CLR_PALEGRAY};

LONG clrText[MAXUSERS]= {
    CLR_BLACK, CLR_WHITE, CLR_YELLOW, CLR_GREEN, CLR_BLACK, CLR_YELLOW,
    CLR_WHITE, CLR_RED, CLR_WHITE, CLR_BLUE, CLR_RED,
    CLR_PINK, CLR_GREEN, CLR_CYAN, CLR_WHITE, CLR_DARKGRAY};

/* static variables - only visible within this file */
static LONG  yStatsTop, yStatsBtm, xStatsRight, yBoardTop, yDescGlobal;
static POINTL ptlInfoOne, ptlInfoTwo;
SHORT   xWidth;
extern USHORT fSemaphoreStarted, fSemaphoreWasStarted;

/****************************************************************\
 * Routine to print informational message      
 *--------------------------------------------------------------
 *
 *  Name:     InfoLine (HPS)
 *            
 *  Purpose:  print informational message as space allows
 *
 *  Usage:    called from DrawRects on screen repaint
 *
 *  Method:   use information stored in global variables to
 *            calculate the position for 2 lines of informational
 *            text and lines to bracket them.
 *
 *  Returns:  none
 *
\****************************************************************/
VOID
InfoLine (HPS hps)
{
    POINTL  ptl;
    LONG    yBot;
    CHAR    acLineOne[MESSAGELEN];
    CHAR    acLineTwo[MESSAGELEN];

    /* print dividing line at bottom of stat display */
    ptl.x = 0;
    yBot = ptl.y = yStatsBtm - 2;
    GpiMove (hps, &ptl);
    ptl.x = xWidth;
    GpiLine (hps, &ptl);

    /* ptlInfoOne and ptlInfoTwo are intialized in SetRectPositions
     * when the window is created or resized.
     * The y coordinate will be zero if the window is too small
     * for the informational text.
     */
    if (ptlInfoOne.y) {
        /* load informational text from resource file */
        memset (acLineOne, 0, MESSAGELEN);
        if(WinLoadString(hab, NULL, IDS_INFOONE, MESSAGELEN, (PSZ)acLineOne)) {
            GpiCharStringAt (hps, &ptlInfoOne, MESSAGELEN, acLineOne);
            yBot = ptlInfoOne.y - yDescGlobal - 1;
        }
    }
    
    if (ptlInfoTwo.y) {
        /* load informational text from resource file */
        memset (acLineTwo, 0, MESSAGELEN);
        if(WinLoadString(hab, NULL, IDS_INFOTWO, MESSAGELEN, (PSZ)acLineTwo)) {
            GpiCharStringAt (hps, &ptlInfoTwo, MESSAGELEN, acLineTwo);
            yBot = ptlInfoTwo.y - yDescGlobal - 1;
        }
    }

    /* if there is informational text, then print another line at the top
     * of the "game board".
     */
    if (yBoardTop != yStatsBtm) {
        ptl.x = 0;
        ptl.y = min (yBoardTop + 1, yBot);
        GpiMove (hps, &ptl);
        ptl.x = xWidth;
        GpiLine (hps, &ptl);
    }
}

/****************************************************************\
 * Routine to draw the resource rectangle.                      *
 *--------------------------------------------------------------*
 *                                                              *
 *  Name:     DrawResource(PRECTL, COLOR)                       *
 *                                                              *
 *  Purpose:  Color 1 of the 64 rectangles on the playing board.*
 *                                                              *
 *  Usage:    Called from ThreadConsumer in semaph.c when       *
 *            resource becomes owned by a thread.               *
 *                                                              *
 *  Method:   Get the PS from global hwndMain and  WinFillRect. *
 *            This rountine is included so that no access       *
 *            to the resouce is made outside of paint.c.        *
 *            This is to produce code which is more             *
 *            object orientated.                                *
 *                                                              *
 *  Returns:  none                                              *
 *                                                              *
\****************************************************************/

VOID DrawResource(PRECTL prcl, COLOR color)
{
    HPS hps;

    hps = WinGetPS(hwndMain);
    /* this code is related to the WinFillRect in DrawRects.
     * they should stay in synch with each other.
     */
    WinFillRect(hps,prcl,color);
    WinReleasePS(hps);
}

/****************************************************************\
 * update the statistics (number of hits) for a thread          *
 *--------------------------------------------------------------*
 *                                                              *
 *  Name:     DrawStats(USHORT)                                 *
 *                                                              *
 *  Purpose:  update statistics display for for a thread        *
 *                                                              *
 *  Usage:    Called from ThreadConsumer in semaph.c when       *
 *            resource becomes owned by a thread.               *
 *                                                              *
 *                                                              *
 *  Method:   Get the PS, set colors, print number of hits for  *
 *            the thread identified by usMyID.                  *
 *            This rountine is included so that no access       *
 *            to the resouce is made outside of paint.c.        *
 *                                                              *
 *  Returns:                                                    *
 *                                                              *
\****************************************************************/

VOID DrawStats(USHORT usMyID)
{
    HPS hps;
    POINTL  ptl;
    THRDATA *pThr = &thrConsumers[usMyID];
    CHAR    szBuf [CNT_SZHITS];

    ptl.x = pThr->rcl.xLeft;
    ptl.y = pThr->rcl.yBottom;
    /* sprintf is non-reentrant, so it is used only when      
     * have the mutex.
     */
    sprintf (szBuf, "%4.4lu", pThr->lHits);
    hps = WinGetPS(hwndMain);
    GpiSetBackColor (hps, colors [usMyID]);
    GpiSetColor (hps, clrText [usMyID]);
    GpiCharStringPosAt (hps, &ptl, &pThr->rcl, CHS_CLIP | CHS_OPAQUE,
     strlen (szBuf), szBuf, NULL);
    WinReleasePS(hps);
}


/****************************************************************\
 *  Routine to paint rectangles in main window.                 *
 *--------------------------------------------------------------*
 *                                                              *
 *  Name:     DrawRects(HPS)                                    *
 *                                                              *
 *  Purpose:  Does painting of rectangles.                      *
 *                                                              *
 *  Usage:    Called from MainPaint when a paint message        *
 *            is received after the semaphore sample has        *
 *            been started.                                     *
 *                                                              *
 *  Method:   Uses WinFillRect API to color all owned squares on*
 *            the square "playing board". Updates stats for     *
 *            every active consumer thread. Prints the static   *
 *            informational text.                               *
 *                                                              *
 *  Returns:  none.                                             *
 *                                                              *
\****************************************************************/

VOID DrawRects(HPS hps)
{
    INT i;

    /*
     * Fill all rectangles in consumer array.... as well as rectangle
     * for resource.
     */
    if (fSemaphoreWasStarted) {
        for ( i = 0; i < MAXRESOURCES; i++ )
        {
            if (aSquares[i].usOwner < (USHORT) MAXUSERS &&
             aSquares[i].usOwner != (USHORT) UNOWNED) {
                /* this line is identical to that in DrawResource.
                * they should stay in synch with each other.
                */
                WinFillRect (hps, &aSquares[i].rcl, colors[aSquares[i].usOwner]);
            }
        }
    }
    InfoLine (hps);
    /* print statistics for each user */
    for (i = 0; i < cNumUsers; i++) {
        DrawStats (i);
    }
}



/********************************************************************\
 * Routine to size and set the positions of rectangle.          
 *------------------------------------------------------------------
 *                                                                  
 * Name:    SetRectPositions (xClient, yClient, yChar, yDesc)
 *          SHORT   xClient;    width of client window              
 *          SHORT   yClient;    height of client window             
 *          SHORT   yChar;      maximum baseline extender           
 *          SHORT   yDesc;      maximum char descender              
 *                                                                  
 * Purpose: Given above information about the window, calculate     
 *          the area need for the square game board, the statistics    
 *          display, and informative text.                          
 *                                                                  
 * Usage:   Called from MainWndProc whenever a size message         
 *          is received.                                            
 *                                                                  
 * Method:  Determines space needed for statistics display from the 
 *          font information given as parameters to this procedure. 
 *          Then calculates the 18 values which describe a chess    
 *          by distances from a corner along 2 adjacent sides.
 *          These are stored in arrays aX and aY. Given these values,
 *          rectangles are calculated for each square on the grid,
 *          and stored as part of the information about those squares.
 *          Then the size of the rectangles used for the stat display
 *          at the top of the window are calculated, and stored in
 *          the struct describing the thread. Finally, the position
 *          of the line of informative text which divides the two regions
 *          of colored squares is derived.
 *                                                                  
 * Returns: none                                                    
 *                                                                  
\********************************************************************/

VOID SetRectPositions(SHORT xClient, SHORT yClient, SHORT yChar, SHORT yDesc)
{
    INT     i;
    INT     dx;
    LONG aX [CNT_POINTS_EDGE];
    LONG aY [CNT_POINTS_EDGE];
    SHORT xScale, yScale;

    if (!fSemaphoreStarted)
    {
        /* insert code here for informative display */
    }
    
    /* top of stat display */
    yStatsTop = yClient;
    
    /* bottom of stat display */
    yStatsBtm = yClient - yChar - yDesc;
    
    /* width of stat display */
    xStatsRight = xClient;
    
    /* dx is the "scaling factor" for the statistics display */
    dx = xStatsRight / cNumUsers;
    
    /* rectangles for the stat display */    
    for (i = 0; i < cNumUsers; i++) {
        thrConsumers[i].rcl.yBottom = yStatsBtm;
        thrConsumers[i].rcl.yTop = yStatsTop;
        thrConsumers[i].rcl.xLeft = i * dx;
        thrConsumers[i].rcl.xRight = (i+1) * dx;
    }
    /* consume any unused edge */
    thrConsumers [cNumUsers - 1].rcl.xRight = xClient;

    /* if there is room for it, print an informational message */
    if (yStatsBtm > yChar + yDesc) {
        /* there is room for the first line */
        ptlInfoOne.x = 0;
        ptlInfoOne.y = yStatsBtm - yChar;
    }
    else
        ptlInfoOne.y = 0L;

    if (ptlInfoOne.y && ptlInfoOne.y > (2 * yDesc + yChar)) {
        /* room for second line */
        ptlInfoTwo.x = 0;
        ptlInfoTwo.y = ptlInfoOne.y - yChar - yDesc;
    }
    else
        ptlInfoTwo.y = 0L;

    /* calculate top of playing board, hence stored in yClient */
    if (ptlInfoTwo.y) {
        yClient = ptlInfoTwo.y - yDesc;
    }
    else if (ptlInfoOne.y) {
        yClient = ptlInfoOne.y - yDesc;
    }
    else
        yClient = yStatsBtm - 1;

    /* discard unusable portion */
    yClient = yClient - (yClient % CNT_SQUARES_EDGE);
    /* the scaling factors determine how large each square will be */
    xScale = xClient / CNT_SQUARES_EDGE;
    yScale = yClient / CNT_SQUARES_EDGE;
    
    /* the entire game board is described by the points that are
     * calculated here.
     */
    for (i = 0; i < CNT_POINTS_EDGE; i++) {
        aX[i] = i * xScale;
        aY[i] = i * yScale;
    }
    /* consume any unused portion */
    aX[CNT_SQUARES_EDGE] = aX[CNT_SQUARES_EDGE] + xClient % CNT_SQUARES_EDGE;
    aY[CNT_SQUARES_EDGE] = aY[CNT_SQUARES_EDGE] + yClient % CNT_SQUARES_EDGE - 1;

    /* now plug the points just calculated into the
     * rectangles that make up the board
     */
    for (i = 0; i < MAXRESOURCES; i++) {
        aSquares[i].rcl.xLeft = aX [i % CNT_SQUARES_EDGE];
        aSquares[i].rcl.xRight = aX [(i % CNT_SQUARES_EDGE) + 1];
        aSquares[i].rcl.yBottom = aY [i / CNT_SQUARES_EDGE];
        aSquares[i].rcl.yTop = aY [(i / CNT_SQUARES_EDGE) + 1];
    }
    /* store the descender for later */
    yDescGlobal = yDesc;
    /* store top of board for later reference */
    yBoardTop = aY[CNT_SQUARES_EDGE];
    /* finally, store the width of the client window for later reference */
    xWidth = xClient;
}



/****************************************************************\
 *   client painting routine                                *
 *--------------------------------------------------------------*
 *                                                              *
 *  Name:   MainPaint(hwnd)                                     *
 *                                                              *
 *  Purpose: Paints the main client window.                     *
 *                                                              *
 *  Usage:  Routine is called whenver the client window         *
 *          procedure receives a WM_PAINT message               *
 *                                                              *
 *  Method:                                                     *
 *          - begins painting by calling WinBeginPaint          *
 *            and retriving the HPS for the window              *
 *          - performs any painting desired.  Currently the     *
 *            only painting it does is to draw rectangles on    *
 *            the screen if semaphore is started.               *
 *          - ends painting by calling WinEndPaint              *
 *                                                              *
 *  Returns:                                                    *
 *                                                              *
\****************************************************************/

VOID MainPaint(hwnd)
HWND hwnd;	/* handle of the window to be painted */
{
    HPS hps;

    hps = WinBeginPaint(hwnd, NULL, NULL);
    GpiErase (hps);
    DrawRects (hps);
    WinEndPaint(hps);

}   /* MainPaint() */


unix.superglobalmegacorp.com

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