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