NtGdiExtTextOut (ExtTextOut in user-mode) should now obey at least the right clipping edge with ETO_CLIPPED.
Modified: trunk/reactos/subsys/win32k/objects/text.c

Modified: trunk/reactos/subsys/win32k/objects/text.c
--- trunk/reactos/subsys/win32k/objects/text.c	2005-01-25 19:11:22 UTC (rev 13274)
+++ trunk/reactos/subsys/win32k/objects/text.c	2005-01-25 20:53:37 UTC (rev 13275)
@@ -1493,7 +1493,7 @@
    LONGLONG TextLeft, RealXStart;
    ULONG TextTop, pitch, previous, BackgroundLeft;
    FT_Bool use_kerning;
-   RECTL DestRect, MaskRect;
+   RECTL DestRect, MaskRect, SpecifiedDestRect;
    POINTL SourcePoint, BrushOrigin;
    HBRUSH hBrushFg = NULL;
    PGDIBRUSHOBJ BrushFg = NULL;
@@ -1517,7 +1517,21 @@
    NTSTATUS Status;
    INT *Dx = NULL;
    POINT Start;
+   BOOL DoBreak = FALSE;
 
+   // TODO: Write test-cases to exactly match real Windows in different
+   // bad parameters (e.g. does Windows check the DC or the RECT first?).
+   if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED)))
+   {
+      // At least one of the two flags were specified. Copy lprc. Once.
+      Status = MmCopyFromCaller(&SpecifiedDestRect, lprc, sizeof(RECT));
+      if (!NT_SUCCESS(Status))
+      {
+         SetLastWin32Error(ERROR_INVALID_PARAMETER);
+         return FALSE;
+      }
+   }
+
    dc = DC_LockDc(hDC);
    if (!dc)
    {
@@ -1607,11 +1621,10 @@
 
    if ((fuOptions & ETO_OPAQUE) && lprc)
    {
-      MmCopyFromCaller(&DestRect, lprc, sizeof(RECT));
-      DestRect.left += dc->w.DCOrgX;
-      DestRect.top += dc->w.DCOrgY;
-      DestRect.right += dc->w.DCOrgX;
-      DestRect.bottom += dc->w.DCOrgY;
+      DestRect.left   = SpecifiedDestRect.left   + dc->w.DCOrgX;
+      DestRect.top    = SpecifiedDestRect.top    + dc->w.DCOrgY;
+      DestRect.right  = SpecifiedDestRect.right  + dc->w.DCOrgX;
+      DestRect.bottom = SpecifiedDestRect.bottom + dc->w.DCOrgY;
       IntEngBitBlt(
          BitmapObj,
          NULL,
@@ -1880,6 +1893,17 @@
        * brush.
        */
 
+      if (lprc &&
+          (fuOptions & ETO_CLIPPED) &&
+          DestRect.right >= SpecifiedDestRect.right + dc->w.DCOrgX)
+      {
+         // We do the check '>=' instead of '>' to possibly save an iteration
+         // through this loop, since it's breaking after the drawing is done,
+         // and x is always incremented.
+         DestRect.right = SpecifiedDestRect.right + dc->w.DCOrgX;
+         DoBreak = TRUE;
+      }
+
       IntEngMaskBlt(
          SurfObj,
          SourceGlyphSurf,
@@ -1895,6 +1919,11 @@
       EngUnlockSurface(SourceGlyphSurf);
       EngDeleteSurface((HSURF)HSourceGlyph);
 
+      if (DoBreak)
+      {
+         break;
+      }
+
       if (NULL == Dx)
       {
          TextLeft += glyph->advance.x;