home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk12 / calc / calc.c next >
Encoding:
C/C++ Source or Header  |  1990-07-09  |  21.0 KB  |  794 lines

  1. /****************************** Module Header *********************************/
  2. /*                                          */
  3. /* Module Name:  calc.c - Calc application                      */
  4. /*                                          */
  5. /* OS/2 Presentation Manager version of Calc, ported from Windows version     */
  6. /*                                          */
  7. /* Created by Microsoft Corporation, 1987                      */
  8. /*                                          */
  9. /******************************************************************************/
  10.  
  11. #define INCL_WININPUT
  12. #define INCL_WINPOINTERS
  13. #define INCL_WINMENUS
  14. #define INCL_WINSYS
  15. #define INCL_WINCLIPBOARD
  16. #define INCL_GPIPRIMITIVES
  17. #define INCL_GPIBITMAPS
  18. #define INCL_GPILCIDS
  19. #define INCL_DEV
  20. #define INCL_ERRORS
  21. #define INCL_DOSPROCESS
  22. #define INCL_DOSSEMAPHORES
  23. #define INCL_DOSNLS
  24. #include <os2.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include "calc.h"
  29.  
  30. /******************************************************************************/
  31. /*                                          */
  32. /*  GLOBAL VARIABLES                                  */
  33. /*                                          */
  34. /******************************************************************************/
  35.  
  36. CHAR  chLastKey, chCurrKey;
  37. CHAR  szreg1[20], szreg2[20], szmem[20], szregx[20];
  38. CHAR  szTitle[30], szErrorString[20], szPlusMinus[2];
  39. SHORT sCharWidth, sCharHeight;
  40. extern BOOL fError;
  41. BOOL  fValueInMemory = FALSE;
  42. BOOL  fMDown = FALSE;               /* TRUE iff 'm' key depressed  */
  43. UCHAR uchMScan = 0;               /* scan code for 'm' key       */
  44.  
  45. #define TOLOWER(x)   ( (((x) >= 'A') && ((x) <= 'Z')) ? (x)|0x20 : (x))
  46. #define WIDTHCONST  28
  47. #define CXCHARS     37
  48. #define CYCHARS     13
  49.  
  50. HAB hab;
  51. HDC hdcLocal;                /* Local used for button bitmap */
  52. HPS hpsLocal;
  53. HDC hdcSqr;                /* Sqr used for square-root bitmap */
  54. HPS hpsSqr;
  55. HBITMAP hbmLocal, hbmSqr;
  56. HMQ  hmqCalc;
  57. HWND hwndCalc, hwndMenu;
  58. HWND hwndCalcFrame;
  59. HPS  hpsCalc;
  60. HDC  hdcCalc;
  61. HPOINTER hptrFinger;
  62.  
  63. DEVOPENSTRUC dop =            /* used by DevOpenDC */
  64. {
  65.     NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL
  66. };
  67.  
  68. static char achKeys[25] =           /* keyboard keys */
  69. {
  70.     '\271', '0', '.', '\261', '+', '=',
  71.     '\272', '1', '2', '3', '-', 'c',
  72.     '\273', '4', '5', '6', '*', '%',
  73.     '\274', '7', '8', '9', '/', 'q',
  74.     NULL
  75. };
  76.  
  77. static CHAR achDKeys[25] =    /* 4th key is plusminus */
  78. {
  79.     ' ', '0', '.', '+', '+', '=',
  80.     ' ', '1', '2', '3', '-', 'C',
  81.     ' ', '4', '5', '6', '*', '%',
  82.     ' ', '7', '8', '9', '/', ' ',
  83.     NULL
  84. };
  85.  
  86. /******************************************************************************/
  87. /*                                          */
  88. /*  PROCEDURE DECLARATIONS                              */
  89. /*                                          */
  90. /******************************************************************************/
  91.  
  92. VOID FarStrcpy( PSZ, PSZ);
  93. MPARAM EXPENTRY AboutDlgProc( HWND, USHORT, MPARAM, MPARAM);
  94. BOOL CalcInit(VOID);
  95. VOID CalcPaint( HWND, HPS);
  96. VOID CalcTextOut( HPS, INT, INT, PCH, INT);
  97. MRESULT EXPENTRY CalcWndProc( HWND, USHORT, MPARAM, MPARAM);
  98. VOID cdecl main(VOID);
  99. VOID DataXCopy( VOID);
  100. VOID DataXPaste( VOID);
  101. VOID DrawNumbers( HPS);
  102. VOID Evaluate(BYTE);
  103. BOOL FlashSqr( HPS, PWPOINT);
  104. VOID FlipKey( HPS, INT, INT);
  105. VOID FrameKey( HPS, INT, INT);
  106. VOID InitCalc( VOID);
  107. BOOL InterpretChar( CHAR);
  108. VOID ProcessKey( PWPOINT);
  109. BOOL PSInit( VOID);
  110. CHAR Translate( PWPOINT);
  111. VOID UpdateDisplay( VOID);
  112.  
  113.  
  114. /******************************************************************************/
  115. /******************************************************************************/
  116. VOID CalcTextOut( hps, iX, iY, pch, iCount)
  117.  
  118. HPS hps;
  119. INT iX, iY;
  120. PCH pch;
  121. INT iCount;
  122. {
  123.     POINTL ptl;
  124.  
  125.     ptl.x = iX;
  126.     ptl.y = iY;
  127.  
  128.     GpiSetColor( hps, CLR_BLACK);
  129.     GpiCharStringAt( hps, (PPOINTL)&ptl, (LONG)iCount, (PSZ)pch);
  130. }
  131.  
  132.  
  133. /******************************************************************************/
  134. /* Write the appropriate number or error string to the display area          */
  135. /* and mark memory-in-use if appropriate.                      */
  136. /******************************************************************************/
  137. VOID
  138. UpdateDisplay()
  139. {
  140.     RECTL rcl;
  141.  
  142.     rcl.xLeft = (6 * sCharWidth);
  143.     rcl.yBottom = 1050 * sCharHeight / 100;
  144.     rcl.xRight = rcl.xLeft + (12 * sCharWidth);
  145.     rcl.yTop = rcl.yBottom + (3 * sCharHeight) / 2;
  146.  
  147.     WinFillRect( hpsCalc, &rcl, CLR_WHITE);     /* paint display area white */
  148.     if( fError)
  149.     WinDrawText( hpsCalc
  150.            , -1
  151.            , szErrorString
  152.            , &rcl
  153.            , CLR_BLACK
  154.            , CLR_WHITE
  155.            , DT_RIGHT | DT_VCENTER );
  156.     else
  157.     WinDrawText( hpsCalc
  158.            , -1
  159.            , szreg1
  160.            , &rcl
  161.            , CLR_BLACK
  162.            , CLR_WHITE
  163.            , DT_RIGHT | DT_VCENTER );
  164.  
  165.     if (fValueInMemory)         /* little black square shows mem use */
  166.     {
  167.     rcl.xLeft = (6 * sCharWidth);
  168.     rcl.yBottom = 1050 * sCharHeight / 100;
  169.     rcl.xRight = rcl.xLeft + (sCharWidth / 2);
  170.     rcl.yTop = rcl.yBottom + (sCharHeight / 2);
  171.     WinFillRect( hpsCalc, &rcl, CLR_BLACK);
  172.     }
  173. }
  174.  
  175.  
  176. /******************************************************************************/
  177. /*  Display helpful info                              */
  178. /******************************************************************************/
  179. MPARAM EXPENTRY
  180. AboutDlgProc( hwnd, msg, mp1, mp2)
  181.  
  182. HWND   hwnd;
  183. USHORT msg;
  184. MPARAM mp1;
  185. MPARAM mp2;
  186. {
  187.     if (msg == WM_COMMAND)
  188.     {
  189.         WinDismissDlg(hwnd, TRUE);
  190.     return(MPFROMSHORT(TRUE));
  191.     }
  192.     else return(WinDefDlgProc( hwnd, msg, mp1, mp2));
  193. }
  194.  
  195.  
  196. /******************************************************************************/
  197. /*  General initialization                              */
  198. /******************************************************************************/
  199. BOOL
  200. CalcInit()
  201. {
  202.     hab = WinInitialize( NULL);
  203.  
  204.     hmqCalc = WinCreateMsgQueue( hab, 0);
  205.     if( !hmqCalc)
  206.         return(FALSE);
  207.  
  208.     WinLoadString( NULL, NULL, 1, 30, (PSZ)szTitle);
  209.     WinLoadString( NULL, NULL, 2, 20, (PSZ)szErrorString);
  210.     WinLoadString( NULL, NULL, 3, 2, (PSZ)szPlusMinus);
  211.  
  212.     if (!WinRegisterClass( hab, szTitle, CalcWndProc, CS_SIZEREDRAW, 0))
  213.         return(FALSE);
  214.  
  215.     hptrFinger = WinLoadPointer( HWND_DESKTOP, (HMODULE)NULL, IDP_FINGER);
  216.  
  217.     InitCalc();             /* arithmetic initialization */
  218.  
  219.     return(TRUE);
  220. }
  221.  
  222. /******************************************************************************/
  223. /*  main procedure                                  */
  224. /******************************************************************************/
  225. VOID cdecl
  226. main()
  227. {
  228.     QMSG  qmsg;
  229.     ULONG ulFCF;
  230.  
  231.     if (!CalcInit()) {                /* general initialization */
  232.     WinAlarm(HWND_DESKTOP, WA_ERROR);
  233.         goto exit;
  234.     }
  235.  
  236.     if (!PSInit()) {                /* presentation spaces & bitmaps */
  237.     WinAlarm(HWND_DESKTOP, WA_ERROR);
  238.         goto exit;
  239.     }
  240.  
  241.     ulFCF = FCF_STANDARD & ~(LONG)(FCF_SIZEBORDER | FCF_MAXBUTTON);
  242.     hwndCalcFrame = WinCreateStdWindow( HWND_DESKTOP
  243.                       , WS_VISIBLE | FS_BORDER
  244.                       , &ulFCF
  245.                       , szTitle
  246.                       , NULL
  247.                       , 0L
  248.                       , NULL
  249.                       , IDR_CALC
  250.                       , &hwndCalc);
  251.  
  252.     WinSetWindowPos( hwndCalcFrame
  253.            , (HWND)NULL
  254.            , 2
  255.            , 2
  256.            , CXCHARS * sCharWidth
  257.            , CYCHARS * sCharHeight
  258.                  + (SHORT)WinQuerySysValue( HWND_DESKTOP
  259.                               , SV_CYTITLEBAR )
  260.                  + (SHORT)WinQuerySysValue( HWND_DESKTOP
  261.                               , SV_CYMENU )
  262.            , SWP_MOVE | SWP_SIZE );
  263.  
  264.     while (WinGetMsg( hab, &qmsg, NULL, 0, 0))
  265.     WinDispatchMsg( hab, &qmsg);
  266.  
  267. exit:                        /* clean up */
  268.     if (hdcSqr)                 /* square-root bitmap */
  269.     {
  270.     GpiDestroyPS( hpsSqr);
  271.     if (hbmSqr)
  272.         GpiDeleteBitmap( hbmSqr);
  273.     }
  274.  
  275.     if (hdcLocal)                /* keypad button */
  276.     {
  277.     GpiDestroyPS( hpsLocal);
  278.     if (hbmLocal)
  279.         GpiDeleteBitmap( hbmLocal);
  280.     }
  281.  
  282.     WinDestroyWindow(hwndCalcFrame);
  283.  
  284.     WinDestroyMsgQueue(hmqCalc);
  285.     WinTerminate(hab);
  286.  
  287.     DosExit(EXIT_PROCESS, 0);            /* exit without error */
  288. }
  289.  
  290.  
  291. /******************************************************************************/
  292. /* Calc Window Procedure                              */
  293. /******************************************************************************/
  294. MRESULT EXPENTRY
  295. CalcWndProc(hwnd, msg, mp1, mp2)
  296.  
  297. HWND    hwnd;
  298. USHORT    msg;
  299. MPARAM    mp1;
  300. MPARAM    mp2;
  301. {
  302.     HPS     hps;
  303.     RECTL   rclPaint;
  304.     WPOINT  wpt;
  305.     BOOL    fClip;
  306.     USHORT  usFmtInfo;
  307.     RECTL   rcl;
  308.     SIZEL   sizl;
  309.  
  310.     switch (msg)
  311.     {
  312.     case WM_CREATE:
  313.     hdcCalc = WinOpenWindowDC( hwnd);
  314.     WinQueryWindowRect( hwnd, &rcl);
  315.     sizl.cx = rcl.xRight - rcl.xLeft;
  316.     sizl.cy = rcl.yTop - rcl.yBottom;
  317.     hpsCalc = GpiCreatePS( hab
  318.                  , hdcCalc
  319.                  , &sizl
  320.                  , GPIA_ASSOC | PU_PELS );
  321.         break;
  322.  
  323.     case WM_DESTROY:
  324.         WinDestroyPointer(hptrFinger);
  325.     GpiDestroyPS( hpsSqr);
  326.     GpiDeleteBitmap( hbmSqr);
  327.     GpiDestroyPS( hpsLocal);
  328.     GpiDeleteBitmap( hbmLocal);
  329.         break;
  330.  
  331.     case WM_INITMENU:
  332.         fClip = FALSE;
  333.     if (WinOpenClipbrd( hab))
  334.         {
  335.         fClip = WinQueryClipbrdFmtInfo( hab, CF_TEXT, &usFmtInfo);
  336.         WinCloseClipbrd( hab);
  337.         }
  338.     WinSendMsg((HWND)mp2, MM_SETITEMATTR,
  339.            (MPARAM) MAKELONG(CMD_PASTE, TRUE),
  340.            (MPARAM) MAKELONG(MIA_DISABLED, fClip ? 0 : MIA_DISABLED));
  341.         break;
  342.  
  343.     case WM_PAINT:
  344.     hps = WinBeginPaint(hwnd, NULL, &rclPaint);
  345.     CalcPaint( hwnd, hps);                /* re-draw calculator */
  346.         WinEndPaint(hps);
  347.         break;
  348.  
  349.     case WM_COMMAND:
  350.     if (fError)
  351.             break;
  352.         switch(LOUSHORT(mp1))
  353.         {
  354.         case CMD_COPY:
  355.         DataXCopy();            /* copy to clipboard */
  356.             break;
  357.         case CMD_PASTE:
  358.         DataXPaste();            /* paste from clipboard */
  359.             break;
  360.         case CMD_EXIT:
  361.         WinPostMsg( hwndCalcFrame, WM_QUIT, 0L, 0L);
  362.             break;
  363.         case CMD_ABOUT:
  364.         WinDlgBox( HWND_DESKTOP
  365.              , hwndCalcFrame
  366.              , (PFNWP)AboutDlgProc
  367.              , NULL
  368.              , 1
  369.              , (PSZ)NULL );
  370.             break;
  371.         }
  372.         break;
  373.  
  374.     case WM_CLOSE:
  375.         WinPostMsg(hwndCalcFrame, WM_QUIT, 0L, 0L);
  376.         break;
  377.  
  378.     case WM_MOUSEMOVE:
  379.     WinSetPointer( HWND_DESKTOP, hptrFinger);
  380.         break;
  381.  
  382.     case WM_BUTTON1DOWN:
  383.     wpt.x = LOUSHORT(mp1);
  384.     wpt.y = HIUSHORT(mp1);
  385.     ProcessKey( &wpt);
  386.         goto dwp;
  387.         break;
  388.  
  389.     case WM_CHAR:
  390.     if (SHORT1FROMMP(mp1) & KC_KEYUP)
  391.     {
  392.         if (CHAR4FROMMP(mp1) == uchMScan)
  393.            fMDown = FALSE;         /* 'm' key went up */
  394.     }
  395.     else 
  396.     {
  397.         if (SHORT1FROMMP(mp1) & KC_CHAR)
  398.       {
  399.          if (InterpretChar((UCHAR)SHORT1FROMMP(mp2)))
  400.           {    
  401.                 UpdateDisplay();
  402.           }
  403.          else 
  404.           {
  405.                   if (((UCHAR)SHORT1FROMMP(mp2)== 'm') || ((UCHAR)SHORT1FROMMP(mp2)== 'M'))
  406.                 {
  407.                     uchMScan = CHAR4FROMMP(mp1);       /* save 'm' key scan code  */
  408.                     fMDown = TRUE;               /* 'm' key went down       */
  409.                 }
  410.         }
  411.         }
  412.     }
  413.         break;
  414.  
  415.     case WM_ACTIVATE:
  416.         if (HIUSHORT(mp1))
  417.         WinSetFocus( HWND_DESKTOP, hwndCalc);
  418.     break;
  419.  
  420.     case WM_SETFOCUS:
  421.     if ((HWNDFROMMP(mp1)==hwndCalc) && !mp2);
  422.         fMDown = FALSE;            /* since we are losing focus */
  423.     break;
  424.  
  425. dwp:
  426.     default:
  427.         return(WinDefWindowProc(hwnd, msg, mp1, mp2));
  428.         break;
  429.     }
  430.     return(0L);
  431. }
  432.  
  433.  
  434. /******************************************************************************/
  435. /*  translate & interpret keys (ie. locate in logical keyboard)           */
  436. /******************************************************************************/
  437. BOOL
  438. InterpretChar( ch)
  439.  
  440. CHAR ch;
  441. {
  442.     BOOL fDone;
  443.     NPCH pchStep;
  444.     INT  i;
  445.  
  446.     fDone = FALSE;
  447.     pchStep = achKeys;
  448.     switch (ch)
  449.     {
  450.     case 'n':
  451.     ch = szPlusMinus[0];
  452.         break;
  453.     case 27:                        /* xlate Escape into 'c' */
  454.         ch = 'c';
  455.         break;
  456.     case '\r':                      /* xlate Enter into '=' */
  457.         ch = '=';
  458.         break;
  459.     }
  460.  
  461.     if (fMDown)             /* Do memory keys */
  462.     {
  463.         switch (ch)
  464.         {
  465.         case 'c':
  466.         case 'C':
  467.             ch = '\274';
  468.             break;
  469.         case 'r':
  470.         case 'R':
  471.             ch = '\273';
  472.             break;
  473.         case '+':
  474.             ch = '\272';
  475.             break;
  476.         case '-':
  477.             ch = '\271';
  478.             break;
  479.         }
  480.     }
  481.  
  482.     while (!fDone && *pchStep)
  483.     {
  484.     if ((CHAR) *pchStep++ == ch)
  485.         fDone = TRUE;        /* char found in logical keyboard */
  486.     }
  487.     if (fDone)
  488.     {
  489.     chLastKey = chCurrKey;
  490.     i = pchStep - achKeys - 1;
  491.     FlipKey( hpsCalc, i/6, i%6);
  492.     Evaluate( achKeys[i]);
  493.     }
  494.     return (fDone);
  495. }
  496.  
  497.  
  498. /******************************************************************************/
  499. /*  briefly reverse the shading on one of the keys                  */
  500. /******************************************************************************/
  501. VOID
  502. FlipKey( hps, iRow, iCol)
  503.  
  504. HPS hps;
  505. INT iRow, iCol;
  506. {
  507.     RECTL rcl;
  508.  
  509.     rcl.xLeft = (iCol * 6 * sCharWidth) + (14 * sCharWidth / 10);
  510.     rcl.yBottom = (165 * sCharHeight / 100) + (2 * iRow * sCharHeight);
  511.     rcl.xRight = rcl.xLeft + (11 * sCharWidth / 3);
  512.     rcl.yTop = rcl.yBottom + (7 * sCharHeight / 4);
  513.     WinInvertRect( hps, &rcl);
  514.     DosSleep( 50L);
  515.     WinInvertRect( hps, &rcl);
  516. }
  517.  
  518.  
  519. /******************************************************************************/
  520. /*  compute whether a point is over a button and flash the button if so       */
  521. /******************************************************************************/
  522. BOOL
  523. FlashSqr( hps, pwpt)
  524.  
  525. HPS     hps;
  526. PWPOINT  pwpt;
  527. {
  528.     INT  iRow, iCol;
  529.     BOOL fDone;
  530.  
  531.     /* find x range */
  532.     fDone = FALSE;
  533.     iCol = 0;
  534.     iRow = 3;
  535.     while (!fDone && iCol<6)
  536.     {
  537.     if (pwpt->x <    (iCol * 6 * sCharWidth)
  538.                + (14 * sCharWidth / 10)
  539.                + (11*sCharWidth/3)     )
  540.         {
  541.         if (pwpt->x > (iCol * 6 * sCharWidth) + (14 * sCharWidth / 10))
  542.                 fDone = TRUE;
  543.             else
  544.                 return FALSE;
  545.         }
  546.         else
  547.         iCol++;
  548.     }
  549.     if (!fDone)
  550.         return FALSE;
  551.     fDone = FALSE;
  552.     while (!fDone && iRow >= 0)
  553.     {
  554.     if (pwpt->y > ((165 * sCharHeight / 100) + (2 * iRow * sCharHeight)))
  555.         {
  556.         if (pwpt->y <   (165 * sCharHeight / 100)
  557.                + (2 * iRow * sCharHeight)
  558.                + (7 * sCharHeight / 4)     )
  559.                 fDone = TRUE;
  560.             else
  561.                 return FALSE;
  562.         }
  563.         else
  564.         iRow--;
  565.     }
  566.     if (!fDone)
  567.         return FALSE;
  568.     pwpt->x = iCol;
  569.     pwpt->y = iRow;
  570.     FlipKey( hps, iRow, iCol);
  571.     return TRUE;
  572. }
  573.  
  574.  
  575. /******************************************************************************/
  576. /*  which key is point on?                              */
  577. /******************************************************************************/
  578. CHAR
  579. Translate( pwpt)
  580.  
  581. PWPOINT pwpt;
  582. {
  583.     return( achKeys[ pwpt->y * 6 + pwpt->x]);
  584. }
  585.  
  586.  
  587. /******************************************************************************/
  588. /*  invoke flashing, point-to-key translation, and result-display update      */
  589. /******************************************************************************/
  590. VOID
  591. ProcessKey( pwpt)
  592.  
  593. PWPOINT pwpt;
  594. {
  595.     BOOL fFlashed;
  596.  
  597.     chLastKey = chCurrKey;
  598.     fFlashed = FlashSqr( hpsCalc, pwpt);
  599.  
  600.     if (fFlashed)
  601.     Evaluate( (BYTE)Translate( pwpt));
  602.     UpdateDisplay();
  603. }
  604.  
  605.  
  606. /******************************************************************************/
  607. /*  draw a blank key                                  */
  608. /******************************************************************************/
  609. VOID
  610. FrameKey(hps, iRow, iCol)
  611.  
  612. HPS hps;
  613. INT iRow, iCol;
  614. {
  615.     POINTL aptl[3];
  616.  
  617.     aptl[0].x = (iCol * 6 * sCharWidth) + (14 * sCharWidth / 10);
  618.     aptl[0].y = (165 * sCharHeight / 100) + (2 * iRow * sCharHeight);
  619.     aptl[1].x = (11 * sCharWidth / 3) + (aptl[0].x);
  620.     aptl[1].y = (7 * sCharHeight / 4) + (aptl[0].y);
  621.     aptl[2].x = 0;
  622.     aptl[2].y = 0;
  623.     GpiBitBlt( hps, hpsLocal, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE);
  624. }
  625.  
  626.  
  627. /******************************************************************************/
  628. /*  draw the keys and fill in numbers                          */
  629. /******************************************************************************/
  630. VOID
  631. DrawNumbers(hps)
  632.  
  633. HPS hps;
  634. {
  635.     INT iRow, iCol;
  636.  
  637.     /* Draw the keys and fill in the numbers we can */
  638.     for (iRow = 0; iRow < 4; iRow++)
  639.     {
  640.     for (iCol = 0; iCol < 6; iCol++)
  641.         {
  642.         FrameKey( hps, iRow, iCol);
  643.         CalcTextOut( hps
  644.                ,   (iCol * 6 * sCharWidth)
  645.              + (WIDTHCONST * sCharWidth / 10)
  646.                , (iRow + 1) * 2 * sCharHeight
  647.                , (PSZ)(achDKeys + (iRow * 6) + iCol)
  648.                , 1 );
  649.         }
  650.     }
  651. }
  652.  
  653.  
  654. /******************************************************************************/
  655. /*  redraw the whole calculator                           */
  656. /******************************************************************************/
  657. VOID
  658. CalcPaint( hwnd, hps)
  659.  
  660. HWND hwnd;
  661. HPS  hps;
  662. {
  663.     RECTL      rclDst;
  664.     CHARBUNDLE cbnd;
  665.     INT        iX, iY;
  666.  
  667.     WinQueryWindowRect( hwnd, &rclDst);
  668.     WinFillRect( hps, &rclDst, CLR_GREEN);
  669.  
  670.     DrawNumbers(hps);
  671.     CalcTextOut(hps, iX = (11 * sCharWidth / 5) + 1, iY = 2 * sCharHeight,
  672.                (PSZ)"M-", 2);
  673.     CalcTextOut(hps, iX, iY + 2 * sCharHeight, (PSZ)"M+", 2);
  674.     CalcTextOut(hps, iX, iY + 4 * sCharHeight, (PSZ)"MR", 2);
  675.     CalcTextOut(hps, iX, iY + 6 * sCharHeight, (PSZ)"MC", 2);
  676.  
  677.     /* Draw the minus of the plus/minus button */
  678.     cbnd.usBackMixMode = FM_LEAVEALONE;
  679.     GpiSetAttrs( hps, PRIM_CHAR, CBB_BACK_MIX_MODE, 0L, &cbnd);
  680.     iX =  (3 * 6 * sCharWidth) + (WIDTHCONST * sCharWidth / 10);
  681.     CalcTextOut( hps, iX, iY + sCharHeight / 4, (PSZ)"_", 1);
  682.  
  683.     /* Draw the square root bitmap */
  684.     rclDst.xLeft = 160 * sCharWidth / 5;
  685.     rclDst.yBottom = 31 * sCharHeight / 4;
  686.     rclDst.xRight = rclDst.xLeft + 2 * sCharWidth;
  687.     rclDst.yTop = rclDst.yBottom + (3 * sCharHeight / 2);
  688.     WinDrawBitmap( hps
  689.          , hbmSqr
  690.          , NULL
  691.          , (PPOINTL)&rclDst
  692.          , CLR_WHITE
  693.          , CLR_BLACK
  694.          , DBM_STRETCH );
  695.  
  696.     UpdateDisplay();
  697. }
  698.  
  699.  
  700. /******************************************************************************/
  701. /*  initialize the bitmaps for a blank key and for the square-root sign       */
  702. /******************************************************************************/
  703. BOOL
  704. PSInit()
  705. {
  706.     HPS          hps;
  707.     FONTMETRICS      fm;
  708.     POINTL         ptl;
  709.     SIZEL         sizl;
  710.     BITMAPINFOHEADER bmp;
  711.     POINTL         aptl[4];
  712.     LONG         alCaps[2];
  713.  
  714.     /**************************************************************************/
  715.     /*    compute the units of horizontal and vertical distance based on font   */
  716.     /**************************************************************************/
  717.     hps = WinGetPS( HWND_DESKTOP);
  718.     GpiQueryFontMetrics( hps, (LONG)sizeof(FONTMETRICS), &fm);
  719.     sCharHeight = (SHORT)(fm.lEmHeight); /* avg height of uppercase character */
  720.     sCharWidth    = (SHORT)(fm.lEmInc);     /* usually 'M' increment          */
  721.     WinReleasePS( hps);
  722.  
  723.     /**************************************************************************/
  724.     /*    prepare the square root bitmap                          */
  725.     /**************************************************************************/
  726.     hdcSqr = DevOpenDC( hab, OD_MEMORY, "*", 3L, (PDEVOPENDATA)&dop, NULL);
  727.     if( !hdcSqr)
  728.     return(FALSE);
  729.  
  730.     sizl.cx = sizl.cy = 0L;
  731.     hpsSqr = GpiCreatePS( hab
  732.             , hdcSqr
  733.             , &sizl
  734.             , PU_PELS | GPIT_MICRO | GPIA_ASSOC );
  735.     hbmSqr = GpiLoadBitmap( hpsSqr, NULL, IDB_SQR, 0L, 0L);
  736.  
  737.     /**************************************************************************/
  738.     /*    prepare the bitmap of a blank key                      */
  739.     /**************************************************************************/
  740.     hdcLocal = DevOpenDC( hab, OD_MEMORY, "*", 3L, (PDEVOPENDATA)&dop, NULL);
  741.     if( !hdcLocal)
  742.     return(FALSE);
  743.  
  744.     sizl.cx = sizl.cy = 0L;
  745.     hpsLocal = GpiCreatePS( hab
  746.               , hdcLocal
  747.               , &sizl
  748.               , PU_PELS | GPIT_MICRO | GPIA_ASSOC );
  749.     bmp.cbFix = 12;
  750.     bmp.cx = 11 * sCharWidth / 3;
  751.     bmp.cy = sCharHeight * 2;
  752.     DevQueryCaps( hdcLocal, CAPS_COLOR_PLANES, 2L, alCaps);
  753.     bmp.cPlanes = (USHORT)alCaps[0];
  754.     bmp.cBitCount = (USHORT)alCaps[1];
  755.     hbmLocal = GpiCreateBitmap( hpsLocal, &bmp, 0L, NULL, NULL);
  756.     if( !hbmLocal )
  757.     return(FALSE);
  758.     GpiSetBitmap( hpsLocal, hbmLocal);
  759.  
  760.     aptl[0].x = aptl[0].y = 0;
  761.     aptl[1].x = 11 * sCharWidth / 3;
  762.     aptl[1].y = 7 * sCharHeight / 4;
  763.     aptl[2].x = aptl[2].y = 0;
  764.     aptl[3].x = aptl[1].x;
  765.     aptl[3].y = aptl[1].y;
  766.     GpiSetColor( hpsLocal, CLR_GREEN);        /* match the background to client */
  767.     GpiBitBlt( hpsLocal, NULL, 2L, aptl, ROP_PATCOPY, BBO_IGNORE);
  768.  
  769.     /* Draw the rounded rect */
  770.     ptl.x = 0;
  771.     ptl.y = 0;
  772.     GpiSetCurrentPosition( hpsLocal, &ptl);
  773.     ptl.x = (11 * sCharWidth / 3) - 1;
  774.     ptl.y = (7 * sCharHeight / 4) - 1;
  775.     GpiSetColor( hpsLocal, CLR_WHITE);        /* white interior              */
  776.     GpiBox( hpsLocal
  777.       , DRO_FILL
  778.       , &ptl
  779.       , (LONG)sCharWidth
  780.       , (LONG)(sCharHeight / 2) );
  781.     ptl.x = 0;
  782.     ptl.y = 0;
  783.     GpiSetCurrentPosition( hpsLocal, &ptl);
  784.     ptl.x = (11 * sCharWidth / 3) - 1;
  785.     ptl.y = (7 * sCharHeight / 4) - 1;
  786.     GpiSetColor( hpsLocal, CLR_BLACK);        /* black border              */
  787.     GpiBox( hpsLocal
  788.       , DRO_OUTLINE
  789.       , &ptl
  790.       , (LONG)sCharWidth
  791.       , (LONG)(sCharHeight / 2) );
  792.     return( TRUE);
  793. }
  794.