[YAROTOWS] Reintegrate the branch. For a brighter future.
[reactos.git] / reactos / subsystems / win32 / win32k / objects / pen.c
index a8c0eb4..5884945 100644 (file)
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * $Id$
  */
 
-#include <w32k.h>
+#include <win32k.h>
 
 #define NDEBUG
 #include <debug.h>
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
-PGDIBRUSHOBJ
+PBRUSH
 FASTCALL
-PENOBJ_LockPen(HGDIOBJ hBMObj)
+PEN_LockPen(HGDIOBJ hBMObj)
 {
    if (GDI_HANDLE_GET_TYPE(hBMObj) == GDI_OBJECT_TYPE_EXTPEN)
       return GDIOBJ_LockObj( hBMObj, GDI_OBJECT_TYPE_EXTPEN);
@@ -37,7 +37,17 @@ PENOBJ_LockPen(HGDIOBJ hBMObj)
       return GDIOBJ_LockObj( hBMObj, GDI_OBJECT_TYPE_PEN);
 }
 
-HPEN STDCALL
+PBRUSH
+FASTCALL
+PEN_ShareLockPen(HGDIOBJ hBMObj)
+{
+   if (GDI_HANDLE_GET_TYPE(hBMObj) == GDI_OBJECT_TYPE_EXTPEN)
+      return GDIOBJ_ShareLockObj( hBMObj, GDI_OBJECT_TYPE_EXTPEN);
+   else
+      return GDIOBJ_ShareLockObj( hBMObj, GDI_OBJECT_TYPE_PEN);
+}
+
+HPEN APIENTRY
 IntGdiExtCreatePen(
    DWORD dwPenStyle,
    DWORD dwWidth,
@@ -47,51 +57,57 @@ IntGdiExtCreatePen(
    IN ULONG_PTR ulHatch,
    DWORD dwStyleCount,
    PULONG pStyle,
-   IN ULONG cjDIB,     // FIXME! We are shipping this too!
+   IN ULONG cjDIB,
    IN BOOL bOldStylePen,
    IN OPTIONAL HBRUSH hbrush)
 {
    HPEN hPen;
-   PGDIBRUSHOBJ PenObject;
-   static const BYTE PatternAlternate[] = {0x55, 0x55, 0x55};
-   static const BYTE PatternDash[] = {0xFF, 0xFF, 0xC0};
-   static const BYTE PatternDot[] = {0xE3, 0x8E, 0x38};
-   static const BYTE PatternDashDot[] = {0xFF, 0x81, 0xC0};
-   static const BYTE PatternDashDotDot[] = {0xFF, 0x8E, 0x38};
+   PBRUSH pbrushPen;
+   static const BYTE PatternAlternate[] = {0x55, 0x55, 0x55, 0};
+   static const BYTE PatternDash[] = {0xFF, 0xFF, 0xC0, 0};
+   static const BYTE PatternDot[] = {0xE3, 0x8E, 0x38, 0};
+   static const BYTE PatternDashDot[] = {0xFF, 0x81, 0xC0, 0};
+   static const BYTE PatternDashDotDot[] = {0xFF, 0x8E, 0x38, 0};
 
    dwWidth = abs(dwWidth);
 
+   if ( (dwPenStyle & PS_STYLE_MASK) == PS_NULL)
+   {
+      return StockObjects[NULL_PEN];
+   }
+
    if (bOldStylePen)
    {
-      PenObject = PENOBJ_AllocPenWithHandle();
+      pbrushPen = PEN_AllocPenWithHandle();
    }
    else
    {
-      PenObject = PENOBJ_AllocExtPenWithHandle();
+      pbrushPen = PEN_AllocExtPenWithHandle();
    }
 
-   if (!PenObject)
+   if (!pbrushPen)
    {
       SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
       DPRINT("Can't allocate pen\n");
       return 0;
    }
-   hPen = PenObject->BaseObject.hHmgr;
+   hPen = pbrushPen->BaseObject.hHmgr;
 
    // If nWidth is zero, the pen is a single pixel wide, regardless of the current transformation.
-   if ((bOldStylePen) && (!dwWidth)) dwWidth = 1;
-
-   PenObject->ptPenWidth.x = dwWidth;
-   PenObject->ptPenWidth.y = 0;
-   PenObject->ulPenStyle = dwPenStyle;
-   PenObject->BrushAttr.lbColor = ulColor;
-   PenObject->ulStyle = ulBrushStyle;
+   if ((bOldStylePen) && (!dwWidth) && (dwPenStyle & PS_STYLE_MASK) != PS_SOLID)
+      dwWidth = 1;
+
+   pbrushPen->ptPenWidth.x = dwWidth;
+   pbrushPen->ptPenWidth.y = 0;
+   pbrushPen->ulPenStyle = dwPenStyle;
+   pbrushPen->BrushAttr.lbColor = ulColor;
+   pbrushPen->ulStyle = ulBrushStyle;
    // FIXME: copy the bitmap first ?
-   PenObject->hbmClient = (HANDLE)ulClientHatch;
-   PenObject->dwStyleCount = dwStyleCount;
-   PenObject->pStyle = pStyle;
+   pbrushPen->hbmClient = (HANDLE)ulClientHatch;
+   pbrushPen->dwStyleCount = dwStyleCount;
+   pbrushPen->pStyle = pStyle;
 
-   PenObject->flAttrs = bOldStylePen? GDIBRUSH_IS_OLDSTYLEPEN : GDIBRUSH_IS_PEN;
+   pbrushPen->flAttrs = bOldStylePen? GDIBRUSH_IS_OLDSTYLEPEN : GDIBRUSH_IS_PEN;
 
    // If dwPenStyle is PS_COSMETIC, the width must be set to 1.
    if ( !(bOldStylePen) && ((dwPenStyle & PS_TYPE_MASK) == PS_COSMETIC) && ( dwWidth != 1) )
@@ -100,45 +116,40 @@ IntGdiExtCreatePen(
    switch (dwPenStyle & PS_STYLE_MASK)
    {
       case PS_NULL:
-         PenObject->flAttrs |= GDIBRUSH_IS_NULL;
+         pbrushPen->flAttrs |= GDIBRUSH_IS_NULL;
          break;
 
       case PS_SOLID:
-         PenObject->flAttrs |= GDIBRUSH_IS_SOLID;
+         pbrushPen->flAttrs |= GDIBRUSH_IS_SOLID;
          break;
 
       case PS_ALTERNATE:
-         /* PS_ALTERNATE is applicable only for cosmetic pens */
-         if ((dwPenStyle & PS_TYPE_MASK) == PS_GEOMETRIC) goto ExitCleanup;
-         PenObject->flAttrs |= GDIBRUSH_IS_BITMAP;
-         PenObject->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternAlternate);
+         pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
+         pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternAlternate);
          break;
 
       case PS_DOT:
-         PenObject->flAttrs |= GDIBRUSH_IS_BITMAP;
-         PenObject->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDot);
+         pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
+         pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDot);
          break;
 
       case PS_DASH:
