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

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