Thomas Weidenmueller : comctl32: Implement LM_GETIDEALSIZE for the syslink control.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Feb 20 14:18:49 CST 2007


Module: wine
Branch: master
Commit: 254b97732befd7e7bd29f369d2878ef38bfd4488
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=254b97732befd7e7bd29f369d2878ef38bfd4488

Author: Thomas Weidenmueller <wine-patches at reactsoft.com>
Date:   Mon Feb 19 16:25:01 2007 +0100

comctl32: Implement LM_GETIDEALSIZE for the syslink control.

---

 dlls/comctl32/syslink.c |  163 ++++++++++++++++++++++++++++++-----------------
 include/commctrl.h      |    1 +
 2 files changed, 106 insertions(+), 58 deletions(-)

diff --git a/dlls/comctl32/syslink.c b/dlls/comctl32/syslink.c
index 304e407..d631244 100644
--- a/dlls/comctl32/syslink.c
+++ b/dlls/comctl32/syslink.c
@@ -643,18 +643,24 @@ static BOOL SYSLINK_WrapLine (HDC hdc, LPWSTR Text, WCHAR BreakChar, int *LineLe
  * SYSLINK_Render
  * Renders the document in memory
  */
-static VOID SYSLINK_Render (SYSLINK_INFO *infoPtr, HDC hdc)
+static VOID SYSLINK_Render (SYSLINK_INFO *infoPtr, HDC hdc, PRECT pRect)
 {
     RECT rc;
     PDOC_ITEM Current;
     HGDIOBJ hOldFont;
     int x, y, LineHeight;
-    
-    GetClientRect(infoPtr->Self, &rc);
+    SIZE szDoc;
+
+    szDoc.cx = szDoc.cy = 0;
+
+    rc = *pRect;
     rc.right -= SL_RIGHTMARGIN;
     rc.bottom -= SL_BOTTOMMARGIN;
-    
-    if(rc.right - SL_LEFTMARGIN < 0 || rc.bottom - SL_TOPMARGIN < 0) return;
+
+    if(rc.right - SL_LEFTMARGIN < 0)
+        rc.right = MAXLONG;
+    if (rc.bottom - SL_TOPMARGIN < 0)
+        rc.bottom = MAXLONG;
     
     hOldFont = SelectObject(hdc, infoPtr->Font);
     
@@ -715,6 +721,7 @@ static VOID SYSLINK_Render (SYSLINK_INFO *infoPtr, HDC hdc)
             {
                 int LineLen = n;
                 BOOL Wrap = FALSE;
+                PDOC_TEXTBLOCK nbl;
                 
                 if(n != 0)
                 {
@@ -753,30 +760,12 @@ static VOID SYSLINK_Render (SYSLINK_INFO *infoPtr, HDC hdc)
                     }
                 }
                 
-                if(bl != NULL)
-                {
-                    PDOC_TEXTBLOCK nbl = ReAlloc(bl, (nBlocks + 1) * sizeof(DOC_TEXTBLOCK));
-                    if (nbl != NULL)
-                    {
-                        bl = nbl;
-                        nBlocks++;
-                    }
-                    else
-                    {
-                        Free(bl);
-                        bl = NULL;
-                        nBlocks = 0;
-                    }
-                }
-                else
-                {
-                    bl = Alloc(sizeof(DOC_TEXTBLOCK));
-                    if (bl != NULL)
-                        nBlocks++;
-                }
-                
-                if(bl != NULL)
+                nbl = ReAlloc(bl, (nBlocks + 1) * sizeof(DOC_TEXTBLOCK));
+                if (nbl != NULL)
                 {
+                    bl = nbl;
+                    nBlocks++;
+
                     cbl = bl + nBlocks - 1;
                     
                     cbl->nChars = LineLen;
@@ -785,7 +774,12 @@ static VOID SYSLINK_Render (SYSLINK_INFO *infoPtr, HDC hdc)
                     cbl->rc.top = y;
                     cbl->rc.right = x + szDim.cx;
                     cbl->rc.bottom = y + szDim.cy;
-                    
+
+                    if (cbl->rc.right > szDoc.cx)
+                        szDoc.cx = cbl->rc.right;
+                    if (cbl->rc.bottom > szDoc.cy)
+                        szDoc.cy = cbl->rc.bottom;
+
                     if(LineLen != 0)
                     {
                         x += szDim.cx;
@@ -801,6 +795,10 @@ static VOID SYSLINK_Render (SYSLINK_INFO *infoPtr, HDC hdc)
                 }
                 else
                 {
+                    Free(bl);
+                    bl = NULL;
+                    nBlocks = 0;
+
                     ERR("Failed to alloc DOC_TEXTBLOCK structure!\n");
                     break;
                 }
@@ -820,6 +818,9 @@ static VOID SYSLINK_Render (SYSLINK_INFO *infoPtr, HDC hdc)
     }
     
     SelectObject(hdc, hOldFont);
+
+    pRect->right = pRect->left + szDoc.cx;
+    pRect->bottom = pRect->top + szDoc.cy;
 }
 
 /***********************************************************************
@@ -920,6 +921,7 @@ static HFONT SYSLINK_SetFont (SYSLINK_INFO *infoPtr, HFONT hFont, BOOL bRedraw)
     HDC hdc;
     LOGFONTW lf;
     TEXTMETRICW tm;
+    RECT rcClient;
     HFONT hOldFont = infoPtr->Font;
     infoPtr->Font = hFont;
     
@@ -931,24 +933,27 @@ static HFONT SYSLINK_SetFont (SYSLINK_INFO *infoPtr, HFONT hFont, BOOL bRedraw)
     }
 
     /* Render text position and word wrapping in memory */
-    hdc = GetDC(infoPtr->Self);
-    if(hdc != NULL)
+    if (GetClientRect(infoPtr->Self, &rcClient))
     {
-        /* create a new underline font */
-        if(GetTextMetricsW(hdc, &tm) &&
-           GetObjectW(infoPtr->Font, sizeof(LOGFONTW), &lf))
-        {
-            lf.lfUnderline = TRUE;
-            infoPtr->LinkFont = CreateFontIndirectW(&lf);
-            infoPtr->BreakChar = tm.tmBreakChar;
-        }
-        else
+        hdc = GetDC(infoPtr->Self);
+        if(hdc != NULL)
         {
-            ERR("Failed to create link font!\n");
-        }
+            /* create a new underline font */
+            if(GetTextMetricsW(hdc, &tm) &&
+               GetObjectW(infoPtr->Font, sizeof(LOGFONTW), &lf))
+            {
+                lf.lfUnderline = TRUE;
+                infoPtr->LinkFont = CreateFontIndirectW(&lf);
+                infoPtr->BreakChar = tm.tmBreakChar;
+            }
+            else
+            {
+                ERR("Failed to create link font!\n");
+            }
 
-        SYSLINK_Render(infoPtr, hdc);
-        ReleaseDC(infoPtr->Self, hdc);
+            SYSLINK_Render(infoPtr, hdc, &rcClient);
+            ReleaseDC(infoPtr->Self, hdc);
+        }
     }
     
     if(bRedraw)