-         PenObject->flAttrs |= GDIBRUSH_IS_BITMAP;
-         PenObject->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDash);
+         pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
+         pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDash);
          break;
 
       case PS_DASHDOT:
-         PenObject->flAttrs |= GDIBRUSH_IS_BITMAP;
-         PenObject->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDot);
+         pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
+         pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDot);
          break;
 
       case PS_DASHDOTDOT:
-         PenObject->flAttrs |= GDIBRUSH_IS_BITMAP;
-         PenObject->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDotDot);
+         pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
+         pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDotDot);
          break;
 
       case PS_INSIDEFRAME:
-         /* FIXME: does it need some additional work? */
-         /* PS_INSIDEFRAME is applicable only for geometric pens */
-         if ((dwPenStyle & PS_TYPE_MASK) == PS_COSMETIC) goto ExitCleanup;
-         PenObject->flAttrs |= (GDIBRUSH_IS_SOLID|GDIBRUSH_IS_INSIDEFRAME);
+         pbrushPen->flAttrs |= (GDIBRUSH_IS_SOLID|GDIBRUSH_IS_INSIDEFRAME);
          break;
 
       case PS_USERSTYLE:
@@ -146,7 +157,7 @@ IntGdiExtCreatePen(
          {
             /* FIXME: PS_USERSTYLE workaround */
             DPRINT1("PS_COSMETIC | PS_USERSTYLE not handled\n");
-            PenObject->flAttrs |= GDIBRUSH_IS_SOLID;
+            pbrushPen->flAttrs |= GDIBRUSH_IS_SOLID;
             break;
          }
          else
@@ -166,80 +177,97 @@ IntGdiExtCreatePen(
             }
          }
          /* FIXME: what style here? */
