📄 syslink.c
字号:
}
else
Last->u.Link.szID = NULL;
if(lpUrl != NULL)
{
nc = min(lenUrl, strlenW(lpUrl));
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);
}
}
else
Last->u.Link.szUrl = NULL;
}
docitems++;
}
if(linktext != NULL && linklen > 0)
{
/* we got an unclosed link, just display the text */
Last = SYSLINK_AppendDocItem(infoPtr, linktext, linklen, slText, Last);
if(Last == NULL)
{
ERR("Unable to create new document item!\n");
return docitems;
}
docitems++;
}
return docitems;
}
/***********************************************************************
* SYSLINK_RepaintLink
* Repaints a link.
*/
static VOID SYSLINK_RepaintLink (SYSLINK_INFO *infoPtr, PDOC_ITEM DocItem)
{
PDOC_TEXTBLOCK bl;
int n;
if(DocItem->Type != slLink)
{
ERR("DocItem not a link!\n");
return;
}
bl = DocItem->Blocks;
if (bl != NULL)
{
n = DocItem->nText;
while(n > 0)
{
InvalidateRect(infoPtr->Self, &bl->rc, TRUE);
n -= bl->nChars + bl->nSkip;
bl++;
}
}
}
/***********************************************************************
* SYSLINK_GetLinkItemByIndex
* Retrieves a document link by its index
*/
static PDOC_ITEM SYSLINK_GetLinkItemByIndex (SYSLINK_INFO *infoPtr, int iLink)
{
PDOC_ITEM Current = infoPtr->Items;
while(Current != NULL)
{
if((Current->Type == slLink) && (iLink-- <= 0))
{
return Current;
}
Current = Current->Next;
}
return NULL;
}
/***********************************************************************
* SYSLINK_GetFocusLink
* Retrieves the link that has the LIS_FOCUSED bit
*/
static PDOC_ITEM SYSLINK_GetFocusLink (SYSLINK_INFO *infoPtr, int *LinkId)
{
PDOC_ITEM Current = infoPtr->Items;
int id = 0;
while(Current != NULL)
{
if((Current->Type == slLink))
{
if(Current->u.Link.state & LIS_FOCUSED)
{
if(LinkId != NULL)
*LinkId = id;
return Current;
}
id++;
}
Current = Current->Next;
}
return NULL;
}
/***********************************************************************
* SYSLINK_GetNextLink
* Gets the next link
*/
static PDOC_ITEM SYSLINK_GetNextLink (SYSLINK_INFO *infoPtr, PDOC_ITEM Current)
{
for(Current = (Current != NULL ? Current->Next : infoPtr->Items);
Current != NULL;
Current = Current->Next)
{
if(Current->Type == slLink)
{
return Current;
}
}
return NULL;
}
/***********************************************************************
* SYSLINK_GetPrevLink
* Gets the previous link
*/
static PDOC_ITEM SYSLINK_GetPrevLink (SYSLINK_INFO *infoPtr, PDOC_ITEM Current)
{
if(Current == NULL)
{
/* returns the last link */
PDOC_ITEM Last = NULL;
for(Current = infoPtr->Items; Current != NULL; Current = Current->Next)
{
if(Current->Type == slLink)
{
Last = Current;
}
}
return Last;
}
else
{
/* returns the previous link */
PDOC_ITEM Cur, Prev = NULL;
for(Cur = infoPtr->Items; Cur != NULL; Cur = Cur->Next)
{
if(Cur == Current)
{
break;
}
if(Cur->Type == slLink)
{
Prev = Cur;
}
}
return Prev;
}
}
/***********************************************************************
* SYSLINK_WrapLine
* Tries to wrap a line.
*/
static BOOL SYSLINK_WrapLine (HDC hdc, LPWSTR Text, WCHAR BreakChar, int *LineLen,
int nFit, LPSIZE Extent, int Width)
{
WCHAR *Current;
if(nFit == *LineLen)
{
return FALSE;
}
*LineLen = nFit;
Current = Text + nFit;
/* check if we're in the middle of a word */
if((*Current) != BreakChar)
{
/* search for the beginning of the word */
while(Current > Text && (*(Current - 1)) != BreakChar)
{
Current--;
(*LineLen)--;
}
if((*LineLen) == 0)
{
Extent->cx = 0;
Extent->cy = 0;
}
return TRUE;
}
return TRUE;
}
/***********************************************************************
* SYSLINK_Render
* Renders the document in memory
*/
static VOID SYSLINK_Render (SYSLINK_INFO *infoPtr, HDC hdc)
{
RECT rc;
PDOC_ITEM Current;
HGDIOBJ hOldFont;
int x, y, LineHeight;
GetClientRect(infoPtr->Self, &rc);
rc.right -= SL_RIGHTMARGIN;
rc.bottom -= SL_BOTTOMMARGIN;
if(rc.right - SL_LEFTMARGIN < 0 || rc.bottom - SL_TOPMARGIN < 0) return;
hOldFont = SelectObject(hdc, infoPtr->Font);
x = SL_LEFTMARGIN;
y = SL_TOPMARGIN;
LineHeight = 0;
for(Current = infoPtr->Items; Current != NULL; Current = Current->Next)
{
int n, nBlocks;
LPWSTR tx;
PDOC_TEXTBLOCK bl, cbl;
INT nFit;
SIZE szDim;
if(Current->nText == 0)
{
continue;
}
tx = Current->Text;
n = Current->nText;
if (Current->Blocks != NULL)
{
Free(Current->Blocks);
Current->Blocks = NULL;
}
bl = NULL;
nBlocks = 0;
if(Current->Type == slText)
{
SelectObject(hdc, infoPtr->Font);
}
else if(Current->Type == slLink)
{
SelectObject(hdc, infoPtr->LinkFont);
}
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)
{
while(n > 0 && (*tx) == infoPtr->BreakChar)
{
tx++;
SkipChars++;
n--;
}
}
if((n == 0 && SkipChars != 0) ||
GetTextExtentExPointW(hdc, tx, n, rc.right - x, &nFit, NULL, &szDim))
{
int LineLen = n;
BOOL Wrap = FALSE;
if(n != 0)
{
Wrap = SYSLINK_WrapLine(hdc, tx, infoPtr->BreakChar, &LineLen, nFit, &szDim, rc.right - x);
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);
}
}
if(LineLen != n)
{
if(!GetTextExtentExPointW(hdc, tx, LineLen, rc.right - x, NULL, NULL, &szDim))
{
if(bl != NULL)
{
Free(bl);
bl = NULL;
nBlocks = 0;
}
break;
}
}
}
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)
{
cbl = bl + nBlocks - 1;
cbl->nChars = LineLen;
cbl->nSkip = SkipChars;
cbl->rc.left = x;
cbl->rc.top = y;
cbl->rc.right = x + szDim.cx;
cbl->rc.bottom = y + szDim.cy;
if(LineLen != 0)
{
x += szDim.cx;
LineHeight = max(LineHeight, szDim.cy);
if(Wrap)
{
x = SL_LEFTMARGIN;
y += LineHeight;
LineHeight = 0;
}
}
}
else
{
ERR("Failed to alloc DOC_TEXTBLOCK structure!\n");
break;
}
n -= LineLen;
tx += LineLen;
}
else
{
n--;
}
}
if(nBlocks != 0)
{
Current->Blocks = bl;
}
}
SelectObject(hdc, hOldFont);
}
/***********************************************************************
* SYSLINK_Draw
* Draws the SysLink control.
*/
static LRESULT SYSLINK_Draw (SYSLINK_INFO *infoPtr, HDC hdc)
{
RECT rc;
PDOC_ITEM Current;
HFONT hOldFont;
COLORREF OldTextColor, OldBkColor;
hOldFont = SelectObject(hdc, infoPtr->Font);
OldTextColor = SetTextColor(hdc, infoPtr->TextColor);
OldBkColor = SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
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;
for(Current = infoPtr->Items; Current != NULL; Current = Current->Next)
{
int n;
LPWSTR tx;
PDOC_TEXTBLOCK bl;
bl = Current->Blocks;
if(bl != NULL)
{
tx = Current->Text;
n = Current->nText;
if(Current->Type == slText)
{
SelectObject(hdc, infoPtr->Font);
SetTextColor(hdc, infoPtr->TextColor);
}
else
{
SelectObject(hdc, infoPtr->LinkFont);
SetTextColor(hdc, (!(Current->u.Link.state & LIS_VISITED) ? infoPtr->LinkColor : infoPtr->VisitedColor));
}
while(n > 0)
{
tx += bl->nSkip;
ExtTextOutW(hdc, bl->rc.left, bl->rc.top, ETO_OPAQUE | ETO_CLIPPED, &bl->rc, tx, bl->nChars, NULL);
if((Current->Type == slLink) && (Current->u.Link.state & LIS_FOCUSED) && infoPtr->HasFocus)
{
COLORREF PrevTextColor;
PrevTextColor = SetTextColor(hdc, infoPtr->TextColor);
DrawFocusRect(hdc, &bl->rc);
SetTextColor(hdc, PrevTextColor);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -