home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / prog_pm / chap08 / typeaway.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-01-09  |  17.4 KB  |  448 lines

  1. /*------------------------------
  2.    TYPEAWAY.C -- Typing Program
  3.   ------------------------------*/
  4.  
  5. #define INCL_WIN
  6. #define INCL_GPI
  7. #include <os2.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include "easyfont.h"
  11.  
  12. #define LCID_FIXEDFONT 1L
  13. #define BUFFER(x,y) (*(pBuffer + y * xMax + x))
  14.  
  15. MRESULT EXPENTRY ClientWndProc (HWND, USHORT, MPARAM, MPARAM) ;
  16.  
  17. CHAR szClientClass [] = "TypeAway" ;
  18. HAB  hab ;
  19.  
  20. int main (void)
  21.      {
  22.      static ULONG flFrameFlags = FCF_TITLEBAR      | FCF_SYSMENU |
  23.                                  FCF_SIZEBORDER    | FCF_MINMAX  |
  24.                                  FCF_SHELLPOSITION | FCF_TASKLIST ;
  25.      HMQ          hmq ;
  26.      HWND         hwndFrame, hwndClient ;
  27.      QMSG         qmsg ;
  28.  
  29.      hab = WinInitialize (0) ;
  30.      hmq = WinCreateMsgQueue (hab, 0) ;
  31.  
  32.      WinRegisterClass (hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0) ;
  33.  
  34.      hwndFrame = WinCreateStdWindow (HWND_DESKTOP, WS_VISIBLE,
  35.                                      &flFrameFlags, szClientClass, NULL,
  36.                      0L, NULL, 0, &hwndClient) ;
  37.      if (hwndFrame != NULL)
  38.           {
  39.           WinSendMsg (hwndFrame, WM_SETICON,
  40.                       WinQuerySysPointer (HWND_DESKTOP, SPTR_APPICON, FALSE),
  41.                       NULL) ;
  42.  
  43.           while (WinGetMsg (hab, &qmsg, NULL, 0, 0))
  44.                WinDispatchMsg (hab, &qmsg) ;
  45.  
  46.           WinDestroyWindow (hwndFrame) ;
  47.           }
  48.      WinDestroyMsgQueue (hmq) ;
  49.      WinTerminate (hab) ;
  50.      return 0 ;
  51.      }
  52.  
  53. VOID GetCharXY (HPS hps, SHORT *pcxChar, SHORT *pcyChar, SHORT *pcyDesc)
  54.      {
  55.      FONTMETRICS fm ;
  56.  
  57.      GpiQueryFontMetrics (hps, (LONG) sizeof fm, &fm) ;
  58.      *pcxChar = (SHORT) fm.lAveCharWidth ;
  59.      *pcyChar = (SHORT) fm.lMaxBaselineExt ;
  60.      *pcyDesc = (SHORT) fm.lMaxDescender ;
  61.      }
  62.  
  63. MRESULT EXPENTRY ClientWndProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  64.      {
  65.      static BOOL  fInsertMode = FALSE ;
  66.      static CHAR  *pBuffer ;
  67.      static SHORT cxClient, cyClient, cxChar, cyChar, cyDesc,
  68.                   xCursor, yCursor, xMax,  yMax ;
  69.      BOOL         fProcessed ;
  70.      CHAR         szBuffer [20] ;
  71.      HPS          hps ;
  72.      POINTL       ptl ;
  73.      RECTL        rcl ;
  74.      SHORT        sRep, s ;
  75.  
  76.      switch (msg)
  77.           {
  78.           case WM_CREATE:
  79.                hps = WinGetPS (hwnd) ;
  80.                EzfQueryFonts (hps) ;
  81.  
  82.                if (!EzfCreateLogFont (hps, LCID_FIXEDFONT, FONTFACE_COUR,
  83.                                                            FONTSIZE_10, 0))
  84.                     {
  85.                     WinReleasePS (hps) ;
  86.  
  87.                     WinMessageBox (HWND_DESKTOP, HWND_DESKTOP,
  88.                          "Cannot find a fixed-pitch font.  Load the Courier "
  89.                          "fonts from the Control Panel and try again.",
  90.                          szClientClass, 0, MB_OK | MB_ICONEXCLAMATION) ;
  91.  
  92.                     return 1 ;
  93.                     }
  94.  
  95.                GpiSetCharSet (hps, LCID_FIXEDFONT) ;
  96.  
  97.                GetCharXY (hps, &cxChar, &cyChar, &cyDesc) ;
  98.  
  99.                GpiSetCharSet (hps, LCID_DEFAULT) ;
  100.                GpiDeleteSetId (hps, LCID_FIXEDFONT) ;
  101.                WinReleasePS (hps) ;
  102.                return 0 ;
  103.  
  104.           case WM_SIZE:
  105.                cxClient = SHORT1FROMMP (mp2) ;
  106.                cyClient = SHORT2FROMMP (mp2) ;
  107.  
  108.                xMax = min (255, cxClient / cxChar) ;
  109.                yMax = min (255, cyClient / cyChar - 2) ;
  110.  
  111.                if (pBuffer != NULL)
  112.                     free (pBuffer) ;
  113.  
  114.                if (NULL == (pBuffer = malloc (xMax * yMax + 1)))
  115.                     {
  116.                     WinMessageBox (HWND_DESKTOP, hwnd,
  117.                          "Cannot allocate memory for text buffer.\n"
  118.                          "Try a smaller window.", szClientClass, 0,
  119.                          MB_OK | MB_ICONEXCLAMATION) ;
  120.  
  121.                     xMax = yMax = 0 ;
  122.                     }
  123.                else
  124.                     {                    
  125.                     for (s = 0 ; s < xMax * yMax ; BUFFER (s++, 0) = ' ') ;
  126.  
  127.                     xCursor = 0 ;
  128.                     yCursor = 0 ;
  129.                     }
  130.  
  131.                if (hwnd == WinQueryFocus (HWND_DESKTOP, FALSE))
  132.                     {
  133.                     WinDestroyCursor (hwnd) ;
  134.  
  135.                     WinCreateCursor (hwnd, 0, cyClient - cyChar,
  136.                                      cxChar, cyChar,
  137.                                      CURSOR_SOLID | CURSOR_FLASH, NULL) ;
  138.  
  139.                     WinShowCursor (hwnd, xMax > 0 && yMax > 0) ;
  140.                     }
  141.                return 0 ;
  142.  
  143.           case WM_SETFOCUS:
  144.                if (SHORT1FROMMP (mp2))
  145.                     {
  146.                     WinCreateCursor (hwnd, cxChar * xCursor,
  147.                                      cyClient - cyChar * (1 + yCursor),
  148.                                      cxChar, cyChar,
  149.                                      CURSOR_SOLID | CURSOR_FLASH, NULL) ;
  150.  
  151.                     WinShowCursor (hwnd, xMax > 0 && yMax > 0) ;
  152.                     }
  153.                else
  154.                     WinDestroyCursor (hwnd) ;
  155.                return 0 ;
  156.  
  157.           case WM_CHAR:
  158.                if (xMax == 0 || yMax == 0)
  159.                     return 0 ;
  160.  
  161.                if (CHARMSG(&msg)->fs & KC_KEYUP)
  162.                     return 0 ;
  163.  
  164.                if (CHARMSG(&msg)->fs & KC_INVALIDCHAR)
  165.                     return 0 ;
  166.  
  167.                if (CHARMSG(&msg)->fs & KC_INVALIDCOMP)
  168.                     {
  169.                     xCursor = (xCursor + 1) % xMax ;        // Advance cursor
  170.                     if (xCursor == 0)
  171.                          yCursor = (yCursor + 1) % yMax ;
  172.  
  173.                     WinAlarm (HWND_DESKTOP, WA_ERROR) ;     // And beep
  174.                     }
  175.  
  176.                for (sRep = 0 ; sRep < CHARMSG(&msg)->cRepeat ; sRep++)
  177.                     {
  178.                     fProcessed = FALSE ;
  179.  
  180.                     ptl.x = xCursor * cxChar ;
  181.                     ptl.y = cyClient - cyChar * (yCursor + 1) + cyDesc ;
  182.  
  183.                               /*---------------------------
  184.                                  Process some virtual keys
  185.                                 ---------------------------*/
  186.  
  187.                     if (CHARMSG(&msg)->fs & KC_VIRTUALKEY)
  188.                          {
  189.                          fProcessed = TRUE ;
  190.  
  191.                          switch (CHARMSG(&msg)->vkey)
  192.                               {
  193.                                         /*---------------
  194.                                            Backspace key
  195.                                           ---------------*/
  196.  
  197.                               case VK_BACKSPACE:
  198.                                    if (xCursor > 0)
  199.                                         {
  200.                                         WinSendMsg (hwnd, WM_CHAR,
  201.                                              MPFROM2SHORT (KC_VIRTUALKEY, 1),
  202.                                              MPFROM2SHORT (0, VK_LEFT)) ;
  203.  
  204.                                         WinSendMsg (hwnd, WM_CHAR,
  205.                                              MPFROM2SHORT (KC_VIRTUALKEY, 1),
  206.                                              MPFROM2SHORT (0, VK_DELETE)) ;
  207.                                         }
  208.                                    break ;
  209.  
  210.                                         /*---------
  211.                                            Tab key
  212.                                           ---------*/
  213.  
  214.                               case VK_TAB:
  215.                                    s = min (8 - xCursor % 8, xMax - xCursor) ;
  216.  
  217.                                    WinSendMsg (hwnd, WM_CHAR, 
  218.                                         MPFROM2SHORT (KC_CHAR, s),
  219.                                         MPFROM2SHORT ((USHORT) ' ', 0)) ;
  220.                                    break ;
  221.  
  222.                                         /*-------------------------
  223.                                            Backtab (Shift-Tab) key
  224.                                           -------------------------*/
  225.  
  226.                               case VK_BACKTAB:
  227.                                    if (xCursor > 0)
  228.                                         {
  229.                                         s = (xCursor - 1) % 8 + 1 ;
  230.  
  231.                                         WinSendMsg (hwnd, WM_CHAR,
  232.                                              MPFROM2SHORT (KC_VIRTUALKEY, s),
  233.                                              MPFROM2SHORT (0, VK_LEFT)) ;
  234.                                         }
  235.                                    break ;
  236.  
  237.                                         /*------------------------
  238.                                            Newline and Enter keys
  239.                                           ------------------------*/
  240.  
  241.                               case VK_NEWLINE:
  242.                               case VK_ENTER:
  243.                                    xCursor = 0 ;
  244.                                    yCursor = (yCursor + 1) % yMax ;
  245.                                    break ;
  246.  
  247.                               default:
  248.                                    fProcessed = FALSE ;
  249.                                    break ;
  250.                               }
  251.                          }
  252.  
  253.                               /*------------------------
  254.                                  Process character keys
  255.                                 ------------------------*/
  256.  
  257.                     if (!fProcessed && CHARMSG(&msg)->fs & KC_CHAR)
  258.                          {
  259.                                                   // Shift line if fInsertMode
  260.                          if (fInsertMode)
  261.                               for (s = xMax - 1 ; s > xCursor ; s--)
  262.                                    BUFFER (s, yCursor) =
  263.                                         BUFFER (s - 1, yCursor) ;
  264.  
  265.                                                   // Store character in buffer
  266.  
  267.                          BUFFER (xCursor, yCursor) =
  268.                                              (CHAR) CHARMSG(&msg)->chr ;
  269.  
  270.                                                   // Display char or new line
  271.  
  272.                          WinShowCursor (hwnd, FALSE) ;
  273.                          hps = WinGetPS (hwnd) ;
  274.  
  275.                          EzfCreateLogFont (hps, LCID_FIXEDFONT,
  276.                                            FONTFACE_COUR, FONTSIZE_10, 0) ;
  277.                          GpiSetCharSet (hps, LCID_FIXEDFONT) ;
  278.                          GpiSetBackMix (hps, BM_OVERPAINT) ;
  279.  
  280.                          if (fInsertMode)
  281.                               GpiCharStringAt (hps, &ptl,
  282.                                                (LONG) (xMax - xCursor),
  283.                                                & BUFFER (xCursor, yCursor)) ;
  284.                          else
  285.                               GpiCharStringAt (hps, &ptl, 1L,
  286.                                                (CHAR *) & CHARMSG(&msg)->chr) ;
  287.  
  288.                          GpiSetCharSet (hps, LCID_DEFAULT) ;
  289.                          GpiDeleteSetId (hps, LCID_FIXEDFONT) ;
  290.                          WinReleasePS (hps) ;
  291.                          WinShowCursor (hwnd, TRUE) ;
  292.  
  293.                                                   // Increment cursor
  294.  
  295.                          if (!(CHARMSG(&msg)->fs & KC_DEADKEY))
  296.                               if (0 == (xCursor = (xCursor + 1) % xMax))
  297.                                    yCursor = (yCursor + 1) % yMax ;
  298.  
  299.                          fProcessed = TRUE ;
  300.                          }
  301.  
  302.                               /*--------------------------------
  303.                                  Process remaining virtual keys
  304.                                 --------------------------------*/
  305.  
  306.                     if (!fProcessed && CHARMSG(&msg)->fs & KC_VIRTUALKEY)
  307.                          {
  308.                          fProcessed = TRUE ;
  309.  
  310.                          switch (CHARMSG(&msg)->vkey)
  311.                               {
  312.                                         /*----------------------
  313.                                            Cursor movement keys
  314.                                           ----------------------*/
  315.  
  316.                               case VK_LEFT:
  317.                                    xCursor = (xCursor - 1 + xMax) % xMax ;
  318.  
  319.                                    if (xCursor == xMax - 1)
  320.                                         yCursor = (yCursor - 1 + yMax) % yMax ;
  321.                                    break ;
  322.  
  323.                               case VK_RIGHT:
  324.                                    xCursor = (xCursor + 1) % xMax ;
  325.  
  326.                                    if (xCursor == 0)
  327.                                         yCursor = (yCursor + 1) % yMax ;
  328.                                    break ;
  329.  
  330.                               case VK_UP:
  331.                                    yCursor = max (yCursor - 1, 0) ;
  332.                                    break ;
  333.  
  334.                               case VK_DOWN:
  335.                                    yCursor = min (yCursor + 1, yMax - 1) ;
  336.                                    break ;
  337.  
  338.                   case VK_PAGEUP:
  339.                                    yCursor = 0 ;
  340.                                    break ;
  341.  
  342.                   case VK_PAGEDOWN:
  343.                                    yCursor = yMax - 1 ;
  344.                                    break ;
  345.  
  346.                               case VK_HOME:
  347.                                    xCursor = 0 ;
  348.                                    break ;
  349.  
  350.                               case VK_END:
  351.                                    xCursor = xMax - 1 ;
  352.                                    break ;
  353.  
  354.                                         /*------------
  355.                                            Insert key
  356.                                           ------------*/
  357.  
  358.                               case VK_INSERT:
  359.                                    fInsertMode = fInsertMode ? FALSE : TRUE ;
  360.                                    WinSetRect (hab, &rcl, 0, 0,
  361.                                                cxClient, cyChar) ;
  362.                                    WinInvalidateRect (hwnd, &rcl, FALSE) ;
  363.                                    break ;
  364.  
  365.                                         /*------------
  366.                                            Delete key
  367.                                           ------------*/
  368.  
  369.                   case VK_DELETE:
  370.                                    for (s = xCursor ; s < xMax - 1 ; s++)
  371.                                         BUFFER (s, yCursor) =
  372.                                              BUFFER (s + 1, yCursor) ;
  373.  
  374.                                    BUFFER (xMax, yCursor) = ' ' ;
  375.  
  376.                                    WinShowCursor (hwnd, FALSE) ;
  377.                                    hps = WinGetPS (hwnd) ;
  378.                                    EzfCreateLogFont (hps, LCID_FIXEDFONT,
  379.                                              FONTFACE_COUR, FONTSIZE_10, 0) ;
  380.                                    GpiSetCharSet (hps, LCID_FIXEDFONT) ;
  381.                                    GpiSetBackMix (hps, BM_OVERPAINT) ;
  382.  
  383.                                    GpiCharStringAt (hps, &ptl,
  384.                                              (LONG) (xMax - xCursor), 
  385.                                              & BUFFER (xCursor, yCursor)) ;
  386.  
  387.                                    GpiSetCharSet (hps, LCID_DEFAULT) ;
  388.                                    GpiDeleteSetId (hps, LCID_FIXEDFONT) ;
  389.                                    WinReleasePS (hps) ;
  390.                                    WinShowCursor (hwnd, TRUE) ;
  391.                                    break ;
  392.  
  393.                               default:
  394.                                    fProcessed = FALSE ;
  395.                                    break ;
  396.                               }
  397.                          }
  398.                     }
  399.                WinCreateCursor (hwnd, cxChar * xCursor,
  400.                                       cyClient - cyChar * (1 + yCursor),
  401.                                       0, 0, CURSOR_SETPOS, NULL) ;
  402.                return 0 ;
  403.  
  404.           case WM_PAINT:
  405.                hps = WinBeginPaint (hwnd, NULL, NULL) ;
  406.                GpiErase (hps) ;
  407.                EzfCreateLogFont (hps, LCID_FIXEDFONT, FONTFACE_COUR,
  408.                                                       FONTSIZE_10, 0) ;
  409.                GpiSetCharSet (hps, LCID_FIXEDFONT) ;
  410.  
  411.                ptl.x = cxChar ;
  412.                ptl.y = cyDesc ;
  413.                GpiCharStringAt (hps, &ptl,
  414.                                 (LONG) sprintf (szBuffer, "Insert Mode: %s",
  415.                                                 fInsertMode ? "ON" : "OFF"),
  416.                                 szBuffer) ;
  417.  
  418.                ptl.x = 0 ;
  419.                ptl.y = 3 * cyChar / 2 ;
  420.                GpiMove (hps, &ptl) ;
  421.  
  422.                ptl.x = cxClient ;
  423.                GpiLine (hps, &ptl) ;
  424.  
  425.                if (xMax > 0 && yMax > 0)
  426.                     {
  427.                     for (s = 0 ; s < yMax ; s++)
  428.                          {
  429.                          ptl.x = 0 ;
  430.                          ptl.y = cyClient - cyChar * (s + 1) + cyDesc ;
  431.  
  432.                          GpiCharStringAt (hps, &ptl, (LONG) xMax,
  433.                                                      & BUFFER (0, s)) ;
  434.                          }
  435.                     }
  436.                GpiSetCharSet (hps, LCID_DEFAULT) ;
  437.                GpiDeleteSetId (hps, LCID_FIXEDFONT) ;
  438.                WinEndPaint (hps) ;
  439.                return 0 ;
  440.  
  441.           case WM_DESTROY:
  442.                if (pBuffer != NULL)
  443.                     free (pBuffer) ;
  444.                break ;
  445.           }
  446.      return WinDefWindowProc (hwnd, msg, mp1, mp2) ;
  447.      }
  448.