-         PenObject->flAttrs |= 0;
+         pbrushPen->flAttrs |= 0;
          break;
 
       default:
          DPRINT1("IntGdiExtCreatePen unknown penstyle %x\n", dwPenStyle);
    }
-   PENOBJ_UnlockPen(PenObject);
+   PEN_UnlockPen(pbrushPen);
    return hPen;
 
 ExitCleanup:
    SetLastWin32Error(ERROR_INVALID_PARAMETER);
-   PenObject->pStyle = NULL;
-   PENOBJ_UnlockPen(PenObject);
+   pbrushPen->pStyle = NULL;
+   PEN_UnlockPen(pbrushPen);
    if (bOldStylePen)
-      PENOBJ_FreePenByHandle(hPen);
+      PEN_FreePenByHandle(hPen);
    else
-      PENOBJ_FreeExtPenByHandle(hPen);
+      PEN_FreeExtPenByHandle(hPen);
    return NULL;
 }
 
 VOID FASTCALL
 IntGdiSetSolidPenColor(HPEN hPen, COLORREF Color)
 {
-  PGDIBRUSHOBJ PenObject;
+  PBRUSH pbrushPen;
 
-  PenObject = PENOBJ_LockPen(hPen);
-  if (PenObject)
+  pbrushPen = PEN_LockPen(hPen);
+  if (pbrushPen)
   {
-    if (PenObject->flAttrs & GDIBRUSH_IS_SOLID)
+    if (pbrushPen->flAttrs & GDIBRUSH_IS_SOLID)
     {
-      PenObject->BrushAttr.lbColor = Color & 0xFFFFFF;
+      pbrushPen->BrushAttr.lbColor = Color & 0xFFFFFF;
     }
-    PENOBJ_UnlockPen(PenObject);
+    PEN_UnlockPen(pbrushPen);
   }
 }
 
