* If you discover missing features, or bugs, please note them below.
*/
-#include <stdarg.h>
-#include <string.h>
-#include "windef.h"
-#include "winbase.h"
-#include "wingdi.h"
-#include "winuser.h"
-#include "winnls.h"
-#include "commctrl.h"
#include "comctl32.h"
-#include "wine/unicode.h"
-#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(syslink);
COLORREF TextColor; /* Color of the text */
COLORREF LinkColor; /* Color of links */
COLORREF VisitedColor; /* Color of visited links */
- COLORREF BackColor; /* Background color, set on creation */
WCHAR BreakChar; /* Break Character for the current font */
BOOL IgnoreReturn; /* (infoPtr->Style & LWS_IGNORERETURN) on creation */
} SYSLINK_INFO;
infoPtr->Items = NULL;
}
+/***********************************************************************
+ * SYSLINK_StrCmpNIW
+ * Wrapper for StrCmpNIW to ensure 'len' is not too big.
+ */
+static INT SYSLINK_StrCmpNIW (LPCWSTR str, LPCWSTR comp, INT len)
+{
+ INT i;
+
+ for(i = 0; i < len; i++)
+ {
+ if(!str[i])
+ {
+ len = i + 1;
+ break;
+ }
+ }
+
+ return StrCmpNIW(str, comp, len);
+}
+
/***********************************************************************
* SYSLINK_ParseText
* Parses the window text string and creates a document. Returns the
{
if(*current == '<')
{
- if(!StrCmpNIW(current, SL_LINKOPEN, 2) && (CurrentType == slText))
+ if(!SYSLINK_StrCmpNIW(current, SL_LINKOPEN, 2) && (CurrentType == slText))
{
BOOL ValidParam = FALSE, ValidLink = FALSE;
CheckParameter:
/* compare the current position with all known parameters */
- if(!StrCmpNIW(tmp, SL_HREF, 6))
+ if(!SYSLINK_StrCmpNIW(tmp, SL_HREF, 6))
{
taglen += 6;
ValidParam = TRUE;
CurrentParameter = &lpUrl;
CurrentParameterLen = &lenUrl;
}
- else if(!StrCmpNIW(tmp, SL_ID, 4))
+ else if(!SYSLINK_StrCmpNIW(tmp, SL_ID, 4))
{
taglen += 4;
ValidParam = TRUE;
}
}
}
- else if(!StrCmpNIW(current, SL_LINKCLOSE, 4) && (CurrentType == slLink) && firsttag)
+ else if(!SYSLINK_StrCmpNIW(current, SL_LINKCLOSE, 4) && (CurrentType == slLink) && firsttag)
{
/* there's a <a...> tag opened, first add the previous text, if present */
if(textstart != NULL && textlen > 0 && firsttag > textstart)
while(Current != NULL)
{
- if((Current->Type == slLink))
+ if(Current->Type == slLink)
{
if(Current->u.Link.state & LIS_FOCUSED)
{
* SYSLINK_WrapLine
* Tries to wrap a line.
*/
-static BOOL SYSLINK_WrapLine (LPWSTR Text, WCHAR BreakChar, int *LineLen,
+static BOOL SYSLINK_WrapLine (LPWSTR Text, WCHAR BreakChar, int x, int *LineLen,
int nFit, LPSIZE Extent)
{
- WCHAR *Current;
+ int i;
- if(nFit == *LineLen)
- {
- return FALSE;
- }
+ for (i = 0; i < nFit; i++) if (Text[i] == '\n') break;
- *LineLen = nFit;
+ if (i == *LineLen) return FALSE;
- Current = Text + nFit;
-
/* check if we're in the middle of a word */
- if((*Current) != BreakChar)
+ if (Text[i] != '\n' && Text[i] != BreakChar)
{
/* search for the beginning of the word */
- while(Current > Text && (*(Current - 1)) != BreakChar)
- {
- Current--;
- (*LineLen)--;
- }
-
- if((*LineLen) == 0)
+ while (i && Text[i - 1] != BreakChar) i--;
+
+ if (i == 0)
{
Extent->cx = 0;
Extent->cy = 0;
+ if (x == SL_LEFTMARGIN) i = max( nFit, 1 );
}
- return TRUE;
}
-
+ *LineLen = i;
return TRUE;
}
HGDIOBJ hOldFont;
int x, y, LineHeight;
SIZE szDoc;
+ TEXTMETRICW tm;
szDoc.cx = szDoc.cy = 0;
x = SL_LEFTMARGIN;
y = SL_TOPMARGIN;
- LineHeight = 0;
-
+ GetTextMetricsW( hdc, &tm );
+ LineHeight = tm.tmHeight + tm.tmExternalLeading;
+
for(Current = infoPtr->Items; Current != NULL; Current = Current->Next)
{
int n, nBlocks;
PDOC_TEXTBLOCK bl, cbl;
INT nFit;
SIZE szDim;
+ int SkipChars = 0;
if(Current->nText == 0)
{
while(n > 0)
{
- int SkipChars = 0;
-
/* skip break characters unless they're the first of the doc item */
if(tx != Current->Text || x == SL_LEFTMARGIN)
{
+ if (n && *tx == '\n')
+ {
+ tx++;
+ SkipChars++;
+ n--;
+ }
while(n > 0 && (*tx) == infoPtr->BreakChar)
{
tx++;
if(n != 0)
{
- Wrap = SYSLINK_WrapLine(tx, infoPtr->BreakChar, &LineLen, nFit, &szDim);
+ Wrap = SYSLINK_WrapLine(tx, infoPtr->BreakChar, x, &LineLen, nFit, &szDim);
if(LineLen == 0)
{
- if(x > SL_LEFTMARGIN)
- {
- /* move one line down, the word didn't fit into the line */
- x = SL_LEFTMARGIN;
- y += LineHeight;
- LineHeight = 0;
- continue;
- }
- else
- {
- /* the word starts at the beginning of the line and doesn't
- fit into the line, so break it at the last character that fits */
- LineLen = max(nFit, 1);
- }
+ /* move one line down, the word didn't fit into the line */
+ x = SL_LEFTMARGIN;
+ y += LineHeight;
+ continue;
}
if(LineLen != n)
if(LineLen != 0)
{
x += szDim.cx;
- LineHeight = max(LineHeight, szDim.cy);
-
if(Wrap)
{
x = SL_LEFTMARGIN;
y += LineHeight;
- LineHeight = 0;
}
}
}
}
n -= LineLen;
tx += LineLen;
+ SkipChars = 0;
}
else
{
PDOC_ITEM Current;
HFONT hOldFont;
COLORREF OldTextColor, OldBkColor;
+ HBRUSH hBrush;
+ UINT text_flags = ETO_CLIPPED;
+ UINT mode = GetBkMode( hdc );
hOldFont = SelectObject(hdc, infoPtr->Font);
OldTextColor = SetTextColor(hdc, infoPtr->TextColor);
- OldBkColor = SetBkColor(hdc, infoPtr->BackColor);
-
+ OldBkColor = SetBkColor(hdc, comctl32_color.clrWindow);
+
GetClientRect(infoPtr->Self, &rc);
rc.right -= SL_RIGHTMARGIN + SL_LEFTMARGIN;
rc.bottom -= SL_BOTTOMMARGIN + SL_TOPMARGIN;
if(rc.right < 0 || rc.bottom < 0) return 0;
+ hBrush = (HBRUSH)SendMessageW(infoPtr->Notify, WM_CTLCOLORSTATIC,
+ (WPARAM)hdc, (LPARAM)infoPtr->Self);
+ if (!(infoPtr->Style & LWS_TRANSPARENT))
+ {
+ FillRect(hdc, &rc, hBrush);
+ if (GetBkMode( hdc ) == OPAQUE) text_flags |= ETO_OPAQUE;
+ }
+ else SetBkMode( hdc, TRANSPARENT );
+
+ DeleteObject(hBrush);
+
for(Current = infoPtr->Items; Current != NULL; Current = Current->Next)
{
int n;
while(n > 0)
{
tx += bl->nSkip;
- ExtTextOutW(hdc, bl->rc.left, bl->rc.top, ETO_OPAQUE | ETO_CLIPPED, &bl->rc, tx, bl->nChars, NULL);
+ ExtTextOutW(hdc, bl->rc.left, bl->rc.top, text_flags, &bl->rc, tx, bl->nChars, NULL);
if((Current->Type == slLink) && (Current->u.Link.state & LIS_FOCUSED) && infoPtr->HasFocus)
{
COLORREF PrevTextColor;
SetBkColor(hdc, OldBkColor);
SetTextColor(hdc, OldTextColor);
SelectObject(hdc, hOldFont);
-
+ SetBkMode(hdc, mode);
return 0;
}
return 0;
}
-/***********************************************************************
- * SYSLINK_EraseBkgnd
- * Handles the WM_ERASEBKGND message.
- */
-static LRESULT SYSLINK_EraseBkgnd (const SYSLINK_INFO *infoPtr, HDC hdc)
-{
- HBRUSH hbr;
- RECT r;
-
- GetClientRect(infoPtr->Self, &r);
- hbr = CreateSolidBrush(infoPtr->BackColor);
- FillRect(hdc, &r, hbr);
- DeleteObject(hbr);
-
- return 1;
-}
-
/***********************************************************************
* SYSLINK_SetFont
* Set new Font for the SysLink control.
for(Current = infoPtr->Items; Current != NULL; Current = Current->Next)
{
if((Current->Type == slLink) && SYSLINK_PtInDocItem(Current, *pt) &&
- (!MustBeEnabled || (MustBeEnabled && (Current->u.Link.state & LIS_ENABLED))))
+ (!MustBeEnabled || (Current->u.Link.state & LIS_ENABLED)))
{
if(LinkId != NULL)
{
infoPtr = (SYSLINK_INFO *)GetWindowLongPtrW(hwnd, 0);
if (!infoPtr && message != WM_CREATE)
- goto HandleDefaultMessage;
+ return DefWindowProcW(hwnd, message, wParam, lParam);
switch(message) {
case WM_PRINTCLIENT:
return SYSLINK_Paint (infoPtr, (HDC)wParam);
case WM_ERASEBKGND:
- return SYSLINK_EraseBkgnd(infoPtr, (HDC)wParam);
+ if (!(infoPtr->Style & LWS_TRANSPARENT))
+ {
+ HDC hdc = (HDC)wParam;
+ HBRUSH brush = CreateSolidBrush( comctl32_color.clrWindow );
+ RECT rect;
+
+ GetClipBox( hdc, &rect );
+ FillRect( hdc, &rect, brush );
+ DeleteObject( brush );
+ return 1;
+ }
+ return 0;
case WM_SETCURSOR:
{
SetCursor(LoadCursorW(0, (LPCWSTR)IDC_HAND));
return TRUE;
}
- /* let the default window proc handle this message */
- goto HandleDefaultMessage;
+
+ return DefWindowProcW(hwnd, message, wParam, lParam);
}
case WM_SIZE:
case WM_SETTEXT:
SYSLINK_SetText(infoPtr, (LPWSTR)lParam);
- goto HandleDefaultMessage;
+ return DefWindowProcW(hwnd, message, wParam, lParam);
case WM_LBUTTONDOWN:
{
SYSKEY_SelectNextPrevLink(infoPtr, shift);
return 0;
}
+ default:
+ return DefWindowProcW(hwnd, message, wParam, lParam);
}
- goto HandleDefaultMessage;
}
case WM_GETDLGCODE:
infoPtr->TextColor = comctl32_color.clrWindowText;
infoPtr->LinkColor = comctl32_color.clrHighlight;
infoPtr->VisitedColor = comctl32_color.clrHighlight;
- infoPtr->BackColor = infoPtr->Style & LWS_TRANSPARENT ?
- comctl32_color.clrWindow : comctl32_color.clrBtnFace;
infoPtr->BreakChar = ' ';
infoPtr->IgnoreReturn = infoPtr->Style & LWS_IGNORERETURN;
TRACE("SysLink Ctrl creation, hwnd=%p\n", hwnd);
case WM_SYSCOLORCHANGE:
COMCTL32_RefreshSysColors();
- if (infoPtr->Style & LWS_TRANSPARENT)
- infoPtr->BackColor = comctl32_color.clrWindow;
return 0;
default:
-HandleDefaultMessage:
if ((message >= WM_USER) && (message < WM_APP) && !COMCTL32_IsReflectedMessage(message))
{
ERR("unknown msg %04x wp=%04lx lp=%08lx\n", message, wParam, lParam );