|
|
1.1 ! root 1: /*==============================================================*\ ! 2: * sem_pnt.c - routines for the painting of the main window * ! 3: * Created 1990, Microsoft, IBM Corp. * ! 4: *--------------------------------------------------------------* ! 5: * * ! 6: * This module contains the code for the main client window * ! 7: * painting * ! 8: * * ! 9: *--------------------------------------------------------------* ! 10: * * ! 11: * This source file contains the following functions: * ! 12: * * ! 13: * DrawResource(PRECTL, COLOR) - Draws colored square * ! 14: * DrawStats(USHORT) update the statistics for a thread * ! 15: * ChangeResource(COLOR) - Changes resource color * ! 16: * InitSemaphExample(VOID) - Sets initial colors * ! 17: * SetRectPositions(HWND) - Calculate rectangle locations * ! 18: * MyOffsetRect(PRECTL,SHORT,SHORT) - Offsets consumer * ! 19: * rectangles from * ! 20: * resource * ! 21: * MainPaint(hwnd) - main WM_PAINT processing routine * ! 22: * * ! 23: \*==============================================================*/ ! 24: ! 25: /*--------------------------------------------------------------*\ ! 26: * Include files, macros, defined constants, and externs * ! 27: \*--------------------------------------------------------------*/ ! 28: ! 29: #define LINT_ARGS ! 30: #define INCL_PM ! 31: #define INCL_BASE ! 32: ! 33: #include <os2.h> ! 34: #include <stdio.h> ! 35: #include <stdlib.h> ! 36: #include <string.h> ! 37: #include "sem_pnt.h" ! 38: #include "sem_main.h" ! 39: #include "sem_xtrn.h" ! 40: #include "semaph.h" ! 41: ! 42: /*--------------------------------------------------------------*\ ! 43: * Global variables * ! 44: \*--------------------------------------------------------------*/ ! 45: CHAR szWindowText[MAXTEXTLEN]="Sample"; ! 46: USHORT cNumUsers = NUMUSERS; ! 47: SQ aSquares[MAXRESOURCES]; ! 48: LONG colors[MAXUSERS]= { ! 49: CLR_WHITE, CLR_BLACK, CLR_BLUE, CLR_RED, CLR_PINK, CLR_GREEN, ! 50: CLR_CYAN, CLR_YELLOW, CLR_DARKGRAY, CLR_DARKBLUE, CLR_DARKRED, ! 51: CLR_DARKPINK, CLR_DARKGREEN, CLR_DARKCYAN, CLR_BROWN, CLR_PALEGRAY}; ! 52: ! 53: LONG clrText[MAXUSERS]= { ! 54: CLR_BLACK, CLR_WHITE, CLR_YELLOW, CLR_GREEN, CLR_BLACK, CLR_YELLOW, ! 55: CLR_WHITE, CLR_RED, CLR_WHITE, CLR_BLUE, CLR_RED, ! 56: CLR_PINK, CLR_GREEN, CLR_CYAN, CLR_WHITE, CLR_DARKGRAY}; ! 57: ! 58: /* static variables - only visible within this file */ ! 59: static LONG yStatsTop, yStatsBtm, xStatsRight, yBoardTop, yDescGlobal; ! 60: static POINTL ptlInfoOne, ptlInfoTwo; ! 61: SHORT xWidth; ! 62: extern USHORT fSemaphoreStarted, fSemaphoreWasStarted; ! 63: ! 64: /****************************************************************\ ! 65: * Routine to print informational message ! 66: *-------------------------------------------------------------- ! 67: * ! 68: * Name: InfoLine (HPS) ! 69: * ! 70: * Purpose: print informational message as space allows ! 71: * ! 72: * Usage: called from DrawRects on screen repaint ! 73: * ! 74: * Method: use information stored in global variables to ! 75: * calculate the position for 2 lines of informational ! 76: * text and lines to bracket them. ! 77: * ! 78: * Returns: none ! 79: * ! 80: \****************************************************************/ ! 81: VOID ! 82: InfoLine (HPS hps) ! 83: { ! 84: POINTL ptl; ! 85: LONG yBot; ! 86: CHAR acLineOne[MESSAGELEN]; ! 87: CHAR acLineTwo[MESSAGELEN]; ! 88: ! 89: /* print dividing line at bottom of stat display */ ! 90: ptl.x = 0; ! 91: yBot = ptl.y = yStatsBtm - 2; ! 92: GpiMove (hps, &ptl); ! 93: ptl.x = xWidth; ! 94: GpiLine (hps, &ptl); ! 95: ! 96: /* ptlInfoOne and ptlInfoTwo are intialized in SetRectPositions ! 97: * when the window is created or resized. ! 98: * The y coordinate will be zero if the window is too small ! 99: * for the informational text. ! 100: */ ! 101: if (ptlInfoOne.y) { ! 102: /* load informational text from resource file */ ! 103: memset (acLineOne, 0, MESSAGELEN); ! 104: if(WinLoadString(hab, NULL, IDS_INFOONE, MESSAGELEN, (PSZ)acLineOne)) { ! 105: GpiCharStringAt (hps, &ptlInfoOne, MESSAGELEN, acLineOne); ! 106: yBot = ptlInfoOne.y - yDescGlobal - 1; ! 107: } ! 108: } ! 109: ! 110: if (ptlInfoTwo.y) { ! 111: /* load informational text from resource file */ ! 112: memset (acLineTwo, 0, MESSAGELEN); ! 113: if(WinLoadString(hab, NULL, IDS_INFOTWO, MESSAGELEN, (PSZ)acLineTwo)) { ! 114: GpiCharStringAt (hps, &ptlInfoTwo, MESSAGELEN, acLineTwo); ! 115: yBot = ptlInfoTwo.y - yDescGlobal - 1; ! 116: } ! 117: } ! 118: ! 119: /* if there is informational text, then print another line at the top ! 120: * of the "game board". ! 121: */ ! 122: if (yBoardTop != yStatsBtm) { ! 123: ptl.x = 0; ! 124: ptl.y = min (yBoardTop + 1, yBot); ! 125: GpiMove (hps, &ptl); ! 126: ptl.x = xWidth; ! 127: GpiLine (hps, &ptl); ! 128: } ! 129: } ! 130: ! 131: /****************************************************************\ ! 132: * Routine to draw the resource rectangle. * ! 133: *--------------------------------------------------------------* ! 134: * * ! 135: * Name: DrawResource(PRECTL, COLOR) * ! 136: * * ! 137: * Purpose: Color 1 of the 64 rectangles on the playing board.* ! 138: * * ! 139: * Usage: Called from ThreadConsumer in semaph.c when * ! 140: * resource becomes owned by a thread. * ! 141: * * ! 142: * Method: Get the PS from global hwndMain and WinFillRect. * ! 143: * This rountine is included so that no access * ! 144: * to the resouce is made outside of paint.c. * ! 145: * This is to produce code which is more * ! 146: * object orientated. * ! 147: * * ! 148: * Returns: none * ! 149: * * ! 150: \****************************************************************/ ! 151: ! 152: VOID DrawResource(PRECTL prcl, COLOR color) ! 153: { ! 154: HPS hps; ! 155: ! 156: hps = WinGetPS(hwndMain); ! 157: /* this code is related to the WinFillRect in DrawRects. ! 158: * they should stay in synch with each other. ! 159: */ ! 160: WinFillRect(hps,prcl,color); ! 161: WinReleasePS(hps); ! 162: } ! 163: ! 164: /****************************************************************\ ! 165: * update the statistics (number of hits) for a thread * ! 166: *--------------------------------------------------------------* ! 167: * * ! 168: * Name: DrawStats(USHORT) * ! 169: * * ! 170: * Purpose: update statistics display for for a thread * ! 171: * * ! 172: * Usage: Called from ThreadConsumer in semaph.c when * ! 173: * resource becomes owned by a thread. * ! 174: * * ! 175: * * ! 176: * Method: Get the PS, set colors, print number of hits for * ! 177: * the thread identified by usMyID. * ! 178: * This rountine is included so that no access * ! 179: * to the resouce is made outside of paint.c. * ! 180: * * ! 181: * Returns: * ! 182: * * ! 183: \****************************************************************/ ! 184: ! 185: VOID DrawStats(USHORT usMyID) ! 186: { ! 187: HPS hps; ! 188: POINTL ptl; ! 189: THRDATA *pThr = &thrConsumers[usMyID]; ! 190: CHAR szBuf [CNT_SZHITS]; ! 191: ! 192: ptl.x = pThr->rcl.xLeft; ! 193: ptl.y = pThr->rcl.yBottom; ! 194: /* sprintf is non-reentrant, so it is used only when ! 195: * have the mutex. ! 196: */ ! 197: sprintf (szBuf, "%4.4lu", pThr->lHits); ! 198: hps = WinGetPS(hwndMain); ! 199: GpiSetBackColor (hps, colors [usMyID]); ! 200: GpiSetColor (hps, clrText [usMyID]); ! 201: GpiCharStringPosAt (hps, &ptl, &pThr->rcl, CHS_CLIP | CHS_OPAQUE, ! 202: strlen (szBuf), szBuf, NULL); ! 203: WinReleasePS(hps); ! 204: } ! 205: ! 206: ! 207: /****************************************************************\ ! 208: * Routine to paint rectangles in main window. * ! 209: *--------------------------------------------------------------* ! 210: * * ! 211: * Name: DrawRects(HPS) * ! 212: * * ! 213: * Purpose: Does painting of rectangles. * ! 214: * * ! 215: * Usage: Called from MainPaint when a paint message * ! 216: * is received after the semaphore sample has * ! 217: * been started. * ! 218: * * ! 219: * Method: Uses WinFillRect API to color all owned squares on* ! 220: * the square "playing board". Updates stats for * ! 221: * every active consumer thread. Prints the static * ! 222: * informational text. * ! 223: * * ! 224: * Returns: none. * ! 225: * * ! 226: \****************************************************************/ ! 227: ! 228: VOID DrawRects(HPS hps) ! 229: { ! 230: INT i; ! 231: ! 232: /* ! 233: * Fill all rectangles in consumer array.... as well as rectangle ! 234: * for resource. ! 235: */ ! 236: if (fSemaphoreWasStarted) { ! 237: for ( i = 0; i < MAXRESOURCES; i++ ) ! 238: { ! 239: if (aSquares[i].usOwner < (USHORT) MAXUSERS && ! 240: aSquares[i].usOwner != (USHORT) UNOWNED) { ! 241: /* this line is identical to that in DrawResource. ! 242: * they should stay in synch with each other. ! 243: */ ! 244: WinFillRect (hps, &aSquares[i].rcl, colors[aSquares[i].usOwner]); ! 245: } ! 246: } ! 247: } ! 248: InfoLine (hps); ! 249: /* print statistics for each user */ ! 250: for (i = 0; i < cNumUsers; i++) { ! 251: DrawStats (i); ! 252: } ! 253: } ! 254: ! 255: ! 256: ! 257: /********************************************************************\ ! 258: * Routine to size and set the positions of rectangle. ! 259: *------------------------------------------------------------------ ! 260: * ! 261: * Name: SetRectPositions (xClient, yClient, yChar, yDesc) ! 262: * SHORT xClient; width of client window ! 263: * SHORT yClient; height of client window ! 264: * SHORT yChar; maximum baseline extender ! 265: * SHORT yDesc; maximum char descender ! 266: * ! 267: * Purpose: Given above information about the window, calculate ! 268: * the area need for the square game board, the statistics ! 269: * display, and informative text. ! 270: * ! 271: * Usage: Called from MainWndProc whenever a size message ! 272: * is received. ! 273: * ! 274: * Method: Determines space needed for statistics display from the ! 275: * font information given as parameters to this procedure. ! 276: * Then calculates the 18 values which describe a chess ! 277: * by distances from a corner along 2 adjacent sides. ! 278: * These are stored in arrays aX and aY. Given these values, ! 279: * rectangles are calculated for each square on the grid, ! 280: * and stored as part of the information about those squares. ! 281: * Then the size of the rectangles used for the stat display ! 282: * at the top of the window are calculated, and stored in ! 283: * the struct describing the thread. Finally, the position ! 284: * of the line of informative text which divides the two regions ! 285: * of colored squares is derived. ! 286: * ! 287: * Returns: none ! 288: * ! 289: \********************************************************************/ ! 290: ! 291: VOID SetRectPositions(SHORT xClient, SHORT yClient, SHORT yChar, SHORT yDesc) ! 292: { ! 293: INT i; ! 294: INT dx; ! 295: LONG aX [CNT_POINTS_EDGE]; ! 296: LONG aY [CNT_POINTS_EDGE]; ! 297: SHORT xScale, yScale; ! 298: ! 299: if (!fSemaphoreStarted) ! 300: { ! 301: /* insert code here for informative display */ ! 302: } ! 303: ! 304: /* top of stat display */ ! 305: yStatsTop = yClient; ! 306: ! 307: /* bottom of stat display */ ! 308: yStatsBtm = yClient - yChar - yDesc; ! 309: ! 310: /* width of stat display */ ! 311: xStatsRight = xClient; ! 312: ! 313: /* dx is the "scaling factor" for the statistics display */ ! 314: dx = xStatsRight / cNumUsers; ! 315: ! 316: /* rectangles for the stat display */ ! 317: for (i = 0; i < cNumUsers; i++) { ! 318: thrConsumers[i].rcl.yBottom = yStatsBtm; ! 319: thrConsumers[i].rcl.yTop = yStatsTop; ! 320: thrConsumers[i].rcl.xLeft = i * dx; ! 321: thrConsumers[i].rcl.xRight = (i+1) * dx; ! 322: } ! 323: /* consume any unused edge */ ! 324: thrConsumers [cNumUsers - 1].rcl.xRight = xClient; ! 325: ! 326: /* if there is room for it, print an informational message */ ! 327: if (yStatsBtm > yChar + yDesc) { ! 328: /* there is room for the first line */ ! 329: ptlInfoOne.x = 0; ! 330: ptlInfoOne.y = yStatsBtm - yChar; ! 331: } ! 332: else ! 333: ptlInfoOne.y = 0L; ! 334: ! 335: if (ptlInfoOne.y && ptlInfoOne.y > (2 * yDesc + yChar)) { ! 336: /* room for second line */ ! 337: ptlInfoTwo.x = 0; ! 338: ptlInfoTwo.y = ptlInfoOne.y - yChar - yDesc; ! 339: } ! 340: else ! 341: ptlInfoTwo.y = 0L; ! 342: ! 343: /* calculate top of playing board, hence stored in yClient */ ! 344: if (ptlInfoTwo.y) { ! 345: yClient = ptlInfoTwo.y - yDesc; ! 346: } ! 347: else if (ptlInfoOne.y) { ! 348: yClient = ptlInfoOne.y - yDesc; ! 349: } ! 350: else ! 351: yClient = yStatsBtm - 1; ! 352: ! 353: /* discard unusable portion */ ! 354: yClient = yClient - (yClient % CNT_SQUARES_EDGE); ! 355: /* the scaling factors determine how large each square will be */ ! 356: xScale = xClient / CNT_SQUARES_EDGE; ! 357: yScale = yClient / CNT_SQUARES_EDGE; ! 358: ! 359: /* the entire game board is described by the points that are ! 360: * calculated here. ! 361: */ ! 362: for (i = 0; i < CNT_POINTS_EDGE; i++) { ! 363: aX[i] = i * xScale; ! 364: aY[i] = i * yScale; ! 365: } ! 366: /* consume any unused portion */ ! 367: aX[CNT_SQUARES_EDGE] = aX[CNT_SQUARES_EDGE] + xClient % CNT_SQUARES_EDGE; ! 368: aY[CNT_SQUARES_EDGE] = aY[CNT_SQUARES_EDGE] + yClient % CNT_SQUARES_EDGE - 1; ! 369: ! 370: /* now plug the points just calculated into the ! 371: * rectangles that make up the board ! 372: */ ! 373: for (i = 0; i < MAXRESOURCES; i++) { ! 374: aSquares[i].rcl.xLeft = aX [i % CNT_SQUARES_EDGE]; ! 375: aSquares[i].rcl.xRight = aX [(i % CNT_SQUARES_EDGE) + 1]; ! 376: aSquares[i].rcl.yBottom = aY [i / CNT_SQUARES_EDGE]; ! 377: aSquares[i].rcl.yTop = aY [(i / CNT_SQUARES_EDGE) + 1]; ! 378: } ! 379: /* store the descender for later */ ! 380: yDescGlobal = yDesc; ! 381: /* store top of board for later reference */ ! 382: yBoardTop = aY[CNT_SQUARES_EDGE]; ! 383: /* finally, store the width of the client window for later reference */ ! 384: xWidth = xClient; ! 385: } ! 386: ! 387: ! 388: ! 389: /****************************************************************\ ! 390: * client painting routine * ! 391: *--------------------------------------------------------------* ! 392: * * ! 393: * Name: MainPaint(hwnd) * ! 394: * * ! 395: * Purpose: Paints the main client window. * ! 396: * * ! 397: * Usage: Routine is called whenver the client window * ! 398: * procedure receives a WM_PAINT message * ! 399: * * ! 400: * Method: * ! 401: * - begins painting by calling WinBeginPaint * ! 402: * and retriving the HPS for the window * ! 403: * - performs any painting desired. Currently the * ! 404: * only painting it does is to draw rectangles on * ! 405: * the screen if semaphore is started. * ! 406: * - ends painting by calling WinEndPaint * ! 407: * * ! 408: * Returns: * ! 409: * * ! 410: \****************************************************************/ ! 411: ! 412: VOID MainPaint(hwnd) ! 413: HWND hwnd; /* handle of the window to be painted */ ! 414: { ! 415: HPS hps; ! 416: ! 417: hps = WinBeginPaint(hwnd, NULL, NULL); ! 418: GpiErase (hps); ! 419: DrawRects (hps); ! 420: WinEndPaint(hps); ! 421: ! 422: } /* MainPaint() */ ! 423:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.