comctl32: Reduce memory usage of the syslink control.
diff --git a/dlls/comctl32/syslink.c b/dlls/comctl32/syslink.c
index 1938814..24d567e 100644
--- a/dlls/comctl32/syslink.c
+++ b/dlls/comctl32/syslink.c
@@ -1,7 +1,7 @@
/*
* SysLink control
*
- * Copyright 2004, 2005 Thomas Weidenmueller <w3seek@reactos.com>
+ * Copyright 2004 - 2006 Thomas Weidenmueller <w3seek@reactos.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -62,7 +62,6 @@
typedef struct _DOC_ITEM
{
struct _DOC_ITEM *Next; /* Address to the next item */
- LPWSTR Text; /* Text of the document item */
UINT nText; /* Number of characters of the text */
SL_ITEM_TYPE Type; /* type of the item */
PDOC_TEXTBLOCK Blocks; /* Array of text blocks */
@@ -79,6 +78,7 @@
UINT Dummy;
} Text;
} u;
+ WCHAR Text[1]; /* Text of the document item */
} DOC_ITEM, *PDOC_ITEM;
typedef struct
@@ -117,8 +117,14 @@
{
if(DocItem->Type == slLink)
{
- Free(DocItem->u.Link.szID);
- Free(DocItem->u.Link.szUrl);
+ if (DocItem->u.Link.szID != NULL)
+ {
+ Free(DocItem->u.Link.szID);
+ }
+ if (DocItem->u.Link.szUrl != NULL)
+ {
+ Free(DocItem->u.Link.szUrl);
+ }
}
/* we don't free Text because it's just a pointer to a character in the
@@ -135,16 +141,16 @@
SL_ITEM_TYPE type, PDOC_ITEM LastItem)
{
PDOC_ITEM Item;
- Item = Alloc(sizeof(DOC_ITEM) + ((textlen + 1) * sizeof(WCHAR)));
+
+ textlen = min(textlen, lstrlenW(Text));
+ Item = Alloc(FIELD_OFFSET(DOC_ITEM, Text[textlen + 1]));
if(Item == NULL)
{
ERR("Failed to alloc DOC_ITEM structure!\n");
return NULL;
}
- textlen = min(textlen, lstrlenW(Text));
Item->Next = NULL;
- Item->Text = (LPWSTR)(Item + 1);
Item->nText = textlen;
Item->Type = type;
Item->Blocks = NULL;
@@ -159,7 +165,6 @@
}
lstrcpynW(Item->Text, Text, textlen + 1);
- Item->Text[textlen] = 0;
return Item;
}
@@ -351,12 +356,11 @@
if(lpID != NULL)
{
nc = min(lenId, strlenW(lpID));
- nc = min(nc, MAX_LINKID_TEXT);
- Last->u.Link.szID = Alloc((MAX_LINKID_TEXT + 1) * sizeof(WCHAR));
+ nc = min(nc, MAX_LINKID_TEXT - 1);
+ Last->u.Link.szID = Alloc((nc + 1) * sizeof(WCHAR));
if(Last->u.Link.szID != NULL)
{
lstrcpynW(Last->u.Link.szID, lpID, nc + 1);
- Last->u.Link.szID[nc] = 0;
}
}
else
@@ -364,12 +368,11 @@
if(lpUrl != NULL)
{
nc = min(lenUrl, strlenW(lpUrl));
- nc = min(nc, L_MAX_URL_LENGTH);
- Last->u.Link.szUrl = Alloc((L_MAX_URL_LENGTH + 1) * sizeof(WCHAR));
+ nc = min(nc, L_MAX_URL_LENGTH - 1);
+ Last->u.Link.szUrl = Alloc((nc + 1) * sizeof(WCHAR));
if(Last->u.Link.szUrl != NULL)
{
lstrcpynW(Last->u.Link.szUrl, lpUrl, nc + 1);
- Last->u.Link.szUrl[nc] = 0;
}
}
else
@@ -431,12 +434,11 @@
if(lpID != NULL)
{
nc = min(lenId, strlenW(lpID));
- nc = min(nc, MAX_LINKID_TEXT);
- Last->u.Link.szID = Alloc((MAX_LINKID_TEXT + 1) * sizeof(WCHAR));
+ nc = min(nc, MAX_LINKID_TEXT - 1);
+ Last->u.Link.szID = Alloc((nc + 1) * sizeof(WCHAR));
if(Last->u.Link.szID != NULL)
{
lstrcpynW(Last->u.Link.szID, lpID, nc + 1);
- Last->u.Link.szID[nc] = 0;
}
}
else
@@ -444,12 +446,11 @@
if(lpUrl != NULL)
{
nc = min(lenUrl, strlenW(lpUrl));
- nc = min(nc, L_MAX_URL_LENGTH);
- Last->u.Link.szUrl = Alloc((L_MAX_URL_LENGTH + 1) * sizeof(WCHAR));
+ nc = min(nc, L_MAX_URL_LENGTH - 1);
+ Last->u.Link.szUrl = Alloc((nc + 1) * sizeof(WCHAR));
if(Last->u.Link.szUrl != NULL)
{
lstrcpynW(Last->u.Link.szUrl, lpUrl, nc + 1);
- Last->u.Link.szUrl[nc] = 0;
}
}
else
@@ -751,6 +752,7 @@
{
Free(bl);
bl = NULL;
+ nBlocks = 0;
}
break;
}
@@ -769,11 +771,12 @@
{
Free(bl);
bl = NULL;
+ nBlocks = 0;
}
}
else
{
- bl = Alloc((nBlocks + 1) * sizeof(DOC_TEXTBLOCK));
+ bl = Alloc(sizeof(DOC_TEXTBLOCK));
if (bl != NULL)
nBlocks++;
}
@@ -820,8 +823,6 @@
{
Current->Blocks = bl;
}
- else
- Current->Blocks = NULL;
}
SelectObject(hdc, hOldFont);
@@ -1037,8 +1038,10 @@
static LRESULT SYSLINK_SetItem (SYSLINK_INFO *infoPtr, PLITEM Item)
{
PDOC_ITEM di;
+ int nc;
+ PWSTR szId = NULL;
+ PWSTR szUrl = NULL;
BOOL Repaint = FALSE;
- BOOL Ret = TRUE;
if(!(Item->mask & LIF_ITEMINDEX) || !(Item->mask & (LIF_FLAGSMASK)))
{
@@ -1052,7 +1055,60 @@
ERR("Link %d couldn't be found\n", Item->iLink);
return FALSE;
}
-
+
+ if(Item->mask & LIF_ITEMID)
+ {
+ nc = min(lstrlenW(Item->szID), MAX_LINKID_TEXT - 1);
+ szId = Alloc((nc + 1) * sizeof(WCHAR));
+ if(szId)
+ {
+ lstrcpynW(szId, Item->szID, nc + 1);
+ }
+ else
+ {
+ ERR("Unable to allocate memory for link id\n");
+ return FALSE;
+ }
+ }
+
+ if(Item->mask & LIF_URL)
+ {
+ nc = min(lstrlenW(Item->szUrl), L_MAX_URL_LENGTH - 1);
+ szUrl = Alloc((nc + 1) * sizeof(WCHAR));
+ if(szUrl)
+ {
+ lstrcpynW(szUrl, Item->szUrl, nc + 1);
+ }
+ else
+ {
+ if (szId)
+ {
+ Free(szId);
+ }
+
+ ERR("Unable to allocate memory for link url\n");
+ return FALSE;
+ }
+ }
+
+ if(Item->mask & LIF_ITEMID)
+ {
+ if(di->u.Link.szID)
+ {
+ Free(di->u.Link.szID);
+ }
+ di->u.Link.szID = szId;
+ }
+
+ if(Item->mask & LIF_URL)
+ {
+ if(di->u.Link.szUrl)
+ {
+ Free(di->u.Link.szUrl);
+ }
+ di->u.Link.szUrl = szUrl;
+ }
+
if(Item->mask & LIF_STATE)
{
UINT oldstate = di->u.Link.state;
@@ -1065,47 +1121,13 @@
/* update the focus */
SYSLINK_SetFocusLink(infoPtr, ((di->u.Link.state & LIS_FOCUSED) ? di : NULL));
}
-
- if(Item->mask & LIF_ITEMID)
- {
- if(!di->u.Link.szID)
- {
- di->u.Link.szID = Alloc((MAX_LINKID_TEXT + 1) * sizeof(WCHAR));
- if(!Item->szID)
- {
- ERR("Unable to allocate memory for link id\n");
- Ret = FALSE;
- }
- }
- if(di->u.Link.szID)
- {
- lstrcpynW(di->u.Link.szID, Item->szID, MAX_LINKID_TEXT + 1);
- }
- }
-
- if(Item->mask & LIF_URL)
- {
- if(!di->u.Link.szUrl)
- {
- di->u.Link.szUrl = Alloc((MAX_LINKID_TEXT + 1) * sizeof(WCHAR));
- if(!Item->szUrl)
- {
- ERR("Unable to allocate memory for link url\n");
- Ret = FALSE;
- }
- }
- if(di->u.Link.szUrl)
- {
- lstrcpynW(di->u.Link.szUrl, Item->szUrl, MAX_LINKID_TEXT + 1);
- }
- }
if(Repaint)
{
SYSLINK_RepaintLink(infoPtr, di);
}
- return Ret;
+ return TRUE;
}
/***********************************************************************
@@ -1143,7 +1165,7 @@
{
if(di->u.Link.szID)
{
- lstrcpynW(Item->szID, di->u.Link.szID, MAX_LINKID_TEXT + 1);
+ lstrcpyW(Item->szID, di->u.Link.szID);
}
else
{
@@ -1155,7 +1177,7 @@
{
if(di->u.Link.szUrl)
{
- lstrcpynW(Item->szUrl, di->u.Link.szUrl, L_MAX_URL_LENGTH + 1);
+ lstrcpyW(Item->szUrl, di->u.Link.szUrl);
}
else
{
@@ -1215,7 +1237,7 @@
HitTest->item.stateMask = 0;
if(Current->u.Link.szID)
{
- lstrcpynW(HitTest->item.szID, Current->u.Link.szID, MAX_LINKID_TEXT + 1);
+ lstrcpyW(HitTest->item.szID, Current->u.Link.szID);
}
else
{
@@ -1223,7 +1245,7 @@
}
if(Current->u.Link.szUrl)
{
- lstrcpynW(HitTest->item.szUrl, Current->u.Link.szUrl, L_MAX_URL_LENGTH + 1);
+ lstrcpyW(HitTest->item.szUrl, Current->u.Link.szUrl);
}
else
{
@@ -1285,7 +1307,7 @@
nml.item.stateMask = 0;
if(Link->u.Link.szID)
{
- lstrcpynW(nml.item.szID, Link->u.Link.szID, MAX_LINKID_TEXT + 1);
+ lstrcpyW(nml.item.szID, Link->u.Link.szID);
}
else
{
@@ -1293,7 +1315,7 @@
}
if(Link->u.Link.szUrl)
{
- lstrcpynW(nml.item.szUrl, Link->u.Link.szUrl, L_MAX_URL_LENGTH + 1);
+ lstrcpyW(nml.item.szUrl, Link->u.Link.szUrl);
}
else
{