home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / shapewin.zip / shapewin.c < prev    next >
C/C++ Source or Header  |  1998-12-02  |  20KB  |  766 lines

  1. /*
  2.  * shapewin.c - Shape Window Control
  3.  *
  4.  *  version 1.01 - include speedup patch from "Takayuki Suwa (jjsuwa@ibm.net)"
  5.  *                 add some mouse events send to owner
  6.  */
  7.  
  8. #define INCL_PM
  9. #include <os2.h>
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14.  
  15. #include "shapewin.h"
  16.  
  17. #ifdef  SHPDEBUG
  18. #define TRACE       printf
  19. #else
  20. #define TRACE
  21. #endif
  22.  
  23. #ifdef  SHPDEBUG
  24. #define DUMPSWP(p)      \
  25.         printf("SWP %08x, flag %08x, size %d %d, pos %d %d, Z-Order %08x\n",\
  26.         (p), (p)->fl, (p)->cx, (p)->cy, (p)->x, (p)->y, (p)->hwndInsertBehind)
  27. #else
  28. #define DUMPSWP(p)
  29. #endif
  30.  
  31. /*
  32.  * forward decalations for Pointers
  33.  */
  34.  
  35. typedef struct  _SHPCTLREC  *SHPCTLPTR ;    /* Control Data     */
  36. typedef struct  _SHPRGNREC  *SHPRGNPTR ;    /* Drawing Region   */
  37.  
  38. /*
  39.  * Internal Record to Manage Shape Window (as Window Pointer)
  40.  */
  41.  
  42. typedef struct _SHPCTLREC {
  43.     /*
  44.      * Common Window Parameters (CREATESTRUCT)
  45.      */
  46.     HWND        hwndSelf   ;    /* Window Handle of Self    */
  47.     HWND        hwndParent ;    /* Parent of this Control   */
  48.     HWND        hwndOwner  ;    /* Owner  of this Control   */
  49.     USHORT      id         ;    /* Window ID                */
  50.     SHORT       x          ;    /* x - horz. position       */
  51.     SHORT       y          ;    /* y - vert. position       */
  52.     SHORT       cx         ;    /* horz. size               */
  53.     SHORT       cy         ;    /* vert. size               */
  54.     PSZ         pszText    ;    /* Window Text              */
  55.     
  56.     /*
  57.      * Shape Window Parameters
  58.      */
  59.  
  60.     HPS         hpsDraw ;       /* Data to Display          */
  61.     ULONG       nRegion ;       /* Number of Rectangles     */
  62.     SHPRGNPTR   aRegion ;       /* Array of Rectangles      */
  63.     
  64. } SHPCTLREC ;
  65.  
  66. /*
  67.  * Drawing Regions represent Window Shape
  68.  */
  69.  
  70. typedef struct _SHPRGNREC {
  71.     SHPCTLPTR   pCtrl ;         /* Link to Parent       */
  72.     HWND        hwnd  ;         /* Drawing Window       */
  73.     RECTL       rect  ;         /* Rectangle of Bitmap  */
  74. } SHPRGNREC ;
  75.  
  76. /*
  77.  * Parse Mask Pattern to Rectangles
  78.  */
  79.  
  80. #define STEP    1024
  81.  
  82. typedef struct _SPAN {
  83.     ULONG   nSize    ;
  84.     ULONG   nUsed    ;
  85.     RECTL   aSpan[1] ;
  86. } SPANREC, *SPANPTR ;
  87.  
  88. static  void    freeSpan(SPANPTR pSpan)
  89. {
  90.     if (pSpan != NULL) {
  91.         free(pSpan) ;
  92.     }
  93. }
  94.  
  95. static  SPANPTR makeSpan(void)
  96. {
  97.     SPANPTR pSpan ;
  98.     int     len   ;
  99.     
  100.     len = sizeof(SPANREC) + sizeof(RECTL) * STEP ;
  101.     
  102.     if ((pSpan = (SPANPTR) malloc(len)) == NULL) {
  103.         return NULL ;
  104.     }
  105.     memset(pSpan, 0, len) ;
  106.     pSpan->nSize = STEP ;
  107.     pSpan->nUsed = 0    ;
  108.     return pSpan ;
  109. }
  110.  
  111. static  SPANPTR moreSpan(SPANPTR pOld)
  112. {
  113.     SPANPTR pNew ;
  114.     int     len  ;
  115.     
  116.     TRACE("moreSpan\n") ;
  117.     
  118.     len = sizeof(SPANREC) + sizeof(RECTL) * (pOld->nSize + STEP) ;
  119.     
  120.     if ((pNew = (SPANPTR) malloc(len)) == NULL) {
  121.         return NULL ;
  122.     }
  123.     memset(pNew, 0, len) ;
  124.     pNew->nSize = pOld->nSize + STEP ;
  125.     pNew->nUsed = pOld->nUsed ;
  126.     memcpy(pNew->aSpan, pOld->aSpan, sizeof(RECTL) * pOld->nUsed) ;
  127.     freeSpan(pOld) ;
  128.     
  129.     return pNew ;
  130. }
  131.  
  132. static  SPANPTR putSpan(SPANPTR pSpan, int y, int x1, int x2)
  133. {
  134.     int     i ;
  135.     PRECTL  p ;
  136.     SPANPTR pNew ;
  137.     
  138.     TRACE("putSpan %d (%d %d)\n", y, x1, x2) ;
  139.     
  140.     /*
  141.      * check if continuous one
  142.      */
  143.      
  144.     for (i = 0 ; i < pSpan->nUsed ; i++) {
  145.         p = &pSpan->aSpan[i] ;
  146.     if (p->yTop == y && p->xLeft == x1 && p->xRight == x2) {
  147.         p->yTop += 1 ;
  148.         return pSpan ;      /* merged */
  149.     }
  150.     }
  151.     
  152.     /*
  153.      * if not enough space, expand
  154.      */
  155.  
  156.     if ((pSpan->nUsed + 1) >= pSpan->nSize) {
  157.         if ((pNew = moreSpan(pSpan)) == NULL) {
  158.         return NULL ;
  159.     }
  160.     pSpan = pNew ;
  161.     }
  162.  
  163.     /*
  164.      * append a rectangle
  165.      */
  166.      
  167.     pSpan->aSpan[pSpan->nUsed].yTop = y + 1 ;
  168.     pSpan->aSpan[pSpan->nUsed].yBottom = y  ;
  169.     pSpan->aSpan[pSpan->nUsed].xLeft   = x1 ;
  170.     pSpan->aSpan[pSpan->nUsed].xRight  = x2 ;
  171.     pSpan->nUsed += 1 ;
  172.     
  173.     return pSpan ;
  174. }
  175.  
  176. #ifdef  SHPDEBUG
  177.  
  178. static  BOOL    ptisin(SPANPTR pSpan, int x, int y)
  179. {
  180.     int     i ;
  181.     
  182.     for (i = 0 ; i < pSpan->nUsed ; i++) {
  183.         if (y >= pSpan->aSpan[i].yTop) {
  184.         continue ;
  185.     }
  186.     if (y < pSpan->aSpan[i].yBottom) {
  187.         continue ;
  188.     }
  189.     if (x < pSpan->aSpan[i].xLeft) {
  190.         continue ;
  191.     }
  192.     if (x >= pSpan->aSpan[i].xRight) {
  193.         continue ;
  194.     }
  195.     return TRUE ;
  196.     }
  197.     return FALSE ;
  198. }
  199.  
  200. static  void    dumpSpan(SPANPTR pSpan)
  201. {
  202.     int     i, maxx, maxy, x, y ;
  203.     
  204.     TRACE("dumpSpan %d\n", pSpan->nUsed) ;
  205.     
  206.     maxx = maxy = 0 ;
  207.     
  208.     for (i = 0 ; i < pSpan->nUsed ; i++) {
  209.         if (pSpan->aSpan[i].yTop > maxy) {
  210.         maxy = pSpan->aSpan[i].yTop ;
  211.     }
  212.     if (pSpan->aSpan[i].xRight > maxx) {
  213.         maxx = pSpan->aSpan[i].xRight ;
  214.     }
  215.     }
  216.     
  217.     for (y = maxy - 1 ; y >= 0 ; y--) {
  218.         printf("%03d : ", y) ;
  219.         for (x = 0 ; x < maxx ; x++) {
  220.         if (ptisin(pSpan, x, y)) {
  221.             printf("#") ;
  222.         } else {
  223.             printf("_") ;
  224.         }
  225.         }
  226.     printf("\n") ;
  227.     }
  228. }
  229.  
  230. #endif  /* SHPDEBUG */
  231.  
  232. static  SPANPTR parseMask(HPS hps, PBITMAPINFOHEADER2 bmih2)
  233. {
  234.     int     blen, hlen  ;
  235.     PUCHAR          buf ;
  236.     PBITMAPINFO2    pbm ;
  237.     SPANPTR pSpan, pNew ;
  238.     int     x, y, k     ;
  239.     LONG    first, color ;
  240.     BOOL    inspan ;
  241.     int     left   ;
  242.     
  243.     TRACE("parseMask\n") ;
  244.  
  245.     hlen = sizeof(BITMAPINFO2) + sizeof(RGB) * 256 ;
  246.     blen = ((bmih2->cBitCount * bmih2->cx + 31) / 32) * bmih2->cPlanes * 4 ;
  247.     
  248.     pbm = (PBITMAPINFO2) malloc(hlen) ;
  249.     buf = (PUCHAR) malloc(blen) ;
  250.     
  251.     if (pbm == NULL || buf == NULL) {
  252.         TRACE("parseMask - failed to alloc %d %d\n", hlen, blen) ;
  253.     if (pbm) free(pbm) ;
  254.         if (buf) free(buf) ;
  255.         return NULL ;
  256.     }
  257.     memcpy(pbm, bmih2, sizeof(BITMAPINFOHEADER2)) ;
  258.  
  259.     if ((pSpan = makeSpan()) == NULL) {
  260.         TRACE("parseMask - failed to make\n") ;
  261.     free(pbm) ;
  262.     free(buf) ;
  263.     return NULL ;
  264.     }
  265.     
  266.     first = - 1 ;
  267.     
  268.     for (y = 0 ; y < bmih2->cy ; y++) {
  269.  
  270.         TRACE("parseMask - scan line %d\n", y) ; fflush(stdout) ;
  271.  
  272.         GpiQueryBitmapBits(hps, y, 1, buf, pbm) ;
  273.  
  274.     for (x = 0, inspan = FALSE ; x < bmih2->cx ; x++) {
  275.         k = x * 3 ;
  276.         color = ((buf[k] << 16) | (buf[k+1] << 8) | buf[k+2]) ;
  277.         if (first < 0) {
  278.             first = color ;
  279.         }
  280.         if (inspan == FALSE && color != first) {
  281.         inspan = TRUE ;
  282.         left = x ;
  283.         } else if (inspan == TRUE && color == first) {
  284.         inspan = FALSE ;
  285.         if ((pNew = putSpan(pSpan, y, left, x)) != NULL) {
  286.             pSpan = pNew ;
  287.         } else {
  288.             TRACE("parseMask - failed to extend\n") ;
  289.                     break ;
  290.         }
  291.         }
  292.     }
  293.     if (inspan == TRUE) {
  294.             if ((pNew = putSpan(pSpan, y, left, x)) != NULL) {
  295.             pSpan = pNew ;
  296.         } else {
  297.             TRACE("parseMask - failed to extend\n") ;
  298.                 break ;
  299.         }
  300.     }
  301.     }
  302.  
  303. #ifdef  SHPDEBUG
  304.     dumpSpan(pSpan) ;
  305. #endif
  306.  
  307.     return pSpan ;
  308. }
  309.  
  310. /*
  311.  * ShpMakeRegion - Make Drawing Region from Mask Image (PS)
  312.  */
  313.  
  314. static  int     ShpMakeRegion(SHPCTLPTR pCtrl, HPS hpsMask)
  315. {
  316.     HAB     hab ;
  317.     HDC     hdc ;
  318.     HPS     hps ;
  319.     SIZEL   siz ;
  320.     HBITMAP hbm ;
  321.     BITMAPINFOHEADER2   bmi ;
  322.     POINTL  apt[3] ;
  323.     SPANPTR     pSpan ;
  324.     SHPRGNPTR   pRegn ;
  325.     int         i     ;
  326.     
  327.     TRACE("ShpMakeRegion\n") ;
  328.     
  329.     hab = WinQueryAnchorBlock(pCtrl->hwndSelf) ;
  330.     
  331.     /*
  332.      * Create Memory DC & HPS
  333.      */
  334.     
  335.     hdc = DevOpenDC(hab, OD_MEMORY, "*", 0, NULL, NULLHANDLE) ;
  336.     siz.cx = siz.cy = 0 ;
  337.     hps = GpiCreatePS(hab, hdc, &siz,
  338.             PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC) ;
  339.  
  340.     /*
  341.      * Create Bitmap and relate to memory PS
  342.      */
  343.      
  344.     memset(&bmi, 0, sizeof(bmi)) ;
  345.  
  346.     bmi.cbFix = sizeof(BITMAPINFOHEADER2) ;
  347.     bmi.cx = pCtrl->cx ;
  348.     bmi.cy = pCtrl->cy ;
  349.     bmi.cPlanes       = 1  ;
  350.     bmi.cBitCount     = 24 ;
  351.     bmi.ulCompression = 0  ;
  352.     bmi.cclrUsed      = 0  ;
  353.     bmi.cclrImportant = 0  ;
  354.     
  355.     hbm = GpiCreateBitmap(hps, &bmi, 0, NULL, NULL) ;
  356.     
  357.     GpiSetBitmap(hps, hbm) ;
  358.     
  359.     /*
  360.      * Copy in Mask Pattern
  361.      */
  362.  
  363.     TRACE("ShpMakeRegion - copyin %d x %d mask pattern\n", bmi.cx, bmi.cy) ;
  364.  
  365.     apt[0].x = 0 ;          /* Target       */
  366.     apt[0].y = 0 ;
  367.     apt[1].x = bmi.cx ;
  368.     apt[1].y = bmi.cy ;
  369.     apt[2].x = 0 ;          /* Source       */
  370.     apt[2].y = 0 ;
  371.  
  372.     if (GpiBitBlt(hps, pCtrl->hpsDraw, 3, apt, ROP_SRCCOPY, 0) == GPI_ERROR) {
  373.         TRACE("MakeRect - BitBlt Failed %08x, hdc %08x, hps %08x, hbm %08x\n",
  374.                 WinGetLastError(hab), hdc, hps, hbm) ;
  375.     }
  376.     
  377.     /*
  378.      * Parse Mask Pattern
  379.      */
  380.     
  381.     if ((pSpan = parseMask(hps, &bmi)) != NULL) {
  382.         if ((pRegn = (SHPRGNPTR) malloc(sizeof(SHPRGNREC) * pSpan->nUsed)) == NULL) {
  383.         TRACE("ShpMakeRegion - failed to alloc\n") ;
  384.     } else {
  385.         pCtrl->nRegion = pSpan->nUsed ;
  386.         pCtrl->aRegion = pRegn        ;
  387.         for (i = 0 ; i < pSpan->nUsed ; i++) {
  388.         pRegn[i].pCtrl    = pCtrl      ;
  389.         pRegn[i].hwnd = NULLHANDLE ;
  390.         pRegn[i].rect.xLeft   = pSpan->aSpan[i].xLeft   ;
  391.         pRegn[i].rect.xRight  = pSpan->aSpan[i].xRight  ;
  392.         pRegn[i].rect.yTop    = pSpan->aSpan[i].yTop    ;
  393.         pRegn[i].rect.yBottom = pSpan->aSpan[i].yBottom ;
  394.         }
  395.         }            
  396.         freeSpan(pSpan) ;
  397.     }
  398.  
  399.     /*
  400.      * dispose local resources
  401.      */
  402.  
  403.     GpiDeleteBitmap(hbm) ;
  404.     GpiDestroyPS(hps) ;
  405.     DevCloseDC(hdc) ;
  406.     
  407.     return 0 ;
  408. }
  409.  
  410. /*
  411.  * regnDraw - draw a region
  412.  */
  413.  
  414. static  void    regnDraw(HPS hps, SHPRGNPTR pRgn)
  415. {
  416.     POINTL      apt[3] ;
  417.  
  418.     apt[0].x = 0 ;
  419.     apt[0].y = 0 ;
  420.     apt[1].x = (pRgn->rect.xRight - pRgn->rect.xLeft) ;
  421.     apt[1].y = (pRgn->rect.yTop - pRgn->rect.yBottom) ;
  422.     apt[2].x = pRgn->rect.xLeft   ;
  423.     apt[2].y = pRgn->rect.yBottom ;
  424.     GpiBitBlt(hps, pRgn->pCtrl->hpsDraw, 3, apt, ROP_SRCCOPY, 0) ;
  425. }
  426.  
  427. /*
  428.  * Window Procedure for Drawing Regions
  429.  */
  430.  
  431. static MRESULT EXPENTRY regnProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  432. {
  433.     SHPRGNPTR   pRgn ;
  434.     HPS         hps  ;
  435.     
  436.     pRgn = (SHPRGNPTR) WinQueryWindowPtr(hwnd, 0) ;
  437.  
  438.     switch (msg) {
  439.     
  440.     case WM_CREATE :
  441.         TRACE("WM_CREATE\n") ;
  442.         pRgn = (SHPRGNPTR) PVOIDFROMMP(mp1) ;
  443.     WinSetWindowPtr(hwnd, 0, (PVOID) pRgn) ;
  444.     return (MRESULT) FALSE ;
  445.     
  446.     case WM_PAINT :
  447.         TRACE("WM_PAINT (%d %d) (%d %d)\n", pRgn->rect.yBottom, pRgn->rect.xLeft, pRgn->rect.yTop, pRgn->rect.xRight) ;
  448.         hps = WinBeginPaint(hwnd, NULLHANDLE, NULL) ;
  449.     regnDraw(hps, pRgn) ;
  450.         WinEndPaint(hps)   ;
  451.     return (MRESULT) 0 ;
  452.  
  453.     case WM_MOUSEMOVE     :
  454.     case WM_BUTTON1DOWN   :
  455.     case WM_BUTTON1UP     :
  456.     case WM_BUTTON1CLICK  :
  457.     case WM_BUTTON1DBLCLK :
  458.     case WM_BUTTON2DOWN   :
  459.     case WM_BUTTON2UP     :
  460.     case WM_BUTTON2CLICK  :
  461.     case WM_BUTTON2DBLCLK :
  462.     case WM_BUTTON3DOWN   :
  463.     case WM_BUTTON3UP     :
  464.     case WM_BUTTON3CLICK  :
  465.     case WM_BUTTON3DBLCLK :
  466.     case WM_CHAR          :
  467.     case WM_VIOCHAR       :
  468.     case WM_BEGINDRAG     :
  469.     case WM_ENDDRAG       :
  470.     case WM_SINGLESELECT  :
  471.     case WM_OPEN          :
  472.     case WM_CONTEXTMENU   :
  473.     case WM_CONTEXTHELP   :
  474.     case WM_TEXTEDIT      :
  475.     case WM_BEGINSELECT   :
  476.     case WM_ENDSELECT     :
  477.         return WinSendMsg(pRgn->pCtrl->hwndSelf, msg, mp1, mp2) ;
  478.     }
  479.     return WinDefWindowProc(hwnd, msg, mp1, mp2) ;
  480. }
  481.  
  482. /*
  483.  * ShpOpenRegion - create window for each region
  484.  */
  485.  
  486. static  BOOL    ShapeRegisteredRegion = FALSE ;
  487.  
  488. static  int     ShpOpenRegion(SHPCTLPTR pCtrl)
  489. {
  490.     int         i    ;
  491.     SHPRGNPTR   pRgn ;
  492.     ULONG       flStyle ;
  493.  
  494.     TRACE("ShpOpenRegion %d regions\n", pCtrl->nRegion) ;
  495.     
  496.     if (pCtrl->nRegion == 0 || pCtrl->aRegion == NULL) {
  497.         TRACE("ShpOpenRegion - no region to open\n") ;
  498.     return -1 ;
  499.     }
  500.    
  501.     if (ShapeRegisteredRegion == FALSE) {
  502.         WinRegisterClass(WinQueryAnchorBlock(pCtrl->hwndSelf),
  503.                         "ShapeWinRegion", regnProc, CS_PARENTCLIP | CS_CLIPSIBLINGS | CS_SYNCPAINT, sizeof(PVOID)) ;
  504.         ShapeRegisteredRegion = TRUE ;
  505.     }
  506.  
  507.     flStyle = 0 ;
  508.                         
  509.     
  510.     for (i = 0, pRgn = pCtrl->aRegion ; i < pCtrl->nRegion ; i++, pRgn++) {
  511.         pRgn->hwnd = WinCreateWindow(
  512.                 HWND_DESKTOP,           /* Parent Window    */
  513.                 "ShapeWinRegion",       /* Window Class     */
  514.             NULL,                   /* Window Text      */
  515.             flStyle,                /* Window Style     */
  516.         (pCtrl->x + pRgn->rect.xLeft),
  517.         (pCtrl->y + pRgn->rect.yBottom),
  518.                 (pRgn->rect.xRight - pRgn->rect.xLeft),
  519.         (pRgn->rect.yTop - pRgn->rect.yBottom),
  520.             pCtrl->hwndOwner,       /* Owner Window     */
  521.             HWND_TOP,               /* Z-Order          */
  522.             i,                      /* Window ID        */
  523.             pRgn,                   /* Control Data     */
  524.             NULL) ;                 /* Pres. Param.     */
  525.             
  526.     }
  527.     return 0 ;
  528. }
  529.  
  530. /*
  531.  * ShpFreeRegion - Dispose Region Window and Related Resources
  532.  */
  533.  
  534. static  int     ShpFreeRegion(SHPCTLPTR pCtrl)
  535. {
  536.     int         i    ;
  537.     SHPRGNPTR   pRgn ;
  538.  
  539.     for (i = 0, pRgn = pCtrl->aRegion ; i < pCtrl->nRegion ; i++, pRgn++) {
  540.         WinDestroyWindow(pRgn->hwnd) ;
  541.     }
  542.     free(pCtrl->aRegion) ;
  543.  
  544.     return 0 ;
  545. }
  546.  
  547. /*
  548.  * ShpAdjustRegion - Controls Region's Position, Visibility, etc.
  549.  */
  550.  
  551. static  int     ShpAdjustRegion(SHPCTLPTR pCtrl, PSWP pSwp)
  552. {
  553.     int         i    ;
  554.     SHPRGNPTR   pRgn ;
  555.     ULONG       fl   ;
  556.     HPS         hps  ;
  557.  
  558.     PSWP pswpArray ;
  559.  
  560.     TRACE("ShpAdjustRegion - %d, %08x\n", pCtrl->nRegion, pSwp->fl) ;
  561.  
  562.     if (pCtrl->nRegion == 0 || pCtrl->aRegion == NULL) {
  563.         TRACE("ShpDrawRegion - no region to open\n") ;
  564.     return -1 ;
  565.     }
  566.  
  567.     if ((fl = pSwp->fl) & SWP_MOVE) {
  568.         pCtrl->x = pSwp->x ;
  569.     pCtrl->y = pSwp->y ;
  570.     }
  571.  
  572.     pswpArray = (PSWP) malloc(sizeof(SWP) * pCtrl->nRegion) ;
  573.  
  574.     for (i = 0, pRgn = pCtrl->aRegion ; i < pCtrl->nRegion ; i++, pRgn++) {
  575.         pswpArray[i].fl = fl ;
  576.         pswpArray[i].cy = (pRgn->rect.yTop - pRgn->rect.yBottom) ;
  577.         pswpArray[i].cx = (pRgn->rect.xRight - pRgn->rect.xLeft) ;
  578.         pswpArray[i].y = (pCtrl->y + pRgn->rect.yBottom) ;
  579.         pswpArray[i].x = (pCtrl->x + pRgn->rect.xLeft) ;
  580.         pswpArray[i].hwndInsertBehind = pSwp->hwndInsertBehind ;
  581.         pswpArray[i].hwnd = pRgn->hwnd ;
  582.     }
  583.     WinSetMultWindowPos(WinQueryAnchorBlock(pCtrl->hwndSelf),
  584.                                     &pswpArray[0], pCtrl->nRegion) ;
  585.     free((void*) pswpArray) ;
  586.  
  587.     for (i = 0, pRgn = pCtrl->aRegion ; i < pCtrl->nRegion ; i++, pRgn++) {
  588.         if (fl & (SWP_MOVE | SWP_ZORDER)) {
  589.             WinInvalidateRect(pRgn->hwnd, NULL, FALSE) ;
  590.         }
  591.     }
  592.     return 0 ;
  593. }
  594.  
  595. /*
  596.  * ShpUpdatetRegion - update drawing image
  597.  */
  598.  
  599. static  int     ShpUpdateRegion(SHPCTLPTR pCtrl, PRECTL pRect)
  600. {
  601.     RECTL       rect, intern ;
  602.     int         i    ;
  603.     SHPRGNPTR   pRgn ;
  604.     HAB         hab  ;
  605.     HPS         hps  ;
  606.     
  607.     TRACE("ShpUpdateRegion\n") ;
  608.  
  609.     hab = WinQueryAnchorBlock(pCtrl->hwndSelf) ;
  610.     
  611.     if (pRect == NULL) {
  612.         rect.xLeft   = 0        ;
  613.     rect.yBottom = 0        ;
  614.     rect.xRight = pCtrl->cx ;
  615.     rect.yTop   = pCtrl->cy ;
  616.     pRect = &rect ;
  617.     }
  618.     for (i = 0, pRgn = pCtrl->aRegion ; i < pCtrl->nRegion ; i++, pRgn++) {
  619.         if (WinIntersectRect(hab, &intern, pRect, &pRgn->rect) == FALSE) {
  620.         continue ;
  621.         } else {
  622.             WinInvalidateRect(pRgn->hwnd, NULL, FALSE) ;
  623.         }
  624.     }
  625.     return 0 ;
  626. }
  627.  
  628. /*
  629.  * ShpInit - Initialize Widget's Control Block
  630.  */
  631.  
  632. static  SHPCTLPTR   ShpInit(HWND hwnd, PCREATESTRUCT pWin, PSHAPEWIN pData)
  633. {
  634.     SHPCTLPTR   pCtrl ;
  635.     
  636.     if (pData->hpsDraw == NULLHANDLE || pData->hpsMask == NULLHANDLE) {
  637.         return NULL ;
  638.     }
  639.     if ((pCtrl = (SHPCTLPTR) malloc(sizeof(SHPCTLREC))) == NULL) {
  640.         return NULL ;
  641.     }
  642.  
  643.     /*
  644.      * Setup Common Window Parameters
  645.      */
  646.  
  647.     pCtrl->hwndSelf   = hwnd ;
  648.     pCtrl->hwndParent = pWin->hwndParent ;
  649.     pCtrl->hwndOwner  = pWin->hwndOwner  ;
  650.     pCtrl->id         = pWin->id ;
  651.     pCtrl->x          = pWin->x  ;
  652.     pCtrl->y          = pWin->y  ;
  653.     pCtrl->cx         = pWin->cx ;
  654.     pCtrl->cy         = pWin->cy ;
  655.     
  656.     /*
  657.      * Setup Image Window 's Control Data
  658.      */
  659.  
  660.     pCtrl->cx = pData->cx ;
  661.     pCtrl->cy = pData->cy ;
  662.     pCtrl->hpsDraw = pData->hpsDraw ;
  663.  
  664.     ShpMakeRegion(pCtrl, pData->hpsMask) ;
  665.     ShpOpenRegion(pCtrl) ;
  666.  
  667.     return pCtrl ;
  668. }
  669.  
  670. /*
  671.  * ShpTerm - Dispose Widget's Control Block
  672.  */
  673.  
  674. static  void    ShpTerm(SHPCTLPTR pCtrl)
  675. {
  676.     if (pCtrl == NULL) {
  677.         return ;
  678.     }
  679.     ShpFreeRegion(pCtrl) ;
  680.     free(pCtrl) ;
  681. }
  682.  
  683. /*
  684.  * Window Procedure
  685.  */
  686.  
  687. MRESULT EXPENTRY    ShapeWinProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  688. {
  689.     SHPCTLPTR   pCtrl ;
  690.     HPS         hps   ;
  691.     PSWP        pswp  ;
  692.     SHORT       sx, sy ;
  693.     
  694.     pCtrl = (SHPCTLPTR) WinQueryWindowPtr(hwnd, 0) ;
  695.     
  696.     switch (msg) {
  697.     
  698.     case WM_CREATE  :
  699.         TRACE("WM_CREATE\n") ;
  700.         pCtrl = ShpInit(hwnd, 
  701.             (PCREATESTRUCT) PVOIDFROMMP(mp2), (PSHAPEWIN) PVOIDFROMMP(mp1)) ;
  702.         if (pCtrl == NULL) {
  703.         return (MRESULT) TRUE ;
  704.     }
  705.     WinSetWindowPtr(hwnd, 0, (PVOID) pCtrl) ;
  706.     return (MRESULT) FALSE ;
  707.     
  708.     case WM_DESTROY :
  709.         TRACE("WM_DESTORY\n") ;
  710.         ShpTerm(pCtrl) ;
  711.     return (MRESULT) 0 ;
  712.  
  713.     case WM_ADJUSTWINDOWPOS :
  714.         TRACE("WM_ADJUSTWINDOWPOS\n") ;
  715.     pswp = (PSWP) PVOIDFROMMP(mp1) ;
  716.     DUMPSWP(pswp) ;
  717.     pswp->cx = pCtrl->cx ;          /* size is fixed        */
  718.     pswp->cy = pCtrl->cy ;
  719.     ShpAdjustRegion(pCtrl, pswp) ;  /* adjust sub-windows   */
  720.     pswp->fl &= ~SWP_SHOW ;         /* not show itself      */
  721.     return (MRESULT) 0 ;
  722.     
  723.     case SHAPEWIN_MSG_UPDATE :
  724.         ShpUpdateRegion(pCtrl, (PRECTL) PVOIDFROMMP(mp1)) ;
  725.     return (MRESULT) 0 ;
  726.  
  727.     case WM_QUERYDLGCODE :
  728.         TRACE("WM_QUERYDLGCODE\n") ;
  729.     return (MRESULT) DLGC_STATIC ;
  730.  
  731.     case WM_PAINT :
  732.         TRACE("WM_PAINT\n") ;
  733.         hps = WinBeginPaint(hwnd, NULLHANDLE, NULL) ;
  734.     WinEndPaint(hps) ;
  735.     return (MRESULT) 0 ;
  736.  
  737.     case WM_MOUSEMOVE     :
  738.     case WM_BUTTON1DOWN   :
  739.     case WM_BUTTON1UP     :
  740.     case WM_BUTTON1CLICK  :
  741.     case WM_BUTTON1DBLCLK :
  742.     case WM_BUTTON2DOWN   :
  743.     case WM_BUTTON2UP     :
  744.     case WM_BUTTON2CLICK  :
  745.     case WM_BUTTON2DBLCLK :
  746.     case WM_BUTTON3DOWN   :
  747.     case WM_BUTTON3UP     :
  748.     case WM_BUTTON3CLICK  :
  749.     case WM_BUTTON3DBLCLK :
  750.     case WM_CHAR          :
  751.     case WM_VIOCHAR       :
  752.     case WM_BEGINDRAG     :
  753.     case WM_ENDDRAG       :
  754.     case WM_SINGLESELECT  :
  755.     case WM_OPEN          :
  756.     case WM_CONTEXTMENU   :
  757.     case WM_CONTEXTHELP   :
  758.     case WM_TEXTEDIT      :
  759.     case WM_BEGINSELECT   :
  760.     case WM_ENDSELECT     :
  761.         return WinSendMsg(pCtrl->hwndOwner, msg, mp1, mp2) ;
  762.  
  763.     }
  764.     return WinDefWindowProc(hwnd, msg, mp1, mp2) ;
  765. }
  766.