home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / shapewin.zip / shapewin.c.suwa < prev    next >
Text File  |  1998-11-18  |  20KB  |  771 lines

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