-INT STDCALL
-PEN_GetObject(PGDIBRUSHOBJ pPenObject, INT cbCount, PLOGPEN pBuffer)
+INT APIENTRY
+PEN_GetObject(PBRUSH pbrushPen, INT cbCount, PLOGPEN pBuffer)
 {
    PLOGPEN pLogPen;
    PEXTLOGPEN pExtLogPen;
    INT cbRetCount;
 
-   if (pPenObject->flAttrs & GDIBRUSH_IS_OLDSTYLEPEN)
+   if (pbrushPen->flAttrs & GDIBRUSH_IS_OLDSTYLEPEN)
    {
       cbRetCount = sizeof(LOGPEN);
       if (pBuffer)
       {
+
          if (cbCount < cbRetCount) return 0;
-         pLogPen = (PLOGPEN)pBuffer;
-         pLogPen->lopnWidth = pPenObject->ptPenWidth;
-         pLogPen->lopnStyle = pPenObject->ulPenStyle;
-         pLogPen->lopnColor = pPenObject->BrushAttr.lbColor;
+
+         if ( (pbrushPen->ulPenStyle & PS_STYLE_MASK) == PS_NULL && 
+               cbCount == sizeof(EXTLOGPEN))
+         {
+            pExtLogPen = (PEXTLOGPEN)pBuffer; 
+            pExtLogPen->elpPenStyle = pbrushPen->ulPenStyle;
+            pExtLogPen->elpWidth = 0;
+            pExtLogPen->elpBrushStyle = pbrushPen->ulStyle;
+            pExtLogPen->elpColor = pbrushPen->BrushAttr.lbColor;
+            pExtLogPen->elpHatch = 0;
+            pExtLogPen->elpNumEntries = 0;
+            cbRetCount = sizeof(EXTLOGPEN);
+         }
+         else
+         {
+            pLogPen = (PLOGPEN)pBuffer;
+            pLogPen->lopnWidth = pbrushPen->ptPenWidth;
+            pLogPen->lopnStyle = pbrushPen->ulPenStyle;
+            pLogPen->lopnColor = pbrushPen->BrushAttr.lbColor;
+         }
       }
    }
    else
    {
       // FIXME: Can we trust in dwStyleCount being <= 16?
-      cbRetCount = sizeof(EXTLOGPEN) - sizeof(DWORD) + pPenObject->dwStyleCount * sizeof(DWORD);
+      cbRetCount = sizeof(EXTLOGPEN) - sizeof(DWORD) + pbrushPen->dwStyleCount * sizeof(DWORD);
       if (pBuffer)
       {
          INT i;
 
          if (cbCount < cbRetCount) return 0;
          pExtLogPen = (PEXTLOGPEN)pBuffer;
-         pExtLogPen->elpPenStyle = pPenObject->ulPenStyle;
-         pExtLogPen->elpWidth = pPenObject->ptPenWidth.x;
-         pExtLogPen->elpBrushStyle = pPenObject->ulStyle;
-         pExtLogPen->elpColor = pPenObject->BrushAttr.lbColor;
-         pExtLogPen->elpHatch = (ULONG_PTR)pPenObject->hbmClient;
-         pExtLogPen->elpNumEntries = pPenObject->dwStyleCount;
+         pExtLogPen->elpPenStyle = pbrushPen->ulPenStyle;
+         pExtLogPen->elpWidth = pbrushPen->ptPenWidth.x;
+         pExtLogPen->elpBrushStyle = pbrushPen->ulStyle;
+         pExtLogPen->elpColor = pbrushPen->BrushAttr.lbColor;
+         pExtLogPen->elpHatch = (ULONG_PTR)pbrushPen->hbmClient;
+         pExtLogPen->elpNumEntries = pbrushPen->dwStyleCount;
          for (i = 0; i < pExtLogPen->elpNumEntries; i++)
          {
-            pExtLogPen->elpStyleEntry[i] = pPenObject->pStyle[i];
+            pExtLogPen->elpStyleEntry[i] = pbrushPen->pStyle[i];
          }
       }
    }
@@ -248,52 +276,9 @@ PEN_GetObject(PGDIBRUSHOBJ pPenObject, INT cbCount, PLOGPEN pBuffer)
 }
 
 
-HPEN
-FASTCALL
-IntGdiSelectPen(
-    PDC pDC,
-    HPEN hPen)
-{
-    PDC_ATTR pDc_Attr;
-    HPEN hOrgPen = NULL;
-    PGDIBRUSHOBJ pPen;
-    XLATEOBJ *XlateObj;
-    BOOLEAN bFailed;
-
-    pDc_Attr = pDC->pDc_Attr;
-    if(!pDc_Attr) pDc_Attr = &pDC->Dc_Attr;
-
-    pPen = PENOBJ_LockPen(hPen);
-    if (pPen == NULL)
-    {
-        return NULL;
-    }
-
-    XlateObj = IntGdiCreateBrushXlate(pDC, pPen, &bFailed);
-    PENOBJ_UnlockPen(pPen);
-    if (bFailed)
-    {
-        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
-        return NULL;
-    }
-
-    hOrgPen = pDc_Attr->hpen;
-    pDc_Attr->hpen = hPen;
-
-    if (pDC->XlatePen != NULL)
-    {
-        EngDeleteXlate(pDC->XlatePen);
-    }
-    pDc_Attr->ulDirty_ &= ~DC_PEN_DIRTY;
-
-    pDC->XlatePen = XlateObj;
-
-    return hOrgPen;
-}
-
 /* PUBLIC FUNCTIONS ***********************************************************/
 