@@ -978,14 +983,19 @@ static LRESULT SYSLINK_SetText (SYSLINK_INFO *infoPtr, LPCWSTR Text)
     /* let's parse the string and create a document */
     if(SYSLINK_ParseText(infoPtr, Text) > 0)
     {
+        RECT rcClient;
+
         /* Render text position and word wrapping in memory */
-        HDC hdc = GetDC(infoPtr->Self);
-        if (hdc != NULL)
+        if (GetClientRect(infoPtr->Self, &rcClient))
         {
-            SYSLINK_Render(infoPtr, hdc);
-            ReleaseDC(infoPtr->Self, hdc);
+            HDC hdc = GetDC(infoPtr->Self);
+            if (hdc != NULL)
+            {
+                SYSLINK_Render(infoPtr, hdc, &rcClient);
+                ReleaseDC(infoPtr->Self, hdc);
 
-            InvalidateRect(infoPtr->Self, NULL, TRUE);
+                InvalidateRect(infoPtr->Self, NULL, TRUE);
+            }
         }
     }
     
@@ -1076,6 +1086,7 @@ static LRESULT SYSLINK_SetItem (SYSLINK_INFO *infoPtr, PLITEM Item)
         else
         {
             Free(szId);
+
             ERR("Unable to allocate memory for link url\n");
             return FALSE;
         }
