home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / shapw102.zip / shpwn102.zip / shapewin.c < prev    next >
C/C++ Source or Header  |  1999-03-05  |  20KB  |  773 lines

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