-HPEN STDCALL
+HPEN APIENTRY
 NtGdiCreatePen(
    INT PenStyle,
    INT Width,
@@ -316,10 +301,10 @@ NtGdiCreatePen(
                              NULL,
                              0,
                              TRUE,
-                             0);
+                             hbr);
 }
 
-HPEN STDCALL
+HPEN APIENTRY
 NtGdiExtCreatePen(
    DWORD dwPenStyle,
    DWORD ulWidth,
@@ -352,18 +337,18 @@ NtGdiExtCreatePen(
          SetLastNtError(ERROR_NOT_ENOUGH_MEMORY);
          return 0;
       }
-      _SEH_TRY
+      _SEH2_TRY
       {
          ProbeForRead(pUnsafeStyle, dwStyleCount * sizeof(DWORD), 1);
          RtlCopyMemory(pSafeStyle,
                        pUnsafeStyle,
                        dwStyleCount * sizeof(DWORD));
       }
-      _SEH_HANDLE
+      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
       {
-         Status = _SEH_GetExceptionCode();
+         Status = _SEH2_GetExceptionCode();
       }
-      _SEH_END
+      _SEH2_END
       if(!NT_SUCCESS(Status))
       {
          SetLastNtError(Status);
@@ -372,17 +357,37 @@ NtGdiExtCreatePen(
       }
    }
 
+   if (ulBrushStyle == BS_PATTERN)
+   {
+      _SEH2_TRY
+      {
+         ProbeForRead((PVOID)ulHatch, cjDIB, 1);
+      }
+      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+      {
+         Status = _SEH2_GetExceptionCode();
+      }
+      _SEH2_END
+      if(!NT_SUCCESS(Status))
+      {
+         SetLastNtError(Status);
+         if (pSafeStyle) ExFreePoolWithTag(pSafeStyle, TAG_PENSTYLES);
+         return 0;
+      }
+   }
+
    hPen = IntGdiExtCreatePen(dwPenStyle,
-                             ulWidth,
-                             ulBrushStyle,
-                             ulColor,
-                             ulClientHatch,
-                             ulHatch,
-                             dwStyleCount,
+                                ulWidth,
+                           ulBrushStyle,
+                                ulColor,
+                          ulClientHatch,
+                                ulHatch,
+                           dwStyleCount,
                              pSafeStyle,
-                             cjDIB,
-                             bOldStylePen,
-                             hBrush);
+                                  cjDIB,
+                           bOldStylePen,
+                                 hBrush);
+
    if (!hPen && pSafeStyle)
    {
       ExFreePoolWithTag(pSafeStyle, TAG_PENSTYLES);
@@ -390,31 +395,6 @@ NtGdiExtCreatePen(
    return hPen;
 }
 
- /*
- * @implemented
- */
-HPEN
-APIENTRY
-NtGdiSelectPen(
-    IN HDC hDC,
-    IN HPEN hPen)
-{
-    PDC pDC;
-    HPEN hOrgPen;
-
-    if (hDC == NULL || hPen == NULL) return NULL;
-
-    pDC = DC_LockDc(hDC);
-    if (!pDC)
-    {
-        return NULL;
-    }
 
-    hOrgPen = IntGdiSelectPen(pDC,hPen);
-
-    DC_UnlockDc(pDC);
-
-    return hOrgPen;
-}
 
 /* EOF */