@@ -1503,6 +1514,33 @@ static BOOL SYSLINK_NoNextLink (SYSLINK_INFO *infoPtr, BOOL Prev)
 }
 
 /***********************************************************************
+ *           SYSLINK_GetIdealSize
+ * Calculates the ideal size of a link control at a given maximum width.
+ */
+static VOID SYSLINK_GetIdealSize (SYSLINK_INFO *infoPtr, int cxMaxWidth, LPSIZE lpSize)
+{
+    RECT rc;
+    HDC hdc;
+
+    rc.left = rc.top = rc.bottom = 0;
+    rc.right = cxMaxWidth;
+
+    hdc = GetDC(infoPtr->Self);
+    if (hdc != NULL)
+    {
+        HGDIOBJ hOldFont = SelectObject(hdc, infoPtr->Font);
+
+        SYSLINK_Render(infoPtr, hdc, &rc);
+
+        SelectObject(hdc, hOldFont);
+        ReleaseDC(infoPtr->Self, hdc);
+
+        lpSize->cx = rc.right;
+        lpSize->cy = rc.bottom;
+    }
+}
+
+/***********************************************************************
  *           SysLinkWindowProc
  */
 static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message,
@@ -1542,11 +1580,15 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message,
 
     case WM_SIZE:
     {
-        HDC hdc = GetDC(infoPtr->Self);
-        if(hdc != NULL)
+        RECT rcClient;
+        if (GetClientRect(infoPtr->Self, &rcClient))
         {
-          SYSLINK_Render(infoPtr, hdc);
-          ReleaseDC(infoPtr->Self, hdc);
+            HDC hdc = GetDC(infoPtr->Self);
+            if(hdc != NULL)
+            {
+                SYSLINK_Render(infoPtr, hdc, &rcClient);
+                ReleaseDC(infoPtr->Self, hdc);
+            }
         }
         return 0;
     }
@@ -1651,6 +1693,11 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message,
         return SYSLINK_GetItem(infoPtr, (PLITEM)lParam);
 
     case LM_GETIDEALHEIGHT:
+        if (lParam)
+        {
+            /* LM_GETIDEALSIZE */
+            SYSLINK_GetIdealSize(infoPtr, (int)wParam, (LPSIZE)lParam);
+        }
         return SYSLINK_GetIdealHeight(infoPtr);
 
     case WM_SETFOCUS:
@@ -1660,10 +1707,10 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message,
         return SYSLINK_KillFocus(infoPtr, (HWND)wParam);
 
     case WM_ENABLE:
-	infoPtr->Style &= ~WS_DISABLED;
-	infoPtr->Style |= (wParam ? 0 : WS_DISABLED);
-	InvalidateRect (infoPtr->Self, NULL, FALSE);
-	return 0;
+        infoPtr->Style &= ~WS_DISABLED;
+        infoPtr->Style |= (wParam ? 0 : WS_DISABLED);
+        InvalidateRect (infoPtr->Self, NULL, FALSE);
+        return 0;
 
     case WM_STYLECHANGED:
         if (wParam == GWL_STYLE)
@@ -1710,7 +1757,7 @@ static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message,
 HandleDefaultMessage:
         if ((message >= WM_USER) && (message < WM_APP))
         {
-	        ERR("unknown msg %04x wp=%04x lp=%08lx\n", message, wParam, lParam );
+            ERR("unknown msg %04x wp=%04x lp=%08lx\n", message, wParam, lParam );
         }
         return DefWindowProcW(hwnd, message, wParam, lParam);
     }
diff --git a/include/commctrl.h b/include/commctrl.h
index 1415a30..3225e1b 100644
--- a/include/commctrl.h
+++ b/include/commctrl.h
@@ -4889,6 +4889,7 @@ static const WCHAR WC_LINK[] = { 'S','y','s','L','i','n','k',0 };
 /* SysLink messages */
 #define LM_HITTEST           (WM_USER + 768)
 #define LM_GETIDEALHEIGHT    (WM_USER + 769)
+#define LM_GETIDEALSIZE      (LM_GETIDEALHEIGHT)
 #define LM_SETITEM           (WM_USER + 770)
 #define LM_GETITEM           (WM_USER + 771)
 




More information about the wine-cvs mailing list