#include "stdafx.h"
#include "PPHtmlDrawer.h"
#include "atlconv.h" // for Unicode conversion - requires #include <afxdisp.h> // MFC OLE automation classes
#include <shellapi.h>
#pragma comment(lib, "comctl32.lib")
/*
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
*/
#define PPHTMLDRAWER_NO_HOVERLINK -2 //A hot area is not exist under the cursor
#define PPHTMLDRAWER_BREAK_CHARS _T(" -.,!:;)}]?") //A set of the chars to break line in the text wrap mode
enum {
MODE_DRAW = 0,
MODE_FIRSTPASS,
MODE_SECONDPASS
};
/*
#define m_szOffsetShadow.cx 4 //
#define m_szOffsetShadow.cy 4 //
#define m_szDepthShadow.cx 7 //
#define m_szDepthShadow.cy 7 //
#define PPHTMLDRAWER_SHADOW_COLOR RGB (64, 64, 64) //A gradient shadow's color
*/
/////////////////////////////////////////////////////////////////////////////
// CPPHtmlDrawer
CPPHtmlDrawer::CPPHtmlDrawer()
{
m_nNumPass = MODE_FIRSTPASS;
m_hInstDll = NULL;
m_bFreeInstDll = FALSE;
m_hDC = NULL;
m_hImageList = NULL;
m_csCallbackRepaint.hWnd = NULL;
m_csCallbackRepaint.nMessage = 0;
m_csCallbackRepaint.lParam = 0;
m_csCallbackRepaint.wParam = 0;
m_csCallbackLink.hWnd = NULL;
m_csCallbackLink.nMessage = 0;
m_csCallbackLink.lParam = 0;
m_csCallbackLink.wParam = 0;
// m_clrShadow = PPHTMLDRAWER_SHADOW_COLOR;
m_hLinkCursor = NULL; // No cursor as yet
m_nHoverIndexLink = PPHTMLDRAWER_NO_HOVERLINK;
SetListOfTags();
SetListSpecChars();
SetTableOfColors();
SetDefaultCursor();
EnableEscapeSequences();
SetMaxWidth(0);
// EnableTextWrap(FALSE); //A text warpping was disabled by default
// EnableTextWrap(TRUE); //A text warpping was disabled by default
SetImageShadow(4, 4);
SetTabSize(32);
SetDefaultCssStyles();
EnableOutput();
SetDisabledColor(::GetSysColor(COLOR_BTNSHADOW));
}
CPPHtmlDrawer::~CPPHtmlDrawer()
{
SetResourceDll(NULL);
if (NULL != m_hLinkCursor)
{
::DestroyCursor(m_hLinkCursor);
m_hLinkCursor = NULL;
}
if (NULL != m_hImageList)
::DeleteObject(m_hImageList);
}
void CPPHtmlDrawer::EnableOutput(BOOL bEnable /* = TRUE */)
{
m_bIsEnable = bEnable;
} //End of EnableOutput
void CPPHtmlDrawer::SetDisabledColor(COLORREF color)
{
m_crDisabled = color;
}
HICON CPPHtmlDrawer::GetIconFromResources(DWORD dwID, int nWidth /* = 0 */, int nHeight /* = 0 */) const
{
if (0 == dwID) return NULL;
// Find correct resource handle
#ifdef _MFC_VER
HINSTANCE hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(dwID), RT_GROUP_ICON);
#else
HINSTANCE hInstResource = ::GetModuleHandle(NULL);
#endif
// Set icon when the mouse is IN the button
HICON hIcon = (HICON)::LoadImage(hInstResource, MAKEINTRESOURCE(dwID), IMAGE_ICON, nWidth, nHeight, LR_DEFAULTCOLOR);
return hIcon;
}
HICON CPPHtmlDrawer::GetIconFromFile(LPCTSTR lpszPath, int nWidth /* = 0 */, int nHeight /* = 0 */) const
{
HICON hIcon = (HICON)::LoadImage(NULL, lpszPath, IMAGE_ICON, nWidth, nHeight, LR_LOADFROMFILE | LR_DEFAULTCOLOR);
return hIcon;
}
HICON CPPHtmlDrawer::GetIconFromDll(DWORD dwID, int nWidth /* = 0 */, int nHeight /* = 0 */, LPCTSTR lpszPathDll /* = NULL */) const
{
if (0 == dwID) return NULL;
HICON hIcon = NULL;
HINSTANCE hInstDll = NULL;
BOOL bNewDll = FALSE;
if (NULL == lpszPathDll)
{
if (NULL != m_hInstDll)
hInstDll = m_hInstDll;
}
else
{
//Load New Library
hInstDll = ::LoadLibraryEx(lpszPathDll, NULL, 0);
if (NULL != hInstDll)
bNewDll = TRUE;
}
if (NULL != hInstDll)
{
hIcon = (HICON)::LoadImage(hInstDll, MAKEINTRESOURCE(dwID), IMAGE_ICON, nWidth, nHeight, LR_DEFAULTCOLOR);
if (bNewDll)
::FreeLibrary(hInstDll);
}
return hIcon;
}
HBITMAP CPPHtmlDrawer::GetBitmapFromResources(DWORD dwID) const
{
if (0 == dwID) return NULL;
// Find correct resource handle
#ifdef _MFC_VER
HINSTANCE hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(dwID), RT_BITMAP);
#else
HINSTANCE hInstResource = ::GetModuleHandle(NULL);
#endif
// Load bitmap
HBITMAP hBitmap = (HBITMAP)::LoadImage(hInstResource, MAKEINTRESOURCE(dwID), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
return hBitmap;
}
HBITMAP CPPHtmlDrawer::GetBitmapFromFile(LPCTSTR lpszPath) const
{
HBITMAP hBitmap = (HBITMAP)::LoadImage(NULL, lpszPath, IMAGE_BITMAP,
0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
return hBitmap;
}
HBITMAP CPPHtmlDrawer::GetBitmapFromDll(DWORD dwID, LPCTSTR lpszPathDll /* = NULL */) const
{
if (0 == dwID) return NULL;
HBITMAP hBitmap = NULL;
HINSTANCE hInstDll = NULL;
BOOL bNewDll = FALSE;
if (NULL == lpszPathDll)
{
if (NULL != m_hInstDll)
hInstDll = m_hInstDll;
}
else
{
//Load New Library
hInstDll = ::LoadLibraryEx(lpszPathDll, NULL, 0);
if (NULL != hInstDll)
bNewDll = TRUE;
}
if (NULL != hInstDll)
{
hBitmap = (HBITMAP)::LoadImage(hInstDll, MAKEINTRESOURCE(dwID), IMAGE_BITMAP,
0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
if (bNewDll)
::FreeLibrary(hInstDll);
}
return hBitmap;
}
CPPString CPPHtmlDrawer::GetStringFromResource(DWORD dwID) const
{
if (0 == dwID) return _T("");
CPPString str;
str.LoadString(dwID);
return str;
}
CPPString CPPHtmlDrawer::GetStringFromDll(DWORD dwID, LPCTSTR lpszPathDll /* = NULL */) const
{
if (0 == dwID) return _T("");
CPPString str = _T("");
HINSTANCE hInstDll = NULL;
BOOL bNewDll = FALSE;
if (NULL == lpszPathDll)
{
if (NULL != m_hInstDll)
hInstDll = m_hInstDll;
}
else
{
//Load New Library
hInstDll = ::LoadLibraryEx(lpszPathDll, NULL, 0);
if (NULL != hInstDll)
bNewDll = TRUE;
}
if (NULL != hInstDll)
{
#ifdef _UNICODE
#define CHAR_FUDGE 1 // one TCHAR unused is good enough
#else
#define CHAR_FUDGE 2 // two BYTES unused for case of DBC last char
#endif
// try fixed buffer first (to avoid wasting space in the heap)
TCHAR szTemp[256];
DWORD dwLen = ::LoadString(hInstDll, dwID, szTemp, (sizeof(szTemp) * sizeof(TCHAR)));
// If resource not found (or ::LoadString failure)
if (0 != dwLen)
{
if ((sizeof(szTemp) * sizeof(TCHAR)) - dwLen > CHAR_FUDGE)
{
str = szTemp;
} // if
else
{
// try buffer size of 512, then larger size until entire string is retrieved
int nSize = 256;
do
{
nSize += 256;
dwLen = ::LoadString(hInstDll, dwID, str.GetBuffer(nSize-1), nSize);
} while (nSize - dwLen <= CHAR_FUDGE);
str.ReleaseBuffer();
}
#undef CHAR_FUDGE
}
if (bNewDll)
::FreeLibrary(hInstDll);
}
return str;
}
///////////////////////////////////////////////////////////
// Get tooltip string for menu and toolbar items from the
// resources of the application.
//
// Parameters:
// nID - Resource ID of the string
// nNumParam - Which parameter will gets:
// 0=long,
// 1=short,
// 2=disable
//
//
// Format prompt string: long prompt \n short prompt \n disable prompt
////////////////////////////////////////////////////////////
CPPString CPPHtmlDrawer::GetResCommandPrompt(UINT nID, UINT nNumParam /* = 0 */)
{
CPPString str = GetStringFromResource(nID);
if (!str.IsEmpty())
{
int nFirst = 0;
int nLast = nFirst;
UINT nCount = 0;
while ((nCount <= nNumParam) && (nFirst < str.GetLength()))
{
nLast = str.Find(_T('\n'), nFirst);
if (nLast < 0)
{
//Char wasn't found
if (nCount == nNumParam)
str = str.Mid(nFirst, str.GetLength() - nFirst);
else
str.Empty();
return str;
}
else
{
//Char was found
if (nCount == nNumParam)
{
str = str.Mid(nFirst, nLast - nFirst);
return str;
}
else
{
nFirst = nLast + 1;
} //if
} //if
nCount ++;
} //while
} //if
return _T("");
} //End of GetResCommandPrompt
/////////////////////////////////////////////////////////////////////////////
//
void CPPHtmlDrawer::SetListSpecChars()
{
AddSpecChar(_T("&"), _T("&")); // ampersand
AddSpecChar(_T("•"), _T("\x95\0")); // bullet NOT IN MS SANS SERIF
AddSpecChar(_T("©"), _T("\xA9\0")); // copyright
// AddSpecChar(_T("€"), _T("\x80\0")); // euro sign IN NOT CYRILLIC FONTS
AddSpecChar(_T("€"), _T("\x88\0")); // euro sign IN CYRILLIC FONTS
AddSpecChar(_T(">"), _T(">")); // greater than
AddSpecChar(_T("¿"), _T("\xBF\0")); // inverted question mark
AddSpecChar(_T("<"), _T("<<")); // less than
AddSpecChar(_T(" "), _T(" ")); // nonbreaking space
AddSpecChar(_T("¶"), _T("\xB6\0")); // paragraph sign
AddSpecChar(_T("£"), _T("\xA3\0")); // pound sign
AddSpecChar(_T("""), _T("\"")); // quotation mark
AddSpecChar(_T("®"), _T("\xAE\0")); // registered trademark
AddSpecChar(_T("™"), _T("\x99\0")); // trademark NOT IN MS SANS SERIF
} //End of SetListSpecChars
void CPPHtmlDrawer::AddSpecChar(LPCTSTR lpszAlias, LPCTSTR lpszValue)
{
iter_mapStyles iter = m_mapSpecChars.find(lpszAlias);
if (iter != m_mapSpecChars.end())
iter->second = lpszValue; //Modifies
else
m_mapSpecChars.insert(std::make_pair(lpszAlias, lpszValue)); //Add new
} //End of AddSpecialChar
void CPPHtmlDrawer::ReplaceSpecChars()
{
CPPString sAlias, sValue;
for (iter_mapStyles iter = m_mapSpecChars.begin(); iter != m_mapSpecChars.end(); ++iter)
{
sAlias = iter->first;
sValue = iter->second;
m_csHtmlText.Replace(sAlias, sValue);
} //for
m_csHtmlText.Remove(_T('\r'));
if (!m_bEnableEscapeSequences)
{
//ENG: Remove escape sequences
//RUS: ������� ����������� �������
m_csHtmlText.Remove(_T('\n'));
m_csHtmlText.Remove(_T('\t'));
}
else
{
//ENG: Replace escape sequences to HTML tags
//RUS: �������� ����������� ������� HTML ������
m_csHtmlText.Replace(_T("\n"), _T("<br>"));
m_csHtmlText.Replace(_T("\t"), _T("<t>"));
} //if
} //End of ReplaceSpecChars
/////////////////////////////////////////////////////////////////////////////
//
void CPPHtmlDrawer::SetListOfTags()
{
AddTagToList(_T("b"), TAG_BOLD, _T("bold"));
AddTagToList(_T("i"), TAG_ITALIC, _T("italic"));
AddTagToList(_T("em"), TAG_ITALIC, _T("italic"));
AddTagToList(_T("u"), TAG_UNDERLINE, _T("underline"));
AddTagToList(_T("s"), TAG_STRIKEOUT, _T("strikeout"));
AddTagToList(_T("strike"), TAG_STRIKEOUT, _T("strikeout"));
AddTagToList(_T("font"), TAG_FONT, _T("font"));
AddTagToList(_T("hr"), TAG_HLINE, _T(""));
AddTagToList(_T("br"), TAG_NEWLINE, _T(""));
AddTagToList(_T("\n"), TAG_NEWLINE, _T(""));
AddTagToList(_T("t"), TAG_TABULATION, _T(""));
AddTagToList(_T("\t"), TAG_TABULATION, _T(""));
AddTagToList(_T("left"), TAG_LEFT, _T("left"));
AddTagToList(_T("center"), TAG_CENTER, _T("center"));
AddTagToList(_T("right"), TAG_RIGHT, _T("right"));
AddTagToList(_T("justify"), TAG_JUSTIFY, _T("justify"));
AddTagToList(_T("baseline"), TAG_BASELINE, _T("baseline"));
AddTagToList(_T("top"), TAG_TOP, _T("top"));
AddTagToList(_T("vcenter"), TAG_VCENTER, _T("vcenter"));
AddTagToList(_T("middle"), TAG_VCENTER, _T("vcenter"));
AddTagToList(_T("bottom"), TAG_BOTTOM, _T("vcenter"));
AddTagToList(_T("bmp"), TAG_BITMAP, _T(""));
AddTagToList(_T("icon"), TAG_ICON, _T(""));
AddTagToList(_T("ilst"), TAG_IMAGELIST, _T(""));
AddTagToList(_T("string"), TAG_STRING, _T(""));
AddTagToList(_T("body"), TAG_NEWSTYLE, _T("body"));
AddTagToList(_T("h1"), TAG_NEWSTYLE, _T("h1"));
AddTagToList(_T("h2"), TAG_NEWSTYLE, _T("h2"));
AddTagToList(_T("h3"), TAG_NEWSTYLE, _T("h3"));
AddTagToList(_T("h4"), TAG_NEWSTYLE, _T("h4"));
AddTagToList(_T("h5"), TAG_NEWSTYLE, _T("h5"));
AddTagToList(_T("h6"), TAG_NEWSTYLE, _T("h6"));
AddTagToList(_T("code"), TAG_NEWSTYLE, _T("code"));
AddTagToList(_T("pre"), TAG_NEWSTYLE, _T("pre"));
AddTagToList(_T("big"), TAG_NEWSTYLE, _T("big"));
AddTagToList(_T("small"), TAG_NEWSTYLE, _T("small"));
AddTagToList(_T("sub"), TAG_NEWSTYLE, _T("sub"));
AddTagToList(_T("sup"), TAG_NEWSTYLE, _T("sup"));
AddTagToList(_T("span"), TAG_SPAN, _T("span"));
AddTagToList(_T("a"), TAG_HYPERLINK, _T("link"));
} //End of SetListOfTags
////////////////////////////////////////////////////////////////////////
// Format for the new tags:
// lpszName - a tag's name in the HTML string
// dwTagIndex - ID of the tag
// lpszFullName - a custom name if tag must be closing. Empty if not.
////////////////////////////////////////////////////////////////////////
void CPPHtmlDrawer::AddTagToList(LPCTSTR lpszName, DWORD dwTagIndex, LPCTSTR lpszFullName)
{
STRUCT_TAGPROP tp;
tp.dwTagIndex = dwTagIndex;
tp.strTagName = lpszFullName;
iterMapTags iterMap = m_mapTags.find(lpszName);
if (iterMap != m_mapTags.end())
iterMap->second = tp; //Modifies
else
m_mapTags.insert(std::make_pair(lpszName, tp)); //Add new
} //End of AddTagToList
DWORD CPPHtmlDrawer::GetTagFromList(CPPString sTagName, CPPString & strFullName, BOOL & bCloseTag)
{
strFullName.Empty();
bCloseTag = (sTagName.GetAt(0) == _T('/')) ? TRUE : FALSE;
if (bCloseTag)
sTagName = sTagName.Mid(1);
iterMapTags iterMap = m_mapTags.find(sTagName);
if (iterMap != m_mapTags.end())
{
STRUCT_TAGPROP tp = iterMap->second;
strFullName = tp.strTagName;
return tp.dwTagIndex;
} //if
return TAG_NONE;
} //End of GetTagFromList
///////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////
void CPPHtmlDrawer::SetTableOfColors()
{
//Frequency used
SetColorName(_T("aqua"), RGB(0x00, 0xFF, 0xFF));
SetColorName(_T("black"), RGB(0x00, 0x00, 0x00));
SetColorName(_T("blue"), RGB(0x00, 0x00, 0xFF));
SetColorName(_T("brown"), RGB(0xA5, 0x2A, 0x2A));
SetColorName(_T("cyan"), RGB(0x00, 0xFF, 0xFF));
SetColorName(_T("gold"), RGB(0xFF, 0xD7, 0x00));
SetColorName(_T("gray"), RGB(0x80, 0x80, 0x80));
SetColorName(_T("green"), RGB(0x00, 0x80, 0x00));
SetColorName(_T("magenta"), RGB(0xFF, 0x00, 0xFF));
SetColorName(_T("maroon"), RGB(0x80, 0x00, 0x00));
SetColorName(_T("navy"), RGB(0x00, 0x00, 0x80));
SetColorName(_T("olive"), RGB(0x80, 0x80, 0x00));
SetColorName(_T("orange"), RGB(0xFF, 0xA5, 0x00));
SetColorName(_T("pink"), RGB(0xFF, 0xC0, 0xCB));
SetColorName(_T("purple"), RGB(0x80, 0x00, 0x80));
SetColorName(_T("red"), RGB(0xFF, 0x00, 0x00));
SetColorName(_T("silver"), RGB(0xC0, 0xC0, 0xC0));
SetColorName(_T("snow"), RGB(0xFF, 0xFA, 0xFA));
SetColorName(_T("violet"), RGB(0xEE, 0x82, 0xEE));
SetColorName(_T("white"), RGB(0xFF, 0xFF, 0xFF));
SetColorName(_T("yellow"), RGB(0xFF, 0xFF, 0x00));
//Common Used
SetColorName(_T("aliceblue"), RGB(0xF0, 0xF8, 0xFF));
SetColorName(_T("antiquewhite"), RGB(0xFA, 0xEB, 0xD7));
SetColorName(_T("aquamarine"), RGB(0x7F, 0xFF, 0xD4));
SetColorName(_T("azure"), RGB(0xF0, 0xFF, 0xFF));
SetColorName(_T("beige"), RGB(0xF5, 0xF5, 0xDC));
SetColorName(_T("bisque"), RGB(0xFF, 0xE4, 0xC4));
SetColorName(_T("blanchedalmond"), RGB(0xFF, 0xEB, 0xCD));
SetColorName(_T("blueviolet"), RGB(0x8A, 0x2B, 0xE2));
SetColorName(_T("burlywood"), RGB(0xDE, 0xB8, 0x87));
SetColorName(_T("cadetblue"), RGB(0x5F, 0x9E, 0xA0));
SetColorName(_T("chartreuse"), RGB(0x7F, 0xFF, 0x00));
SetColorName(_T("chocolate"), RGB(0xD2, 0x69, 0x1E));
SetColorName(_T("coral"), RGB(0xFF, 0x7F, 0x50));
SetColorName(_T("cornflowerblue"), RGB(0x64, 0x95, 0xED));
SetColorName(_T("cornsilk"), RGB(0xFF, 0xF8, 0xDC));
SetColorName(_T("crimson"), RGB(0xDC, 0x14, 0x3C));
SetColorName(_T("darkblue"), RGB(0x00, 0x00, 0x8B));
SetColorName(_T("darkcyan"), RGB(0x00, 0x8B, 0x8B));
SetColorName(_T("darkgoldenrod"), RGB(0xB8, 0x86, 0x0B));
SetColorName(_T("darkgray"), RGB(0xA9, 0xA9, 0xA9));
SetColorName(_T("darkgreen"), RGB(0x00, 0x64, 0x00));
SetColorName(_T("darkkhaki"), RGB(0xBD, 0xB7, 0x6B));
SetColorName(_T("darkmagenta"), RGB(0x8B, 0x00, 0x8B));
SetColorName(_T("darkolivegreen"), RGB(0x55, 0x6B, 0x2F));
SetColorName(_T("darkorange"), RGB(0xFF, 0x8C, 0x00));
SetColorName(_T("darkorchid"), RGB(0x99, 0x32, 0xCC));
SetColorName(_T("darkred"), RGB(0x8B, 0x00, 0x00));
SetColorName(_T("darksalmon"), RGB(0xE9, 0x96, 0x7A));
SetColorName(_T("darkseagreen"), RGB(0x8F, 0xBC, 0x8B));
SetColorName(_T("darkslateblue"), RGB(0x48, 0x3D, 0x8B));
SetColorName(_T("darkslategray"), RGB(0x2F, 0x4F, 0x4F));
SetColorName(_T("darkturquoise"), RGB(0x00, 0xCE, 0xD1));
SetColorName(_T("darkviolet"), RGB(0x94, 0x00, 0xD3));
SetColorName(_T("deeppink"), RGB(0xFF, 0x14, 0x93));
SetColorName(_T("deepskyblue"), RGB(0x00, 0xBF, 0xFF));
SetColorName(_T("dimgray"), RGB(0x69, 0x69, 0x69));
SetColorName(_T("dodgerblue"), RGB(0x1E, 0x90, 0xFF));
SetColorName(_T("firebrick"), RGB(0xB2, 0x22, 0x22));
SetColorName(_T("floralwhite"), RGB(0xFF, 0xFA, 0xF0));
SetColorName(_T("forestgreen"), RGB(0x22, 0x8B, 0x22));
SetColorName(_T("fuchsia"), RGB(0xFF, 0x00, 0xFF));
SetColorName(_T("gainsboro"), RGB(0xDC, 0xDC, 0xDC));
SetColorName(_T("ghostwhite"), RGB(0xF8, 0xF8, 0xFF));
SetColorName(_T("goldenrod"), RGB(0xDA, 0xA5, 0x20));
SetColorName(_T("greenyellow"), RGB(0xAD, 0xFF, 0x2F));
SetColorName(_T("honeydew"), RGB(0xF0, 0xFF, 0xF0));
SetColorName(_T("hotpink"), RGB(0xFF, 0x69, 0xB4));
SetColorName(_T("indianred"), RGB(0xCD, 0x5C, 0x5C));
SetColorName(_T("indigo"), RGB(0x4B, 0x00, 0x82));
SetColorName(_T("ivory"), RGB(0xFF, 0xFF, 0xF0));
SetColorName(_T("khaki"), RGB(0xF0, 0xE6, 0x8C));
SetColorName(_T("lavender"), RGB(0xE6, 0xE6, 0xFA));
SetColorName(_T("lavenderblush"), RGB(0xFF, 0xF0, 0xF5));
SetColorName(_T("lawngreen"), RGB(0x7C, 0xFC, 0x00));
SetColorName(_T("lemonchiffon"), RGB(0xFF, 0xFA, 0xCD));
SetColorName(_T("lightblue"), RGB(0xAD, 0xD8, 0xE6));
SetColorName(_T("lightcoral"), RGB(0xF0, 0x80, 0x80));
SetColorName(_T("lightcyan"), RGB(0xE0, 0xFF, 0xFF));
SetColorName(_T("lightgoldenrodyellow"), RGB(0xFA, 0xFA, 0xD2));
SetColorName(_T("lightgreen"), RGB(0x90, 0xEE, 0x90));
SetColorName(_T("lightgrey"), RGB(0xD3, 0xD3, 0xD3));
SetColorName(_T("lightpink"), RGB(0xFF, 0xB6, 0xC1));
SetColorName(_T("lightsalmon"), RGB(0xFF, 0xA0, 0x7A));
SetColorName(_T("lightseagreen"), RGB(0x20, 0xB2, 0xAA));
SetColorName(_T("lightskyblue"), RGB(0x87, 0xCE, 0xFA));
SetColorName(_T("lightslategray"), RGB(0x77, 0x88, 0x99));
SetColorName(_T("lightsteelblue"), RGB(0xB0, 0xC4, 0xDE));
SetColorName(_T("lightyellow"), RGB(0xFF, 0xFF, 0xE0));
SetColorName(_T("lime"), RGB(0x00, 0xFF, 0x00));
SetColorName(_T("limegreen"), RGB(0x32, 0xCD, 0x32));
SetColorName(_T("linen"), RGB(0xFA, 0xF0, 0xE6));
SetColorName(_T("mediumaquamarine"), RGB(0x66, 0xCD, 0xAA));
SetColorName(_T("mediumblue"), RGB(0x00, 0x00, 0xCD));
SetColorName(_T("mediumorchid"), RGB(0xBA, 0x55, 0xD3));
SetColorName(_T("mediumpurple"), RGB(0x93, 0x70, 0xDB));
SetColorName(_T("mediumseagreen"), RGB(0x3C, 0xB3, 0x71));
SetColorName(_T("mediumslateblue"), RGB(0x7B, 0x68, 0xEE));
SetColorName(_T("mediumspringgreen"), RGB(0x00, 0xFA, 0x9A));
SetColorName(_T("mediumturquoise"), RGB(0x48, 0xD1, 0xCC));
SetColorName(_T("mediumvioletred"), RGB(0xC7, 0x15, 0x85));
SetColorName(_T("midnightblue"), RGB(0x19, 0x19, 0x70));
SetColorName(_T("mintcream"), RGB(0xF5, 0xFF, 0xFA));
SetColorName(_T("mistyrose"), RGB(0xFF, 0xE4, 0xE1));
SetColorName(_T("moccasin"), RGB(0xFF, 0xE4, 0xB5));
SetColorName(_T("navajowhite"), RGB(0xFF, 0xDE, 0xAD));
SetColorName(_T("oldlace"), RGB(0xFD, 0xF5, 0xE6));
SetColorName(_T("olivedrab"), RGB(0x6B, 0x8E, 0x23));
SetColorName(_T("orangered"), RGB(0xFF, 0x45, 0x00));
SetColorName(_T("orchid"), RGB(0xDA, 0x70, 0xD6));
SetColorName(_T("palegoldenrod"), RGB(0xEE, 0xE8, 0xAA));
SetColorName(_T("palegreen"), RGB(0x98, 0xFB, 0x98));
SetColorName(_T("paleturquoise"), RGB(0xAF, 0xEE, 0xEE));
SetColorName(_T("palevioletred"), RGB(0xDB, 0x70, 0x93));
SetColorName(_T("papayawhip"), RGB(0xFF, 0xEF, 0xD5));
SetColorName(_T("peachpuff"), RGB(0xFF, 0xDA, 0xB9));
SetColorName(_T("peru"), RGB(0xCD, 0x85, 0x3F));
SetColorName(_T("plum"), RGB(0xDD, 0xA0, 0xDD));
SetColorName(_T("powderblue"), RGB(0xB0, 0xE0, 0xE6));
SetColorName(_T("rosybrown"), RGB(0xBC, 0x8F, 0x8F));
SetColorName(_T("royalblue"), RGB(0x41, 0x69, 0xE1));
SetColorName(_T("saddlebrown"), RGB(0x8B, 0x45, 0x13));
SetColorName(_T("salmon"), RGB(0xFA, 0x80, 0x72));
SetColorName(_T("sandybrown"), RGB(0xF4, 0xA4, 0x60));
SetColorName(_T("seagreen"), RGB(0x2E, 0x8B, 0x57));
SetColorName(_T("seashell"), RGB(0xFF, 0xF5, 0xEE));
SetColorName(_T("sienna"), RGB(0xA0, 0x52, 0x2D));
SetColorName(_T("skyblue"), RGB(0x87, 0xCE, 0xEB));
SetColorName(_T("slateblue"), RGB(0x6A, 0x5A, 0xCD));
SetColorName(_T("slategray"), RGB(0x70, 0x80, 0x90));
SetColorName(_T("springgreen"), RGB(0x00, 0xFF, 0x7F));
SetColorName(_T("steelblue"), RGB(0x46, 0x82, 0xB4));
SetColorName(_T("tan"), RGB(0xD2, 0xB4, 0x8C));
SetColorName(_T("teal"), RGB(0x00, 0x80, 0x80));
SetColorName(_T("thistle"), RGB(0xD8, 0xBF, 0xD8));
SetColorName(_T("tomato"), RGB(0xFF, 0x63, 0x47));
SetColorName(_T("turquoise"), RGB(0x40, 0xE0, 0xD0));
SetColorName(_T("wheat"), RGB(0xF5, 0xDE, 0xB3));
SetColorName(_T("whitesmoke"), RGB(0xF5, 0xF5, 0xF5));
SetColorName(_T("yellowgreen"), RGB(0x9A, 0xCD, 0x32));
//Systems colors
SetColorName(_T("activeborder"), ::GetSysColor(COLOR_ACTIVEBORDER));
SetColorName(_T("activecaption"), ::GetSysColor(COLOR_ACTIVECAPTION));
SetColorName(_T("appworkspace"), ::GetSysColor(COLOR_APPWORKSPACE));
SetColorName(_T("background"), ::GetSysColor(COLOR_BACKGROUND));
SetColorName(_T("buttonface"), ::GetSysColor(COLOR_BTNFACE));
SetColorName(_T("buttonhighlight"), ::GetSysColor(COLOR_BTNHILIGHT));
SetColorName(_T("buttonshadow"), ::GetSysColor(COLOR_BTNSHADOW));
SetColorName(_T("buttontext"), ::GetSysColor(COLOR_BTNTEXT));
SetColorName(_T("captiontext"), ::GetSysColor(COLOR_CAPTIONTEXT));
SetColorName(_T("graytext"), ::GetSysColor(COLOR_GRAYTEXT));
SetColorName(_T("highlight"), ::GetSysColor(COLOR_HIGHLIGHT));
SetColorName(_T("highlighttext"), ::GetSysColor(COLOR_HIGHLIGHTTEXT));
SetColorName(_T("inactiveborder"), ::GetSysColor(COLOR_INACTIVEBORDER));
SetColorName(_T("inactivecaption"), ::GetSysColor(COLOR_INACTIVECAPTION));
SetColorName(_T("inactivecaptiontext"), ::GetSysColor(COLOR_INACTIVECAPTIONTEXT));
SetColorName(_T("infobackground"), ::GetSysColor(COLOR_INFOBK));
SetColorName(_T("infotext"), ::GetSysColor(COLOR_INFOTEXT));
SetColorName(_T("menu"), ::GetSysColor(COLOR_MENU));
SetColorName(_T("menutext"), ::GetSysColor(COLOR_MENUTEXT));
SetColorName(_T("scrollbar"), ::GetSysColor(COLOR_SCROLLBAR));
SetColorName(_T("threeddarkshadow"), ::GetSysColor(COLOR_3DDKSHADOW));
SetColorName(_T("threedface"), ::GetSysColor(COLOR_3DFACE));
SetColorName(_T("threedhighlight"), ::GetSysColor(COLOR_3DHIGHLIGHT));
SetColorName(_T("threedlightshadow"), ::GetSysColor(COLOR_3DLIGHT));
SetColorName(_T("threedshadow"), ::GetSysColor(COLOR_3DSHADOW));
SetColorName(_T("window"), ::GetSysColor(COLOR_WINDOW));
SetColorName(_T("windowframe"), ::GetSysColor(COLOR_WINDOWFRAME));
SetColorName(_T("windowtext"), ::GetSysColor(COLOR_WINDOWTEXT));
} //End SetTableOfColors
void CPPHtmlDrawer::SetColorName(LPCTSTR lpszColorName, COLORREF color)
{
iterMapColors iterMap = m_mapColors.find(lpszColorName);
if (iterMap != m_mapColors.end())
iterMap->second = color; //Modifies
else
m_mapColors.insert(std::make_pair(lpszColorName, color)); //Add new
} //End SetColorName
COLORREF CPPHtmlDrawer::GetColorByName(LPCTSTR lpszColorName, COLORREF crDefColor /* = RGB(0, 0, 0) */)
{
if (m_bIsEnable)
{
iterMapColors iterMap = m_mapColors.find(lpszColorName);
if (iterMap != m_mapColors.end())
crDefColor = iterMap->second;
}
else
{
//For disabled output
crDefColor = m_crDisabled;
} //if
return crDefColor;
} //End GetColorByName
/////////////////////////////////////////////////////////////////
// Gets the system tooltip's logfont
/////////////////////////////////////////////////////////////////
LPLOGFONT CPPHtmlDrawer::GetSystemToolTipFont() const
{
static LOGFONT lf;
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0))
return FALSE;
memcpy(&lf, &(ncm.lfStatusFont), sizeof(LOGFONT));
return &lf;
} //End GetSystemToolTipFont
////////////////////////////////////////////
// Check a pointer over the hyperlink
// In: lpPoint - the coordinates of the mouse pointer
// Out: -1 - hyperlink not found
// index of the hyperlink
////////////////////////////////////////////
int CPPHtmlDrawer::PtInHyperlink(LPPOINT lpPoint)
{
for (UINT i = 0; i < m_arrLinks.size(); ++i)
{
STRUCT_HYPERLINK & link = m_arrLinks [i];
if ((link.rcArea.left <= lpPoint->x) && (link.rcArea.right >= lpPoint->x) &&
(link.rcArea.top <= lpPoint->y) && (link.rcArea.bottom >= lpPoint->y))
return i;
} //for
return -1;
} //End PtInHyperlink
void CPPHtmlDrawer::JumpToHyperlink(int nLink)
{
STRUCT_HYPERLINK & link = m_arrLinks [nLink];
// TRACE(_T("Jump to Hyperlink number = %d\n"), nLink);
if (!link.sHyperlink.IsEmpty())
{
switch (link.nTypeLink)
{
case LINK_HREF:
GotoURL(link.sHyperlink);
break;
case LINK_MESSAGE:
CallbackOnClickHyperlink(link.sHyperlink);
break;
} //switch
} //if
} //End JumpToHyperlink
void CPPHtmlDrawer::OnLButtonDown(LPPOINT lpClient)
{
// TRACE (_T("CPPHtmlDrawer::OnLButtonDown()\n"));
int nLink = PtInHyperlink(lpClient);
if (nLink >= 0)
{
//Hyperlink under the mouse pointer
JumpToHyperlink(nLink);
} //if
} //End OnLButtonDown
BOOL CPPHtmlDrawer::OnSetCursor(LPPOINT lpClient)
{
int nLink = PtInHyperlink(lpClient);
if (nLink >= 0)
{
STRUCT_HYPERLINK link = m_arrLinks [nLink];
if (m_nHoverIndexLink != link.nIndexLink)
{
m_nHoverIndexLink = link.nIndexLink;
CallbackOnRepaint(m_nHoverIndexLink);
//Redraw Window
} //if
if (!link.sHyperlink.IsEmpty() && (NULL != m_hLinkCursor))
{
::SetCursor(m_hLinkCursor);
return TRUE;
} //if
}
else if (m_nHoverIndexLink != PPHTMLDRAWER_NO_HOVERLINK)
{
m_nHoverIndexLink = PPHTMLDRAWER_NO_HOVERLINK;
CallbackOnRepaint(m_nHoverIndexLink);
//Redraw Window
} //if
return FALSE;
} //End OnSetCursor
BOOL CPPHtmlDrawer::OnTimer()
{
BOOL bRedraw = FALSE;
if (m_arrAni.size() > 0)
{
for (UINT i = 0; i < m_arrAni.size(); ++i)
{
STRUCT_ANIMATION & sa = m_arrAni [i];
if (sa.nMaxImages > 0)
{
sa.nTimerCount ++;
if (sa.nTimerCount >= sa.nSpeed)
{
sa.nTimerCount = 0;
sa.nIndex ++;
if (sa.nIndex >= sa.nMaxImages)
sa.nIndex = 0;
bRedraw = TRUE;
} //if
m_arrAni [i] = sa;
} //if
} //for
} //if
return bRedraw;
} //End of OnTimer
void CPPHtmlDrawer::CallbackOnRepaint(int nIndexLink)
{
// TRACE(_T("CPPHtmlDrawer::CallbackOnRepaint()\n"));
if ((NULL == m_csCallbackRepaint.hWnd) || !m_csCallbackRepaint.nMessage)
return;
::SendMessage(m_csCallbackRepaint.hWnd, m_csCallbackRepaint.nMessage, (LPARAM)nIndexLink, m_csCallbackRepaint.lParam);
} //End CallbackOnRepaint
void CPPHtmlDrawer::CallbackOnClickHyperlink(LPCTSTR sLink)
{
// TRACE(_T("CPPHtmlDrawer::CallbackOnClickHyperlink()\n"));
if ((NULL == m_csCallbackLink.hWnd) || !m_csCallbackLink.nMessage)
return;
::SendMessage(m_csCallbackLink.hWnd, m_csCallbackLink.nMessage, (LPARAM)sLink, m_csCallbackLink.lParam);
} //if CallbackOnClickHyperlink
HINSTANCE CPPHtmlDrawer::GotoURL(LPCTSTR url, int showcmd /* = SW_SHOW */)
{
SetHyperlinkCursor(NULL);
TCHAR key[MAX_PATH + MAX_PATH];
// First try ShellExecute()
HINSTANCE result = ShellExecute(NULL, _T("open"), url, NULL, NULL, showcmd);
// If it failed, get the .htm regkey and lookup the program
if ((UINT)result <= HINSTANCE_ERROR)
{
if (GetRegKey(HKEY_CLASSES_ROOT, _T(".htm"), key) == ERROR_SUCCESS)
{
lstrcat(key, _T("\\shell\\open\\command"));
if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS)
{
TCHAR *pos;
pos = _tcsstr(key, _T("\"%1\""));
if (pos == NULL)
{ // No quotes found
pos = _tcsstr(key, _T("%1")); // Check for %1, without quotes
if (pos == NULL) // No parameter at all...
pos = key+lstrlen(key)-1;
else
*pos = '\0'; // Remove the parameter
}
else
*pos = '\0'; // Remove the parameter
lstrcat(pos, _T(" "));
lstrcat(pos, url);
USES_CONVERSION;
result = (HINSTANCE) WinExec(T2A(key),showcmd);
} //if
} //if
} //if
return result;
} //End GotoURL
LONG CPPHtmlDrawer::GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata)
{
HKEY hkey;
LONG retval = RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey);
if (retval == ERROR_SUCCESS) {
long datasize = MAX_PATH;
TCHAR data[MAX_PATH];
RegQueryValue(hkey, NULL, data, &datasize);
lstrcpy(retdata,data);
RegCloseKey(hkey);
} //if
return retval;
} //End GetRegKey
/////////////////////////////////////////////////////////////////
void CPPHtmlDrawer::DrawHtml (LPSIZE lpSize, LPCRECT lpRect)
{
//ENG: Bounding rectangle of a current area for output
//RUS: �������������� ������������� ��� ������� ������� ������
RECT rcArea;
rcArea.left = lpRect->left;
rcArea.right = lpRect->right;
rcArea.top = lpRect->top;
rcArea.bottom = lpRect->bottom;
SIZE szArea;
szArea.cx = szArea.cy = 0;
if (MODE_FIRSTPASS == m_nNumPass)
{
//ENG: In preparing mode clears an auxiliary tables
//RUS: � ������ ���������� ������� ��������������� �������
m_arrLinks.clear();
// m_arrTable.clear();
m_arrHtmlLine.clear();
// m_arrTableSizes.clear();
m_arrAni.clear();
} //if
m_nCurLine = 0;
m_nCurTable = -1;
m_nNumCurTable = -1;
m_nCurIndexLink = -1;
m_nCurIndexAni = -1;
//ENG: Clear stack of tags
//RUS: ������� ���� �����
m_arrStack.clear();
int nIndex = 0;
int nBegin;
CPPString strText;
//ENG: Applies a default styles
//RUS: ��������� ����� ��-���������
SetDefaultStyles(m_defStyle);
SelectNewHtmlStyle(_T("body"), m_defStyle);
//ENG: Creates a default font
//RUS: ������� ����� �� ���������
m_lfDefault.lfHeight = m_defStyle.nSizeFont;
m_lfDefault.lfWidth = 0;
m_lfDefault.lfOrientation = 0;
m_lfDefault.lfEscapement = 0;
m_lfDefault.lfWeight = m_defStyle.nWeightFont;
m_lfDefault.lfItalic = m_defStyle.bItalicFont;
m_lfDefault.lfStrikeOut = m_defStyle.bStrikeOutFont;
m_lfDefault.lfUnderline = m_defStyle.bUnderlineFont;
m_lfDefault.lfCharSet = DEFAULT_CHARSET;
m_lfDefault.lfOutPrecision = OUT_DEFAULT_PRECIS;
m_lfDefault.lfClipPrecision = CLIP_DEFAULT_PRECIS;
m_lfDefault.lfQuality = DEFAULT_QUALITY;
m_lfDefault.lfPitchAndFamily = FF_DONTCARE;
_tcscpy (m_lfDefault.lfFaceName, m_defStyle.sFaceFont);
m_hFont = ::CreateFontIndirect(&m_lfDefault);
//ENG: Remember a current context setting
//RUS: ���������� ������� ��������� �������� ����������
m_hOldFont = (HFONT)::SelectObject(m_hDC, m_hFont);
m_nOldBkMode = ::SetBkMode(m_hDC, m_defStyle.nBkMode);
m_crOldText = ::SetTextColor(m_hDC, m_defStyle.crText);
m_crOldBk = ::SetBkColor(m_hDC, m_defStyle.crBkgnd);
::GetTextMetrics(m_hDC, &m_tm);
while (nIndex < m_csHtmlText.GetLength())
{
//ENG: Searching a begin of table
//RUS: ���� ������ �������
nBegin = nIndex;
BOOL bFoundTable = SearchTag(m_csHtmlText, nIndex, _T("table"));
//ENG: Gets a text before a table
//RUS: �������� ����� �� �������
strText = m_csHtmlText.Mid(nBegin, nIndex - nBegin);
//ENG: If text before a table is exist
//RUS: ���� ����� ����� �������� ����������
if (!strText.IsEmpty())
{
//ENG: Add a tag BODY around of a output text
//RUS: ��������� ��� BODY ������ ���������� ������
// strText = _T("<body>") + strText + _T("</body>");
//ENG: Output a text before of a table
//RUS: ������� ����� ����� ��������
szArea = DrawHtmlString(strText, &rcArea);
//ENG: Updates a output area size
//RUS: ��������� ������ ������� ������
lpSize->cx = max(lpSize->cx, szArea.cx);
lpSize->cy += szArea.cy;
if (MODE_DRAW == m_nNumPass)
rcArea.top += szArea.cy;
} //if
//ENG: If table was found
//RUS: ���� ������� ���� �������
if (bFoundTable)
{
//ENG: Searching an end of the table
//RUS: ���� ��������� �������
nBegin = nIndex;
nIndex += 6;
SearchEndOfTable(m_csHtmlText, nIndex);
//ENG: Cuts a text of a table
//RUS: �������� ����� �������
strText = m_csHtmlText.Mid(nBegin, nIndex - nBegin);
//ENG: Output a table
//RUS: ����� �������
szArea = DrawHtmlTable(strText, &rcArea);
//ENG: Updates a output area size
//RUS: ��������� ������ ������� ������
lpSize->cx = max(lpSize->cx, szArea.cx);
lpSize->cy += szArea.cy;
if (MODE_DRAW == m_nNumPass)
rcArea.top += szArea.cy;
} //if
} //while
//ENG: Restore context setting
//RUS: ��������������� �������� ��������� ����������
::SetBkMode(m_hDC, m_nOldBkMode);
::SetBkColor(m_hDC, m_crOldBk);
::SetTextColor(m_hDC, m_crOldText);
::SelectObject(m_hDC, m_hOldFont);
//ENG: Clear stack of tags
//RUS: ������� ���� �����
m_arrStack.clear();
//ENG: Delete a font
//RUS: ������� �����
::DeleteObject(m_hFont);
} //End of DrawHtml
SIZE CPPHtmlDrawer::DrawHtmlTable (CPPString & sTable, LPCRECT lpRect)
{
//ENG: Jump to the next table
//RUS: �������� ����� �������
m_nCurTable++;
int i;
UINT pos;
SIZE size = {0, 0};
SIZE szTable;
RECT rcTable = {0, 0, 0, 0};
RECT rcRow;
if (MODE_FIRSTPASS == m_nNumPass)
{
//ENG: Get size of the table
//RUS: �������� ������� �������
szTable = GetTableDimensions(sTable);
STRUCT_TABLE st;
STRUCT_CELL sc;
sc.nRowSpan = 0;
sc.nColSpan = 0;
// sc.bHeightPercent = FALSE;
// sc.bWidthPercent = FALSE;
// sc.nHeight = 0;
// sc.nWidth = 0;
sc.szText.cx = sc.szText.cy = sc.szCell.cx = sc.szCell.cy = 0;
sc.bFixedWidth = FALSE;
//ENG: Creates a template of an empty table
//RUS: ������� ������ ������ �������
vecRow rows;
for (i = 0; i < szTable.cx; i++)
{
rows.push_back(sc);
st.width.push_back(0);
st.fixed_width.push_back(FALSE);
} //for
for (i = 0; i < szTable.cy; i++)
{
st.cells.push_back(rows);
st.height.push_back(0);
} //for
//ENG: Add a new table
//RUS: ��������� ����� �������
m_arrTables.push_back(st);
} //if
//ENG: Gets an info about a current table
//RUS: ����� ���������� � ������� �������
int nIndexTable = m_nCurTable;
STRUCT_TABLE cur_table = m_arrTables [nIndexTable];
szTable.cx = cur_table.width.size();
szTable.cy = cur_table.height.size();
//ENG: Applies styles of <table> tag
//RUS: ��������� ����� ������� (��� <table>)
m_defStyle.strTag = _T("table");
StoreRestoreStyle(FALSE);
SelectNewHtmlStyle(m_defStyle.strTag, m_defStyle);
//ENG: Passes a tag body and get a properties of the tag
//RUS: ���������� ��� ������ ������ � �������� ������ ������� ����
int nIndex = 0;
CPPString sTag;
SearchNextTag(sTable, sTag, nIndex);
CPPString sProperties = SplitTag(sTag);
//ENG: Analyses a properties of the tag
//RUS: ����������� �������� ����
AnalyseCellParam(sProperties, m_defStyle, TRUE);
UpdateContext();
if (MODE_FIRSTPASS != m_nNumPass)
{
//ENG: Gets a real size of the table
//RUS: �������� �������� ������� �������
rcTable.left = lpRect->left;
rcTable.top = rcTable.bottom = lpRect->top;
int nWidthTable = m_defStyle.nPadding + cur_table.width.size() - 1;
for (pos = 0; pos < cur_table.width.size(); ++pos)
nWidthTable += cur_table.width [pos] + m_defStyle.nPadding;
rcTable.bottom += m_defStyle.nPadding + cur_table.height.size() - 1;
for (pos = 0; pos < cur_table.height.size(); ++pos)
rcTable.bottom += cur_table.height [pos] + m_defStyle.nPadding;
if (CPPDrawManager::PEN_DOUBLE == m_defStyle.nBorderStyle)
{
nWidthTable += 6;
rcTable.bottom += 6;
}
else
{
nWidthTable += m_defStyle.nBorderWidth * 2;
rcTable.bottom += m_defStyle.nBorderWidth * 2;
} //if
//ENG: Horizontal align of the table
//RUS: ������������ ������� �� �����������
int nRealWidth = lpRect->right - lpRect->left;
if (nWidthTable < nRealWidth)
{
//RUS: ���������� ��������� ������� �� ��� ��������� �������
int nDelta = nRealWidth - nWidthTable;
int nNotFixedColumns = 0;
for (pos = 0; pos < cur_table.fixed_width.size(); ++pos)
{
if (!cur_table.fixed_width [pos])
nNotFixedColumns++;
} //for
for (pos = 0; (pos < cur_table.fixed_width.size()) && (nNotFixedColumns > 0); ++pos)
{
if (!cur_table.fixed_width [pos])
{
int nStep = nDelta / nNotFixedColumns;
cur_table.width [pos] += nStep;
nDelta -= nStep;
nNotFixedColumns--;
nWidthTable += nStep;
} //if
} //for
} //if
if (nWidthTable < nRealWidth)
{
switch (m_defStyle.nHorzAlign)
{
case ALIGN_RIGHT:
rcTable.left = lpRect->right - nWidthTable;
break;
case ALIGN_CENTER:
rcTable.left += (nRealWidth - nWidthTable) / 2;
break;
} //switch
} //if
rcTable.right = rcTable.left + nWidthTable;
//Calculate the real column's width and row's height
// if (CPPDrawManager::PEN_DOUBLE == m_defStyle.nBorderStyle)
// rcTable.bottom += m_defStyle.nBorderWidth * 6;
// else
// rcTable.bottom += m_defStyle.nBorderWidth * 2;
} //if
//Draw table border
if (MODE_DRAW == m_nNumPass)
{
if (m_defStyle.nFillBkgnd >= 0)
{
m_drawmanager.FillEffect(m_hDC, m_defStyle.nFillBkgnd, &rcTable,
m_defStyle.crBkgnd, m_defStyle.crMidBkgnd, m_defStyle.crEndBkgnd,
5);
}
else if (!m_defStyle.strNameResBk.IsEmpty())
{
DrawBackgroundImage(m_hDC, rcTable.left, rcTable.top, rcTable.right - rcTable.left, rcTable.bottom - rcTable.top, m_defStyle.strNameResBk);
} //if
if (m_defStyle.nBorderWidth > 0)
{
if (m_bIsEnable)
{
m_drawmanager.DrawRectangle(m_hDC, &rcTable, m_defStyle.crBorderLight, m_defStyle.crBorderDark,
m_defStyle.nBorderStyle, m_defStyle.nBorderWidth);
}
else
{
m_drawmanager.DrawRectangle(m_hDC, &rcTable, m_crDisabled, m_crDisabled,
m_defStyle.nBorderStyle, m_defStyle.nBorderWidth);
} //if
} //if
} //if
rcRow = rcTable;
if (MODE_FIRSTPASS != m_nNumPass)
{
if (CPPDrawManager::PEN_DOUBLE == m_defStyle.nBorderStyle)
{
rcRow.left += 3;
rcRow.top += 3;
rcRow.right -= 3;
rcRow.bottom -= 3;
}
else
{
rcRow.left += m_defStyle.nBorderWidth;
rcRow.top += m_defStyle.nBorderWidth;
rcRow.right -= m_defStyle.nBorderWidth;
rcRow.bottom -= m_defStyle.nBorderWidth;
}
} //if
if (szTable.cx && szTable.cy)
{
int nNewRow = 0;
int nEndRow;
CPPString sTagName, sTagParam, sRow;
for (i = 0; i < szTable.cy; ++i)
{
//ENG: Searching a begin of the row
//RUS: ����� ������ ������
if (SearchTag(sTable, nNewRow, _T("tr")))
{
//ENG: The begin of the row was found. Searching end of the row
//RUS: ������ ������ �������. ���� ��������� ������
nEndRow = nNewRow;
SearchEndOfRow(sTable, nEndRow);
//ENG: The end of the row was found
//RUS: ��������� ������ �������
sRow = sTable.Mid(nNewRow, nEndRow - nNewRow);
//ENG: Draw a row of the table
//RUS: ������� ������ �������
DrawHtmlTableRow(sRow, &rcRow, cur_table, i);
//ENG: Jump to char after the end of the row
//RUS: ������������ �� ������, ��������� �� ���������� ������
nNewRow = nEndRow + 5;
} //if
} //for
} //if
if (MODE_DRAW != m_nNumPass)
{
//ENG: Analysing cell's width
//RUS: ������ ������ ������
for (i = 1; i <= szTable.cx; i++)
{
for (int y = 0; y < szTable.cy; y++)
{
vecRow & row = cur_table.cells [y];
for (int x = 0; x < szTable.cx; x++)
{
STRUCT_CELL & sc = row [x];
if (sc.nColSpan == i)
{
if (i == 1)
{
cur_table.width [x] = max (cur_table.width [x], sc.szCell.cx);
if (sc.bFixedWidth)
cur_table.fixed_width [x] = TRUE;
}
else
{
int span_width = 0;
for (int z = 0; z < i; z++)
{
span_width += cur_table.width [x + z];
if (sc.bFixedWidth)
cur_table.fixed_width [x + z] = TRUE;
} //for
if (span_width < sc.szText.cx)
{
int step = (sc.szCell.cx - span_width) / i;
cur_table.width [x + i - 1] += (sc.szCell.cx - span_width) % i;
for (z = 0; z < i; z++)
cur_table.width [x + z] += step;
} //if
} //if
} //if
} //for
} //for
} //for
//ENG: Analysing cell's height
//RUS: ������ ������ ������
for (i = 1; i <= szTable.cy; i++)
{
for (int y = 0; y < szTable.cy; y++)
{
vecRow & row = cur_table.cells [y];
for (int x = 0; x < szTable.cx; x++)
{
STRUCT_CELL & sc = row [x];
if (sc.nRowSpan == i)
{
if (i == 1)
cur_table.height [y] = max (cur_table.height [y], sc.szCell.cy);
else
{
int span_height = 0;
for (int z = 0; z < i; z++)
span_height += cur_table.height [y + z];
if (span_height < sc.szCell.cy)
{
int step = (sc.szCell.cy - span_height) / i;
cur_table.height [y] += (sc.szCell.cy - span_height) % i;
for (z = 0; z < i; z++)
cur_table.height [y + z] += step;
} //if
} //if
} //if
} //for
} //for
} //for
size.cx += m_defStyle.nPadding + szTable.cx - 1;
size.cy += m_defStyle.nPadding + szTable.cy - 1;
for (i = 0; i < szTable.cx; i++)
size.cx += cur_table.width [i] + m_defStyle.nPadding;
for (i = 0; i < szTable.cy; i++)
size.cy += cur_table.height [i] + m_defStyle.nPadding;
if (CPPDrawManager::PEN_DOUBLE == m_defStyle.nBorderStyle)
{
size.cx += m_defStyle.nBorderWidth * 6;
size.cy += m_defStyle.nBorderWidth * 6;
}
else
{
size.cx += m_defStyle.nBorderWidth * 2;
size.cy += m_defStyle.nBorderWidth * 2;
} //if
// size.cx = GetTableWidth(strTable, 0, size.cx, TRUE);
}
else
{
size.cx = rcTable.right - rcTable.left;
size.cy = rcTable.bottom - rcTable.top;
} //if
//ENG: Stores a current table
//RUS: ��������� ������� �������
m_arrTables [nIndexTable] = cur_table;
//ENG: Restore styles before <table> tag
//RUS: ��������������� ����� �� ���� <table>
m_defStyle.strTag = _T("table");
if (StoreRestoreStyle(TRUE))
UpdateContext();
return size;
} //End DrawHtmlTable
///////////////////////////////////////////////////////////////////////////////
// CPPHtmlDrawer::DrawHtmlTableRow
// Draw a row of the table
//-----------------------------------------------------------------------------
// Parameters:
// sRow - a text of the cell with the tags. For example: "<tr>...</tr>"
// lpRect - a bounding rectangle for the row
// st - the info about current table
// nRow - the current row of the table
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
void CPPHtmlDrawer::DrawHtmlTableRow(CPPString & sRow, LPCRECT lpRect, STRUCT_TABLE & st, int nRow)
{
//ENG: Applies styles of <tr> tag
//RUS: ��������� ����� ������ (��� <tr>)
m_defStyle.strTag = _T("tr");
StoreRestoreStyle(FALSE);
SelectNewHtmlStyle(m_defStyle.strTag, m_defStyle);
int nCol = 0;
int i;
vecRow & row = st.cells [nRow];
//ENG: Passes a tag body and get a properties of the tag
//RUS: ���������� ��� ������ ������ � �������� ������ ������� ����
int nIndex = 0;
CPPString sTag;
SearchNextTag(sRow, sTag, nIndex);
CPPString sProperties = SplitTag(sTag);
//ENG: Analyses a properties of the tag
//RUS: ����������� �������� ����
AnalyseCellParam(sProperties, m_defStyle, FALSE);
UpdateContext();
while (nIndex < sRow.GetLength())
{
int nEndRow = nIndex;
int nNewCell = nIndex;
//ENG: Search an end of the cell or a begin of the nested table
//RUS: ���� ����� ������ ��� ������ ��������� �������
SearchTag(sRow, nEndRow, _T("/tr"));
SearchTag(sRow, nNewCell, _T("td"));
if (nNewCell < nEndRow)
{
//ENG: Search an existing cell
//RUS: ����� ������������ ������
STRUCT_CELL * sc2 = &row [nCol];
while ((sc2->nColSpan < 0) && (nCol < (int)row.size()))
{
nCol++;
sc2 = &row [nCol];
} //while
STRUCT_CELL & sc = row [nCol];
//ENG: Searching the end of the cell
//RUS: ���� ��������� ������
nIndex = nNewCell;
SearchEndOfCell(sRow, nIndex);
CPPString sCell = sRow.Mid(nNewCell, nIndex - nNewCell);
RECT rcCell = {0, 0, 0, 0};
if (MODE_FIRSTPASS != m_nNumPass)
{
//ENG: Gets a real rectangle to draw a cell
//RUS: �������� �������� ������������� ��� ������ ������
rcCell = *lpRect;
rcCell.left += m_defStyle.nPadding;
for (i = 0; i < nCol; i++)
rcCell.left += st.width [i] + m_defStyle.nPadding + 1;
rcCell.right = rcCell.left;
for (i = 0; i < sc.nColSpan; i++)
rcCell.right += st.width [nCol + i];
rcCell.right += (sc.nColSpan - 1) * (m_defStyle.nPadding + 1);
rcCell.top += m_defStyle.nPadding;
for (i = 0; i < nRow; i++)
rcCell.top += st.height [i] + m_defStyle.nPadding + 1;
rcCell.bottom = rcCell.top;
for (i = 0; i < sc.nRowSpan; i++)
rcCell.bottom += st.height [nRow + i];
rcCell.bottom += (sc.nRowSpan - 1) * (m_defStyle.nPadding + 1);
//ENG: cellspacing - margins from table's edge to the cell's edge
//RUS: cellspacing - ������ �� ������� ������� �� ������
// rcCell.left += m_defStyle.nPadding;
// rcCell.top += m_defStyle.nPadding;
// rcCell.right -= m_defStyle.nPadding;
// rcCell.bottom -= m_defStyle.nPadding;
} //if
DrawHtmlTableCell(sCell, &rcCell, sc);
if (MODE_DRAW != m_nNumPass)
{
//ENG: Add a cellspacing
//RUS: ��������� ������ ������ ��
// sc.szCell.cx += m_defStyle.nPadding + m_defStyle.nPadding;
// sc.szCell.cy += m_defStyle.nPadding + m_defStyle.nPadding;
//ENG: Stores a span cells
//RUS: ���������� ������������ ������
int nColSpan = sc.nColSpan + nCol;
int nRowSpan = sc.nRowSpan + nRow;
for (i = nCol + 1; i < nColSpan; i++)
{
STRUCT_CELL & scTemp = row [i];
scTemp.nColSpan = -1;
scTemp.nRowSpan = -1;
} //for
for (i = nRow + 1; i < nRowSpan; i++)
{
vecRow & rowTemp = st.cells [i];
STRUCT_CELL & scTemp = rowTemp [nCol];
scTemp.nColSpan = -1;
scTemp.nRowSpan = -1;
} //for
} //if
nCol += sc.nColSpan;
}
else
{
nIndex = sRow.GetLength();
} //if
} //while
//ENG: Restore styles before <tr> tag
//RUS: ��������������� ����� �� ���� <tr>
m_defStyle.strTag = _T("tr");
if (StoreRestoreStyle(TRUE))
UpdateContext();
} //End of DrawHtmlTableRow
///////////////////////////////////////////////////////////////////////////////
// CPPHtmlDrawer::DrawHtmlTableCell
// Draw a table's cell
//-----------------------------------------------------------------------------
// Parameters:
// sCell - a text of the cell with the tags. For example: "<td>...</td>"
// lpRect - a bounding rectangle for cell
// sc - the info about current cell
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
void CPPHtmlDrawer::DrawHtmlTableCell(CPPString & sCell, LPCRECT lpRect, STRUCT_CELL & sc)
{
if (MODE_DRAW != m_nNumPass)
{
sc.szText.cx = 0;
sc.szText.cy = 0;
} //if
RECT rcCell = *lpRect;
RECT rcText;
//ENG: Applies styles of <td> tag
//RUS: ��������� ����� ������ (��� <td>)
m_defStyle.strTag = _T("td");
StoreRestoreStyle(FALSE);
SelectNewHtmlStyle(m_defStyle.strTag, m_defStyle);
//ENG: Passes a tag body and get a properties of the tag
//RUS: ���������� ��� ������ ������ � �������� ������ ������� ����
int nIndex = 0;
CPPString sTag;
SearchNextTag(sCell, sTag, nIndex);
CPPString sProperties = SplitTag(sTag);
//ENG: Analyses a properties of the tag
//RUS: ����������� �������� ����
m_defStyle.nCellWidth = m_defStyle.nCellHeight = 0;
m_defStyle.bCellWidthPercent = m_defStyle.bCellHeightPercent = FALSE;
SIZE szSpan = AnalyseCellParam(sProperties, m_defStyle, FALSE);
if (MODE_FIRSTPASS == m_nNumPass)
{
//ENG: Stores a cell span info
//RUS: ��������� ���������� �� ����������� �����
sc.nColSpan = szSpan.cx;
sc.nRowSpan = szSpan.cy;
//ENG: Stores an info about the recommended cell sizes
//RUS: ��������� ���������� �� ��������������� �������� ������
// sc.nWidth = m_defStyle.nCellWidth;
// sc.bWidthPercent = m_defStyle.bCellWidthPercent;
// sc.nHeight = m_defStyle.nCellHeight;
// sc.bHeightPercent = m_defStyle.bCellHeightPercent;
//ENG:
//RUS: ���� ������� ����������� �a����� ������, �� ���������� �� ��� ���������
sc.szText.cx = m_defStyle.nCellWidth;
// sc.szText.cy = m_defStyle.nCellHeight;
sc.szText.cy = 0;
if (m_defStyle.nCellWidth > 0)
sc.bFixedWidth = TRUE;
rcText = rcCell;
rcText.right = rcText.left + sc.szText.cx;
rcText.bottom = rcText.top + sc.szText.cy;
}
else if (MODE_DRAW == m_nNumPass)
{
//ENG: cellspacing - margins from table's edge to the cell's edge
//RUS: cellspacing - ������ �� ������� ������� �� ������
rcText = rcCell;
if (m_defStyle.nFillBkgnd >= 0)
{
//ENG: Filling cell background
//RUS: ���������� ���� ������
m_drawmanager.FillEffect(m_hDC, m_defStyle.nFillBkgnd, &rcText,
m_defStyle.crBkgnd, m_defStyle.crMidBkgnd, m_defStyle.crEndBkgnd, 5);
} //if
//Draws the border
if (m_bIsEnable)
m_drawmanager.DrawRectangle(m_hDC, &rcText, m_defStyle.crBorderDark, m_defStyle.crBorderLight, m_defStyle.nBorderStyle);
else
m_drawmanager.DrawRectangle(m_hDC, &rcText, m_crDisabled, m_crDisabled, m_defStyle.nBorderStyle);
//ENG: cellpadding - margin from cell's edge to the inside cell text
//RUS: cellpadding - ������ �� ������� ������, �� ������ ������ ��
rcText.left += m_defStyle.nMargin + m_defStyle.nBorderWidth;
rcText.top += m_defStyle.nMargin + m_defStyle.nBorderWidth;
rcText.right -= m_defStyle.nMargin + m_defStyle.nBorderWidth;
rcText.bottom -= m_defStyle.nMargin + m_defStyle.nBorderWidth;
//Vertical align
switch (m_defStyle.nVertAlign)
{
case ALIGN_BOTTOM:
rcText.top = rcText.bottom - sc.szText.cy;
break;
case ALIGN_VCENTER:
rcText.top += (rcText.bottom - rcText.top - sc.szText.cy) / 2;
break;
} //switch
} //if
//ENG: Draws a cell
//RUS: ����� ������
while(nIndex < sCell.GetLength())
{
int nEndCell = nIndex;
int nNewTable = nIndex;
//ENG: Search an end of the cell or a begin of the nested table
//RUS: ���� ����� ������ ��� ������ ��������� �������
SearchTag(sCell, nEndCell, _T("/td"));
SearchTag(sCell, nNewTable, _T("table"));
//ENG: Gets a nearly index of the tag
//RUS: �������� ������ ���������� ����
int nNearlyTag = min(nEndCell, nNewTable);
SIZE szTemp = {0, 0};
if (nNearlyTag > nIndex)
{
//ENG: If between the last index and the current index there is a text
//RUS: ���� ����� ��������� �������� � ������� �������� ���������� �����
CPPString sText = sCell.Mid(nIndex, nNearlyTag - nIndex);
szTemp = DrawHtmlString(sText, &rcText);
nIndex = nNearlyTag;
} //if
else if (nNewTable < nEndCell)
{
//ENG: A nested table was found
//RUS: ������� ��������� �������
nIndex = nNewTable;
SearchEndOfTable(sCell, nIndex);
CPPString sTable = sCell.Mid(nNewTable, nIndex - nNewTable);
szTemp = DrawHtmlTable(sTable, &rcText);
}
else
{
//ENG: Alas, it is the end of the cell
//RUS: ����� ������
nIndex = sCell.GetLength();
} //if
if (MODE_DRAW != m_nNumPass)
{
//ENG: On first and second passes we are calculate the dimensions of the cell
//RUS: �� ������ � ������ �������� ��������� ������� ������.
sc.szText.cx = max(szTemp.cx, sc.szText.cx);
sc.szText.cy += szTemp.cy;
} //if
rcText.top += szTemp.cy;
} //while
if (MODE_DRAW != m_nNumPass)
{
//ENG: On first and second passes we are calculate the dimensions of the cell
//RUS: �� ������ � ������ �������� ��������� ������� ������.
sc.szCell.cx = max(m_defStyle.nCellWidth, sc.szText.cx);
sc.szCell.cy = max(m_defStyle.nCellHeight, sc.szText.cy);
//ENG: Add the margins of the text from the cell's edges
//RUS: ��������� ������� ������ �� ������ ������
sc.szCell.cx += 2 * (m_defStyle.nMargin + m_defStyle.nBorderWidth);
sc.szCell.cy += 2 * (m_defStyle.nMargin + m_defStyle.nBorderWidth);
} //if
//ENG: Restore styles before <td> tag
//RUS: ��������������� �����, ������� ���� �� ���� <td>
m_defStyle.strTag = _T("td");
if (StoreRestoreStyle(TRUE))
UpdateContext();
}
SIZE CPPHtmlDrawer::DrawHtmlString (CPPString & sHtml, LPCRECT lpRect)
{
SIZE szTextArea = {0, 0};
COLORREF clrShadow = m_bIsEnable ? m_crShadow : GetColorByName("");
//ENG: For any string we are add a <body> tag as wrapper
//RUS: ��� ����� ������ ��������� ��� <body>
sHtml = _T("<body>") + sHtml;
sHtml += _T("</body>");
//ENG: Bounding rectangle for a full text
//RUS: �������������� ������������� ��� ������ ����� ������
m_rcOutput.top = lpRect->top;
m_rcOutput.left = lpRect->left;
m_rcOutput.bottom = lpRect->bottom;
m_rcOutput.right = lpRect->right;
//ENG: The width of the bounding rectangle
//RUS: ������ ��������������� ��������������
int nTextWrapWidth = m_rcOutput.right - m_rcOutput.left;
//ENG: A current position for output
//RUS: ������� ������� ��� ������
POINT ptOutput;
ptOutput.x = lpRect->left;
ptOutput.y = lpRect->top;
// szTextArea.cx = szTextArea.cy = 0;
// m_szOutput.cx = m_szOutput.cy = 0;
// m_szOutput = CSize(0, 0);
//ENG: If a text is empty
//RUS: ���� ������ ��� ������ ���
// if (str.IsEmpty())
// {
// szTextArea.cx = szTextArea.cy = 0;
// return;
// } //if
int nFirstLine = m_nCurLine;
// POINT pt;
// pt.x = lpRect->left;
// pt.y = lpRect->top;
int y;
SIZE sz;
CPPString sText = _T("");
CPPString sTag = _T(""); //String of the tag
CPPString sProperties = _T(""); //String of the tag's property
CPPString sParameter = _T("");
CPPString sValue = _T("");
BOOL bCloseTag = FALSE; //TRUE if tag have symbol '\'
//ENG: Initializing a new line
//RUS: ������������� ����� ������
ptOutput.x = InitNewLine(ptOutput.x);
int nBeginLineX = ptOutput.x;
int nSpacesInLine = m_hline.nSpaceChars;
int nRealWidth = m_hline.nWidthLine;
int nIndex = 0;
int nBegin = 0;
int i = 0;
while (i < sHtml.GetLength())
{
//ENG: Searching a first tag
//RUS: ����� ������� ����
sText = SearchNextTag(sHtml, sTag, i);
sProperties = SplitTag(sTag);
//ENG: Before a tag was exist a text
//RUS: ����� ����� ���� ����� ��� ������
if (!sText.IsEmpty())
{
//ENG: Transform text
//RUS: ����������� �����
switch (m_defStyle.nTextTransform)
{
case TEXT_TRANSFORM_UPPERCASE:
//ENG: All chars make upper
//RUS: ��� ������� ��������� � ������� �������
sText.MakeUpper();
break;
case TEXT_TRANSFORM_LOWERCASE:
//ENG: All chars make lower
//RUS: ��� ������� ��������� � ������ �������
sText.MakeLower();
break;
case TEXT_TRANSFORM_CAPITALIZE:
//ENG: Each first char of a word to upper
//RUS: ����� ������ ������ ����� � ������� �������, ��������� � ������
sText.MakeLower();
for (nIndex = 0; nIndex < sText.GetLength(); nIndex++)
{
if ((sText.GetAt(nIndex) >= _T('a')) && (sText.GetAt(nIndex) <= _T('z')))
{
if ((0 == nIndex) || (_T(' ') == sText.GetAt(nIndex - 1)))
sText.SetAt(nIndex, sText.GetAt(nIndex) - _T('a') + _T('A'));
} //if
} //if
break;
} //switch
//RUS: ����������� �� ��� ���, ���� �� ����� ������� ���� �����
while (!sText.IsEmpty())
{
//ENG: Reset an additional interval for space chars
//RUS: ����� ��������������� ��������� ����� �������
::SetTextJustification(m_hDC, 0, 0);
//ENG: Gets a size a output text
//RUS: �������� ������ ���������� ������
::GetTextExtentPoint32(m_hDC, sText, sText.GetLength(), &sz);
//ENG: Gets a real top coordinate to output with vertical alignment
//RUS: �������� �������� ��������� ����� ������ � ������ ������������� ������������
y = VerticalAlignText(ptOutput.y, sz.cy);
CPPString sTemp = sText;
int nMaxSize = nTextWrapWidth - ptOutput.x + m_rcOutput.left;
if (m_nMaxWidth && ((nMaxSize - sz.cx) < 0) && nTextWrapWidth)
{
//ENG: Text wrap was enabled and text out for a bounding rectangle
int nRealSize = nMaxSize;
sTemp = GetWordWrap(sText, nTextWrapWidth, nRealSize);
sz.cx = nRealSize;
}
else
{
sText.Empty();
} //if
if (MODE_DRAW == m_nNumPass)
{
if (sz.cx)
{
if ((0 == (nRealWidth - sz.cx)) && (_T(' ') == sTemp.GetAt(sTemp.GetLength() - 1)))
{
//ENG: Removes the right space chars for the last output in line
//RUS: ���� ��� ��������� ����� � ������, �� ������� ������� ������
sTemp.TrimRight();
nSpacesInLine = GetCountOfChars(sTemp);
SIZE szTemp;
::GetTextExtentPoint32(m_hDC, sTemp, sTemp.GetLength(), &szTemp);
nRealWidth -= (sz.cx - szTemp.cx);
} //if
if ((ALIGN_JUSTIFY == m_hline.nHorzAlign) && m_hline.bWrappedLine)
::SetTextJustification(m_hDC, nMaxSize - nRealWidth, nSpacesInLine);
nRealWidth -= sz.cx;
//ENG: Gets a size a output text
//RUS: �������� ������ ���������� ������
::GetTextExtentPoint32(m_hDC, sTemp, sTemp.GetLength(), &sz);
//ENG: Stores a current area as a hyperlink area if it available
//RUS: ��������� ������� ������� ��� ������� ���������� ���� �� ����������
StoreHyperlinkArea(ptOutput.x, y, ptOutput.x + sz.cx, y + sz.cy);
//ENG: Real output a text
//RUS: ����� ������
::TextOut(m_hDC, ptOutput.x, y, sTemp, sTemp.GetLength());
nSpacesInLine -= GetCountOfChars(sTemp);
//ENG: If sets an overline style then draw a line over the text
//RUS: ���� ���������� ����� overline, �� ������ ����� ��� �������
if (m_defStyle.bOverlineFont)
{
HPEN hpenOverline = ::CreatePen(PS_SOLID, (m_defStyle.nWeightFont >= FW_BOLD) ? 2 : 1, m_defStyle.crText);
HPEN hOldPen = (HPEN)::SelectObject(m_hDC, hpenOverline);
::MoveToEx(m_hDC, ptOutput.x, y, NULL);
::LineTo(m_hDC, ptOutput.x + sz.cx, y);
::SelectObject(m_hDC, hOldPen);
} //if
} //if
}
else
{
//ENG: Stores a last horizontal alignment
//RUS: ��������� ��������� �������������� ������������
m_hline.nHorzAlign = m_defStyle.nHorzAlign;
//ENG:
//RUS:
m_hline.nSpaceChars += GetCountOfChars(sTemp);
} //if
//ENG: Moves to a right of the outputed text
//RUS: ������������ ������ �� ����������� ������
ptOutput.x += sz.cx;
if (!sText.IsEmpty())
{
//ENG: Not all text was printed (cause text wrap)
//RUS: �� ��� ������ ��� �������� (� ������ �������� ������)
m_hline.bWrappedLine = TRUE;
Tag_NewLine(&ptOutput, 1, &szTextArea);
nBeginLineX = ptOutput.x;
nSpacesInLine = m_hline.nSpaceChars;
nRealWidth = m_hline.nWidthLine;
}
} //while
} //if
//ENG: If tag was found then analyzing ...
//RUS: ���� ��� ������, ����������� ...
if (!sTag.IsEmpty())
{
//ENG: Reset temporary parameters
//RUS: ����� ��������� ����������
m_defStyle.strTag.Empty();
bCloseTag = FALSE;
//ENG: Get Tag's name
//RUS: �������� ��� ����
nIndex = 0;
//ENG: Searching a tag's value
//RUS: ����� �������� ����
DWORD dwTag = GetTagFromList(sTag, m_defStyle.strTag, bCloseTag);
//ENG: If a tag was found in a list of the tags
//RUS: ���� ��� ������ � ������
if (TAG_NONE != dwTag)
{
//ENG: If it is a style tag
//RUS: ���� ������� ��� ��� ������ �� �������
if (!m_defStyle.strTag.IsEmpty())
{
//ENG: Checks on permissibility of tag
//RUS: ��������� �� ������������ ����
if (StoreRestoreStyle(bCloseTag))
{
//ENG: If it isn't a close tag
//RUS: ���� ��� �� ��������� ����
if (!bCloseTag)
{
//ENG: Processing a tag
//RUS: ��������� ����
switch (dwTag)
{
case TAG_BOLD:
m_defStyle.nWeightFont <<= 1;
if (m_defStyle.nWeightFont > FW_BLACK)
m_defStyle.nWeightFont = FW_BLACK;
break;
case TAG_ITALIC:
m_defStyle.bItalicFont = m_defStyle.bItalicFont ? FALSE : TRUE;
break;
case TAG_UNDERLINE:
m_defStyle.bUnderlineFont = m_defStyle.bUnderlineFont ? FALSE : TRUE;
break;
case TAG_STRIKEOUT:
m_defStyle.bStrikeOutFont = m_defStyle.bStrikeOutFont ? FALSE : TRUE;
break;
case TAG_FONT:
//Search parameters
while (nIndex < sProperties.GetLength())
{
//ENG: Searching a parameters of a tag
//RUS: ����� ���������� ����
sValue = GetNextProperty(sProperties, nIndex, sParameter);
//ENG: If a parameter was found
//RUS: ���� �������� ������
if (!sParameter.IsEmpty())
{
//ENG: Processing a parameters of a tag
//RUS: ��������� ���������� ����
if (sParameter == _T("face"))
m_defStyle.sFaceFont = GetStyleString(sValue, m_defStyle.sFaceFont);
else if (sParameter == _T("size"))
m_defStyle.nSizeFont = GetLengthUnit(sValue, m_defStyle.nSizeFont, TRUE);
else if (sParameter == _T("color"))
{
if (m_bIsEnable)
m_defStyle.crText = GetStyleColor(sValue, m_defStyle.crText);
else
m_defStyle.crText = GetColorByName("");
}
else if (sParameter == _T("style"))
GetStyleFontShortForm(sValue);
else if (sParameter == _T("weight"))
m_defStyle.nWeightFont = GetStyleFontWeight(sValue, m_defStyle.nWeightFont);
else if (sParameter == _T("bkgnd"))
{
if (((sValue == _T("transparent")) && sValue.IsEmpty()) || !m_bIsEnable)
{
m_defStyle.nBkMode = TRANSPARENT;
}
else
{
m_defStyle.nBkMode = OPAQUE;
m_defStyle.crBkgnd = GetStyleColor(sValue, m_defStyle.crBkgnd);
} //if
} //if
} //if
} //while
break;
case TAG_LEFT:
m_defStyle.nHorzAlign = ALIGN_LEFT;
break;
case TAG_CENTER:
m_defStyle.nHorzAlign = ALIGN_CENTER;
break;
case TAG_RIGHT:
m_defStyle.nHorzAlign = ALIGN_RIGHT;
break;
case TAG_JUSTIFY:
m_defStyle.nHorzAlign = ALIGN_JUSTIFY;
break;
case TAG_BASELINE:
m_defStyle.nVertAlign = ALIGN_BASELINE;
break;
case TAG_TOP:
m_defStyle.nVertAlign = ALIGN_TOP;
break;
case TAG_VCENTER:
m_defStyle.nVertAlign = ALIGN_VCENTER;
break;
case TAG_BOTTOM:
m_defStyle.nVertAlign = ALIGN_BOTTOM;
break;
case TAG_NEWSTYLE:
SelectNewHtmlStyle(sTag, m_defStyle);
break;
case TAG_SPAN:
while (nIndex < sProperties.GetLength())
{
//ENG: Searching a parameters of a tag
//RUS: ����� ���������� ����
sValue = GetNextProperty(sProperties, nIndex, sParameter);
//ENG: If a parameter was found
//RUS: ���� �������� ������
if (sParameter == _T("class"))
SelectNewHtmlStyle(_T(".") + GetStyleString(sValue, _T("")), m_defStyle);
} //while
break;
case TAG_HYPERLINK:
//ENG: A default values
//RUS: �������� �� ���������
m_defStyle.nTypeLink = LINK_MESSAGE;
m_defStyle.sHyperlink.Empty();
while (nIndex < sProperties.GetLength())
{
//ENG: Searching a parameters of a tag
//RUS: ����� ���������� ����
sValue = GetNextProperty(sProperties, nIndex, sParameter);
//ENG: If a parameter was found
//RUS: ���� �������� ������
if (!sParameter.IsEmpty())
{
//ENG: Processing a parameters of a tag
//RUS: ��������� ���������� ����
if (sParameter == _T("href"))
{
m_defStyle.nTypeLink = LINK_HREF;
m_defStyle.sHyperlink = GetStyleString(sValue, _T(""));
} //if
if (sParameter == _T("msg"))
{
m_defStyle.nTypeLink = LINK_MESSAGE;
m_defStyle.sHyperlink = GetStyleString(sValue, _T(""));
} //if
} //if
} //while
//ENG: Gets a index of a current link
//RUS: �������� ������ ������� �����������
m_nCurIndexLink ++;
//ENG: If a mouse over this link
//RUS: ���� ��� ��� ���� �����
if (m_nCurIndexLink == m_nHoverIndexLink)
SelectNewHtmlStyle(_T("a:hover"), m_defStyle);
else
SelectNewHtmlStyle(_T("a:link"), m_defStyle);
break;
} //switch
} //if
//ENG: Update a device context
//RUS: ���������� ��������� ����������
UpdateContext();
} //if
}
else
{
BOOL bPercent;
BOOL bShadow;
BOOL bAutoDelete;
int nWidth, nNum;
STRUCT_IMAGE si;
STRUCT_CHANGESTYLE csTemp; //Temporary structure
STRUCT_ANIMATION sa;
SIZE szReal;
HBITMAP hBitmap = NULL;;
HICON hIcon = NULL;
DWORD nMaxCol, nMaxRow;
UINT nIdRes, nIdDll;
//CPPString str;
//ENG: Processing a tag
//RUS: ��������� ����
switch (dwTag)
{
case TAG_HLINE:
//ENG: Draws the horizontal line
//RUS: ��������� �������������� �����
csTemp = m_defStyle;
csTemp.nBorderWidth = 1;
//ENG: Applies a new styles for <hr> tag
SelectNewHtmlStyle(_T("hr"), csTemp);
nWidth = 100;
bPercent = TRUE;
while (nIndex < sProperties.GetLength())
{
//ENG: Searching a parameters of a tag
//RUS: ����� ���������� ����
sValue = GetNextProperty(sProperties, nIndex, sParameter);
//ENG: If a parameter was found
//RUS: ���� �������� ������
if (!sParameter.IsEmpty())
{
//ENG: Processing a parameters of a tag
//RUS: ��������� ���������� ����
if (sParameter == _T("width"))
{
bPercent = IsPercentableValue(sValue);
nWidth = GetLengthUnit(sValue, 100);
}
else if (sParameter == _T("size"))
csTemp.nBorderWidth = GetLengthUnit(sValue, csTemp.nBorderWidth);
else if (sParameter == _T("color"))
{
if (m_bIsEnable)
csTemp.crText = GetStyleColor(sValue, csTemp.crText);
else
csTemp.crText = GetColorByName("");
}
} //if
} //while
if (bPercent)
{
if (MODE_FIRSTPASS == m_nNumPass)
{
m_hline.nAddPercentWidth += nWidth;
nWidth = 1;
}
else nWidth = ::MulDiv(lpRect->right - lpRect->left, nWidth, 100);
} //if
if (MODE_FIRSTPASS == m_nNumPass)
{
m_hline.nHeightLine = max(m_hline.nHeightLine, csTemp.nBorderWidth + 8);
m_hline.nHorzAlign = m_defStyle.nHorzAlign; //Store a last horizontal alignment
}
else if (MODE_DRAW == m_nNumPass)
{
m_drawmanager.DrawLine(m_hDC, ptOutput.x, ptOutput.y + m_hline.nHeightLine / 2,
ptOutput.x + nWidth, ptOutput.y + m_hline.nHeightLine / 2,
csTemp.crText, CPPDrawManager::PEN_SOLID, csTemp.nBorderWidth);
} //if
ptOutput.x += nWidth;
break;
case TAG_NEWLINE:
//ENG: New line
//RUS: ����� ������
nNum = 1;
if (!sProperties.IsEmpty())
{
sProperties = sProperties.Mid(1);
nNum = GetLengthUnit(sProperties, nNum);
} //if
m_hline.bWrappedLine = FALSE;
Tag_NewLine(&ptOutput, nNum, &szTextArea);
nBeginLineX = ptOutput.x;
nSpacesInLine = m_hline.nSpaceChars;
nRealWidth = m_hline.nWidthLine;
break;
case TAG_TABULATION:
//ENG: Tabulation
//RUS: ���������
nNum = 1;
if (!sProperties.IsEmpty())
{
sProperties = sProperties.Mid(1);
nNum = GetLengthUnit(sProperties, nNum);
} //if
Tag_Tabulation(&ptOutput, nNum);
break;
case TAG_BITMAP:
//-----------------------------
//Draws the bitmap
//-----------------------------
//ENG: Default Parameters
//RUS: ��������� �� ���������
si.nIdRes = 0;
si.nIdDll = 0;
si.nHandle = 0;
si.nWidth = 100;
si.bPercentWidth = TRUE;
si.nHeight = 100;
si.bPercentHeight = TRUE;
si.crMask = RGB(255, 0, 255);
si.bUseMask = FALSE;
si.nStyles = 0;
si.nHotStyles = 0;
si.strSrcFile.Empty();
si.strPathDll.Empty();
//ENG: Searching image parameters
//RUS: ����� ���������� �����������
AnalyseImageParam(sProperties, si);
//ENG: If a image's source was specified
//RUS: ���� ������ �������� �����������
if (si.nIdRes || si.nIdDll || si.nHandle || !si.strSrcFile.IsEmpty())
{
//ENG: Sets a autodelete flag of the image object
//RUS: ���������� ���� ��������������� �������� ������� �����������
bAutoDelete = TRUE;
//ENG: Gets a handle of the image
//RUS: �������� ���������� �����������
if (si.nIdRes)
hBitmap = GetBitmapFromResources(si.nIdRes);
else if (!si.strSrcFile.IsEmpty())
hBitmap = GetBitmapFromFile(si.strSrcFile);
else if (si.nIdDll)
hBitmap = GetBitmapFromDll(si.nIdDll, si.strPathDll);
else if (si.nHandle)
{
hBitmap = (HBITMAP)si.nHandle;
//ENG: If an image handle specified, disables autodelete
//RUS: ���� ������ ���������� �����������, �� ��������� ��������
bAutoDelete = FALSE;
} //if
//ENG: If a handle of an image was retrieved
//RUS: ���� ���������� ����������� �������
if (NULL != hBitmap)
{
//ENG: Image with shadow or not?
//RUS: ����������� � ����� ��� ���
bShadow = IsImageWithShadow(si);
//ENG: Retrieves an original size of an image
//RUS: �������� ������������ ������ �����������
m_drawmanager.GetSizeOfBitmap(hBitmap, &sz);
//ENG: Retrieves an output size
//RUS: �������� ������� ��� ���������
if (si.bPercentWidth) si.nWidth = ::MulDiv(sz.cx, si.nWidth, 100);
if (si.bPercentHeight) si.nHeight = ::MulDiv(sz.cy, si.nHeight, 100);
//ENG: If a shadow was enabled then set a real size
//RUS: ���� ���� ��������, �� ������������� �������� ������
if (si.nWidth && si.nHeight && bShadow)
{
sz.cx = si.nWidth + m_szOffsetShadow.cx;
sz.cy = si.nHeight + m_szOffsetShadow.cy;
} //if
int nMaxSize = nTextWrapWidth - ptOutput.x + m_rcOutput.left;
if (m_nMaxWidth && ((nMaxSize - sz.cx) < 0) && nTextWrapWidth)
{
//ENG: Not all text was printed (cause text wrap)
//RUS: �� ��� ������ ��� �������� (� ������ �������� ������)
m_hline.bWrappedLine = TRUE;
Tag_NewLine(&ptOutput, 1, &szTextArea);
nBeginLineX = ptOutput.x;
nSpacesInLine = m_hline.nSpaceChars;
nRealWidth = m_hline.nWidthLine;
} //if
nRealWidth -= sz.cx;
//ENG: Store a last horizontal alignment
//RUS: ���������� ��������� �������������� ������������
if (MODE_FIRSTPASS == m_nNumPass)
m_hline.nHorzAlign = m_defStyle.nHorzAlign;
//ENG: Retrieves a vertical coordinates of drawing area
//RUS: �������� ������������ ���������� ������� ���������
y = VerticalAlignImage(ptOutput.y, si.nHeight);
//ENG: If an image is exist and not prepare mode
//RUS: ���� ����������� �������� � �� ���������� ����� ����������
if (si.nWidth && si.nHeight && (MODE_DRAW == m_nNumPass))
{
//ENG: Add an output area to hyperlink list if needed
//RUS: ���� ���������� ��������� ������� ������ � ������ �����������
StoreHyperlinkArea(ptOutput.x, y, ptOutput.x + sz.cx, y + sz.cy);
//ENG: If a mouse over an image then applies a hot styles
//RUS: ���� ���� ��� ������������, �� ��������� �������������� �����
if (m_defStyle.nTypeLink != LINK_NONE)
{
if (m_nCurIndexLink == m_nHoverIndexLink)
si.nStyles = si.nHotStyles;
} //if
if (!m_bIsEnable)
si.nStyles = (si.nStyles & 0xFF00) | IMAGE_EFFECT_MONOCHROME;
//ENG: Drawing an image
//RUS: ��������� �����������
m_drawmanager.DrawBitmap(m_hDC, ptOutput.x, y, si.nWidth, si.nHeight, hBitmap,
si.bUseMask, si.crMask, si.nStyles,
bShadow,
m_szOffsetShadow.cx, m_szOffsetShadow.cy,
m_szDepthShadow.cx, m_szDepthShadow.cy,
clrShadow);
} //if
//ENG: Moves to a right of the outputed image
//RUS: ������������ ������ �� ����������� �����������
ptOutput.x += sz.cx; //si.nWidth;
//ENG: If needed delete a handle of an image
//RUS: ���� ���������� ������� ���������� �����������
if (bAutoDelete)
::DeleteObject(hBitmap);
} //if
} //if
break;
case TAG_ICON:
//-----------------------------
//Draws the icon
//-----------------------------
//ENG: Default Parameters
//RUS: ��������� �� ���������
si.nIdRes = 0;
si.nIdDll = 0;
si.nHandle = 0;
si.nWidth = 100;
si.bPercentWidth = TRUE;
si.nHeight = 100;
si.bPercentHeight = TRUE;
si.nStyles = 0;
si.nHotStyles = 0;
si.strSrcFile.Empty();
si.strPathDll.Empty();
//ENG: Searching image parameters
//RUS: ����� ���������� �����������
AnalyseImageParam(sProperties, si);
//ENG: If a image's source was specified
//RUS: ���� ������ �������� �����������
if (si.nIdRes || si.nIdDll || si.nHandle || !si.strSrcFile.IsEmpty())
{
//ENG: Sets a autodelete flag of the image object
//RUS: ���������� ���� ��������������� �������� ������� �����������
bAutoDelete = TRUE;
//RUS: �������� ��������� ������ ������
sz.cx = si.nWidth;
sz.cy = si.nHeight;
if (si.bPercentWidth) sz.cx = ::MulDiv(::GetSystemMetrics(SM_CXICON), si.nWidth, 100);
if (si.bPercentHeight) sz.cy = ::MulDiv(::GetSystemMetrics(SM_CYICON), si.nHeight, 100);
//ENG: Gets a handle of the image
//RUS: �������� ���������� �����������
if (si.nIdRes)
hIcon = GetIconFromResources(si.nIdRes, sz.cx, sz.cy);
else if (!si.strSrcFile.IsEmpty())
hIcon = GetIconFromFile(si.strSrcFile, sz.cx, sz.cy);
else if (si.nIdDll)
hIcon = GetIconFromDll(si.nIdDll, sz.cx, sz.cy, si.strPathDll);
else if (si.nHandle)
{
hIcon = (HICON)si.nHandle;
//ENG: If an image handle specified, disables autodelete
//RUS: ���� ������ ���������� �����������, �� ��������� ��������
bAutoDelete = FALSE;
} //if
//ENG: If a handle of an image was retrieved
//RUS: ���� ���������� ����������� �������
if (NULL != hIcon)
{
//ENG: Image with shadow or not?
//RUS: ����������� � ����� ��� ���
BOOL bShadow = IsImageWithShadow(si);
//ENG: Retrieves an original size of an image
//RUS: �������� ������������ ������ �����������
m_drawmanager.GetSizeOfIcon(hIcon, &sz);
si.nWidth = sz.cx;
si.nHeight = sz.cy;
//ENG: Retrieves an output size
//RUS: �������� ������� ��� ���������
// if (si.bPercentWidth) si.nWidth = ::MulDiv(sz.cx, si.nWidth, 100);
// if (si.bPercentHeight) si.nHeight = ::MulDiv(sz.cy, si.nHeight, 100);
//ENG: If a shadow was enabled then set a real size
//RUS: ���� ���� ��������, �� ������������� �������� ������
if (si.nWidth && si.nHeight && bShadow)
{
sz.cx = si.nWidth + m_szOffsetShadow.cx;
sz.cy = si.nHeight + m_szOffsetShadow.cy;
} //if
int nMaxSize = nTextWrapWidth - ptOutput.x + m_rcOutput.left;
if (m_nMaxWidth && ((nMaxSize - sz.cx) < 0) && nTextWrapWidth)
{
//ENG: Not all text was printed (cause text wrap)
//RUS: �� ��� ������ ��� �������� (� ������ �������� ������)
m_hline.bWrappedLine = TRUE;
Tag_NewLine(&ptOutput, 1, &szTextArea);
nBeginLineX = ptOutput.x;
nSpacesInLine = m_hline.nSpaceChars;
nRealWidth = m_hline.nWidthLine;
} //if
nRealWidth -= sz.cx;
//ENG: Store a last horizontal alignment
//RUS: ���������� ��������� �������������� ������������
if (MODE_FIRSTPASS == m_nNumPass)
m_hline.nHorzAlign = m_defStyle.nHorzAlign;
//ENG: Retrieves a vertical coordinates of drawing area
//RUS: �������� ������������ ���������� ������� ���������
y = VerticalAlignImage(ptOutput.y, si.nHeight);
//ENG: If an image is exist and not prepare mode
//RUS: ���� ����������� �������� � �� ���������� ����� ����������
if (si.nWidth && si.nHeight && (MODE_DRAW == m_nNumPass))
{
//ENG: Add an output area to hyperlink list if needed
//RUS: ���� ���������� ��������� ������� ������ � ������ �����������
StoreHyperlinkArea(ptOutput.x, y, ptOutput.x + sz.cx, y + sz.cy);
//ENG: If a mouse over an image then applies a hot styles
//RUS: ���� ���� ��� ������������, �� ��������� �������������� �����
if (m_defStyle.nTypeLink != LINK_NONE)
{
if (m_nCurIndexLink == m_nHoverIndexLink)
si.nStyles = si.nHotStyles;
} //if
if (!m_bIsEnable)
si.nStyles = (si.nStyles & 0xFF00) | IMAGE_EFFECT_MONOCHROME;
//ENG: Drawing an image
//RUS: ��������� �����������
m_drawmanager.DrawIcon(m_hDC, ptOutput.x, y, si.nWidth, si.nHeight, hIcon, si.nStyles,
bShadow,
m_szOffsetShadow.cx, m_szOffsetShadow.cy,
m_szDepthShadow.cx, m_szDepthShadow.cy,
clrShadow);
} //if
//ENG: Moves to a right of the outputed image
//RUS: ������������ ������ �� ����������� �����������
ptOutput.x += sz.cx; //si.nWidth;
//ENG: If needed delete a handle of an image
//RUS: ���� ���������� ������� ���������� �����������
if (bAutoDelete)
::DestroyIcon(hIcon);
} //if
} //if
break;
case TAG_IMAGELIST:
//-----------------------------
//Draws the icon from image list
//-----------------------------
//ENG: Default Parameters
//RUS: ��������� �� ���������
si.nIndexImageList = 0;
si.nIdRes = 0;
si.nIdDll = 0;
si.nHandle = 0;
si.nWidth = 100;
si.bPercentWidth = TRUE;
si.nHeight = 100;
si.bPercentHeight = TRUE;
si.nSpeed = 0;
si.bUseMask = FALSE;
si.crMask = RGB(255, 0, 255);
si.cx = 0;//GetSystemMetrics(SM_CXICON);
si.cy = 0;//GetSystemMetrics(SM_CYICON);
si.nStyles = 0;
si.nHotStyles = 0;
si.strSrcFile.Empty();
si.strPathDll.Empty();
//ENG: Searching image parameters
//RUS: ����� ���������� �����������
AnalyseImageParam(sProperties, si);
//ENG: Image with shadow or not?
//RUS: ����������� � ����� ��� ���
bShadow = IsImageWithShadow(si);
if (si.nIdRes || si.nIdDll || si.nHandle || !si.strSrcFile.IsEmpty())
{
//ENG: Sets a autodelete flag of the image object
//RUS: ���������� ���� ��������������� �������� ������� �����������
bAutoDelete = TRUE;
//ENG: Gets a handle of the image
//RUS: �������� ���������� �����������
if (si.nIdRes)
hBitmap = GetBitmapFromResources(si.nIdRes);
else if (!si.strSrcFile.IsEmpty())
hBitmap = GetBitmapFromFile(si.strSrcFile);
else if (si.nIdDll)
hBitmap = GetBitmapFromDll(si.nIdDll, si.strPathDll);
else if (si.nHandle)
{
hBitmap = (HBITMAP)si.nHandle;
//ENG: If an image handle specified, disables autodelete
//RUS: ���� ������ ���������� �����������, �� ��������� ��������
bAutoDelete = FALSE;
} //if
//ENG: If a handle of an image was retrieved
//RUS: ���� ���������� ����������� �������
if (NULL != hBitmap)
{
//ENG: Retrieves an original size of an image
//RUS: �������� ������������ ������ �����������
m_drawmanager.GetSizeOfBitmap(hBitmap, &sz);
//ENG: Creates a no specified sizes
//RUS: ������� ���������� �������
if (!si.cx && !si.cy)
si.cx = si.cy = min(sz.cx, sz.cy);
else if (!si.cx)
si.cx = si.cy;
else if (!si.cy)
si.cy = si.cx;
//ENG: Retrieves an output size
//RUS: �������� ������� ��� ���������
if (si.bPercentWidth) si.nWidth = ::MulDiv(si.cx, si.nWidth, 100);
if (si.bPercentHeight) si.nHeight = ::MulDiv(si.cy, si.nHeight, 100);
//ENG: If a shadow was enabled then set a real size
//RUS: ���� ���� ��������, �� ������������� �������� ������
szReal.cx = si.nWidth;
szReal.cy = si.nHeight;
if (si.nWidth && si.nHeight && bShadow)
{
szReal.cx += m_szOffsetShadow.cx;
szReal.cy += m_szOffsetShadow.cy;
} //if
//ENG: Gets a max columns and rows of the images on the bitmap
//RUS: �������� ������������ ����� ������� � ����� ����������� �� ��������
nMaxCol = sz.cx / si.cx;
nMaxRow = sz.cy / si.cy;
if (si.nSpeed)
{
if (MODE_FIRSTPASS == m_nNumPass)
{
sa.nIndex = si.nIndexImageList;
sa.nMaxImages = nMaxCol * nMaxRow;
sa.nSpeed = si.nSpeed;
sa.nTimerCount = 0;
m_arrAni.push_back(sa);
}
else if (MODE_DRAW == m_nNumPass)
{
m_nCurIndexAni ++;
sa = m_arrAni [m_nCurIndexAni];
si.nIndexImageList = sa.nIndex;
} //if
} //if
//ENG: If a specified index of image is a legitimate value
//RUS: ���� ��������� ������ ����������� ��������
if ((si.nIndexImageList < (int)(nMaxCol * nMaxRow)) && nMaxCol && nMaxRow)
{
int nMaxSize = nTextWrapWidth - ptOutput.x + m_rcOutput.left;
if (m_nMaxWidth && ((nMaxSize - szReal.cx) < 0) && nTextWrapWidth)
{
//ENG: Not all text was printed (cause text wrap)
//RUS: �� ��� ������ ��� �������� (� ������ �������� ������)
m_hline.bWrappedLine = TRUE;
Tag_NewLine(&ptOutput, 1, &szTextArea);
nBeginLineX = ptOutput.x;
nSpacesInLine = m_hline.nSpaceChars;
nRealWidth = m_hline.nWidthLine;
} //if
nRealWidth -= szReal.cx;
//ENG: Store a last horizontal alignment
//RUS: ���������� ��������� �������������� ������������
if (MODE_FIRSTPASS == m_nNumPass)
m_hline.nHorzAlign = m_defStyle.nHorzAlign;
//ENG: Retrieves a vertical coordinates of drawing area
//RUS: �������� ������������ ���������� ������� ���������
y = VerticalAlignImage(ptOutput.y, szReal.cy);
//ENG: If an image is exist and not prepare mode
//RUS: ���� ����������� �������� � �� ���������� ����� ����������
if (si.nWidth && si.nHeight && (MODE_DRAW == m_nNumPass))
{
//ENG: Add an output area to hyperlink list if needed
//RUS: ���� ���������� ��������� ������� ������ � ������ �����������
StoreHyperlinkArea(ptOutput.x, y, ptOutput.x + szReal.cx, y + szReal.cy);
//ENG: If a mouse over an image then applies a hot styles
//RUS: ���� ���� ��� ������������, �� ��������� �������������� �����
if (m_defStyle.nTypeLink != LINK_NONE)
{
if (m_nCurIndexLink == m_nHoverIndexLink)
si.nStyles = si.nHotStyles;
} //if
if (!m_bIsEnable)
si.nStyles = (si.nStyles & 0xFF00) | IMAGE_EFFECT_MONOCHROME;
//ENG: Drawing an image
//RUS: ��������� �����������
m_drawmanager.DrawImageList(m_hDC, ptOutput.x, y, si.nWidth, si.nHeight, hBitmap,
si.nIndexImageList, si.cx, si.cy,
si.bUseMask, si.crMask, si.nStyles,
bShadow,
m_szOffsetShadow.cx, m_szOffsetShadow.cy,
m_szDepthShadow.cx, m_szDepthShadow.cy,
clrShadow);
} //if
//ENG: Moves to a right of the outputed image
//RUS: ������������ ������ �� ����������� �����������
ptOutput.x += szReal.cx;
} //if
//ENG: If needed delete a handle of an image
//RUS: ���� ���������� ������� ���������� �����������
if (bAutoDelete)
::DeleteObject(hBitmap);
} //if
}
else if (NULL != m_hImageList)
{
// Ensure that the common control DLL is loaded.
InitCommonControls();
if ((int)si.nIndexImageList < ImageList_GetImageCount(m_hImageList))
{
hIcon = ImageList_ExtractIcon(NULL, m_hImageList, si.nIndexImageList);
if (NULL != hIcon)
{
sz.cx = si.nWidth;
sz.cy = si.nHeight;
if (si.bPercentWidth) sz.cx = ::MulDiv(m_szImageList.cx, si.nWidth, 100);
if (si.bPercentHeight) sz.cy = ::MulDiv(m_szImageList.cy, si.nHeight, 100);
szReal.cx = sz.cx;
szReal.cy = sz.cy;
if (sz.cx && sz.cy && bShadow)
{
szReal.cx += m_szOffsetShadow.cx;
szReal.cy += m_szOffsetShadow.cy;
} //if
int nMaxSize = nTextWrapWidth - ptOutput.x + m_rcOutput.left;
if (m_nMaxWidth && ((nMaxSize - szReal.cx) < 0) && nTextWrapWidth)
{
//ENG: Not all text was printed (cause text wrap)
//RUS: �� ��� ������ ��� �������� (� ������ �������� ������)
m_hline.bWrappedLine = TRUE;
Tag_NewLine(&ptOutput, 1, &szTextArea);
nBeginLineX = ptOutput.x;
nSpacesInLine = m_hline.nSpaceChars;
nRealWidth = m_hline.nWidthLine;
} //if
nRealWidth -= sz.cx;
if (MODE_FIRSTPASS == m_nNumPass)
m_hline.nHorzAlign = m_defStyle.nHorzAlign; //Store a last horizontal alignment
y = VerticalAlignImage(ptOutput.y, szReal.cy);
if (sz.cx && sz.cy && (MODE_DRAW == m_nNumPass))
{
StoreHyperlinkArea(ptOutput.x, y, ptOutput.x + szReal.cx, y + szReal.cy);
if (m_defStyle.nTypeLink != LINK_NONE)
{
if (m_nCurIndexLink == m_nHoverIndexLink)
si.nStyles = si.nHotStyles;
} //if
if (!m_bIsEnable)
si.nStyles = (si.nStyles & 0xFF00) | IMAGE_EFFECT_MONOCHROME;
m_drawmanager.DrawIcon(m_hDC, ptOutput.x, y,
sz.cx, sz.cy, hIcon, si.nStyles,
bShadow,
m_szOffsetShadow.cx, m_szOffsetShadow.cy,
m_szDepthShadow.cx, m_szDepthShadow.cy,
clrShadow);
::DestroyIcon(hIcon);
} //if
ptOutput.x += szReal.cx;
} //if
} //if
} //if
break;
case TAG_STRING:
//-----------------------------
//Draws the string
//-----------------------------
nIdRes = 0;
nIdDll = 0;
sText.Empty();
while (nIndex < sProperties.GetLength())
{
//ENG: Searching a parameters of a tag
//RUS: ����� ���������� ����
sValue = GetNextProperty(sProperties, nIndex, sParameter);
//ENG: If a parameter was found
//RUS: ���� �������� ������
if (!sParameter.IsEmpty())
{
if (sParameter == _T("idres"))
nIdRes = GetLengthUnit(sValue, nIdRes);
else if (sParameter == _T("iddll"))
nIdRes = GetLengthUnit(sValue, nIdDll);
else if (sParameter == _T("srcdll"))
sText = GetStyleString(sValue, sText);
} //if
} //while
if (nIdRes || nIdDll)
{
if (nIdRes)
sText = GetStringFromResource(nIdRes);
else if (nIdDll)
sText = GetStringFromDll(nIdDll, sText);
if (!sText.IsEmpty())
{
::GetTextExtentPoint32(m_hDC, sText, sText.GetLength(), &sz);
if (MODE_FIRSTPASS == m_nNumPass) m_hline.nHorzAlign = m_defStyle.nHorzAlign; //Store a last horizontal alignment
y = VerticalAlignText(ptOutput.y, sz.cy);
if (MODE_DRAW == m_nNumPass)
{
StoreHyperlinkArea(ptOutput.x, y, ptOutput.x + sz.cx, y + sz.cy);
::TextOut(m_hDC, ptOutput.x, y, sText, sText.GetLength());
} //if
ptOutput.x += sz.cx;
} //if
} //if
break;
} //switch
} //if
} //if
} //if
} //for
if (nBeginLineX != ptOutput.x)
{
m_hline.bWrappedLine = FALSE;
Tag_NewLine(&ptOutput, 1, &szTextArea);
}
//ENG: Reset an additional interval for space chars
//RUS: ����� ��������������� ��������� ����� �������
::SetTextJustification(m_hDC, 0, 0);
szTextArea.cy = ptOutput.y - lpRect->top;
//Adds the percent's length to the line's length
for (i = nFirstLine; i < m_nCurLine; i++)
{
m_hline = m_arrHtmlLine [i];
if (0 != m_hline.nAddPercentWidth)
{
m_hline.nWidthLine += ::MulDiv(m_hline.nAddPercentWidth, szTextArea.cx, 100);
szTextArea.cx = max(szTextArea.cx, m_hline.nWidthLine);
} //if
} //for
//
// if (NULL != lpSize)
// {
// szTextArea.cx = m_szOutput.cx;
// szTextArea.cy = m_szOutput.cy;
// } //if
return szTextArea;
} //End DrawHtmlString
void CPPHtmlDrawer::StoreHyperlinkArea(int left, int top, int right, int bottom)
{
if (m_defStyle.nTypeLink != LINK_NONE)
{
STRUCT_HYPERLINK link;
link.rcArea.left = left;
link.rcArea.top = top;
link.rcArea.right = right;
link.rcArea.bottom = bottom;
link.sHyperlink = m_defStyle.sHyperlink;
link.nTypeLink = m_defStyle.nTypeLink;
link.nIndexLink = m_nCurIndexLink;
m_arrLinks.push_back(link);
} //if
} //StoreHyperlinkArea
void CPPHtmlDrawer::SelectNewHtmlStyle(LPCTSTR lpszNameStyle, STRUCT_CHANGESTYLE & cs)
{
//Unpack a new styles
UnpackTextStyle(GetTextStyle(lpszNameStyle), cs);
}
BOOL CPPHtmlDrawer::StoreRestoreStyle(BOOL bRestore)
{
BOOL bOk = FALSE;
if (bRestore)
{
//Restore styles
if (m_arrStack.size() > 0)
{
STRUCT_CHANGESTYLE cs = m_arrStack.back();
if (cs.strTag == m_defStyle.strTag)
{
m_defStyle = cs;
m_arrStack.pop_back();
bOk = TRUE;
} //if
} //if
m_defStyle.strTag.Empty();
}
else
{
m_arrStack.push_back(m_defStyle);
bOk = TRUE;
} //if
return bOk;
} //End StoreRestoreStyle
void CPPHtmlDrawer::UpdateContext()
{
::SelectObject(m_hDC, m_hOldFont);
::DeleteObject(m_hFont);
m_lfDefault.lfHeight = m_defStyle.nSizeFont;
m_lfDefault.lfWeight = m_defStyle.nWeightFont;
m_lfDefault.lfItalic = m_defStyle.bItalicFont;
m_lfDefault.lfStrikeOut = m_defStyle.bStrikeOutFont;
m_lfDefault.lfUnderline = m_defStyle.bUnderlineFont;
_tcscpy (m_lfDefault.lfFaceName, m_defStyle.sFaceFont);
m_hFont = ::CreateFontIndirect(&m_lfDefault);
m_hOldFont = (HFONT)::SelectObject(m_hDC, m_hFont);
::GetTextMetrics(m_hDC, &m_tm);
::SetBkMode(m_hDC, m_defStyle.nBkMode);
::SetTextColor(m_hDC, m_defStyle.crText);
::SetBkColor(m_hDC, m_defStyle.crBkgnd);
} //End UpdateContext
int CPPHtmlDrawer::VerticalAlignText(int y, int nHeight)
{
//Vertical align
if (MODE_FIRSTPASS == m_nNumPass)
{
//If calculate then don't output text
m_hline.nDescentLine = max(m_hline.nDescentLine, nHeight - m_tm.tmAscent);
m_hline.nHeightLine = max(m_hline.nHeightLine, m_tm.tmAscent);
}
else if (MODE_DRAW == m_nNumPass)
{
switch (m_defStyle.nVertAlign)
{
case ALIGN_VCENTER:
y += (m_hline.nHeightLine - m_tm.tmHeight) / 2;
break;
case ALIGN_BASELINE:
y += m_hline.nHeightLine - m_hline.nDescentLine - m_tm.tmAscent;
break;
case ALIGN_BOTTOM:
y += m_hline.nHeightLine - m_tm.tmAscent;
break;
} //switch
} //if
return y;
} //End VerticalAlignText
int CPPHtmlDrawer::VerticalAlignImage(int y, int nHeight)
{
//Vertical align
if (MODE_FIRSTPASS == m_nNumPass)
{
//If calculate then don't output text
m_hline.nHeightLine = max(m_hline.nHeightLine, nHeight);
}
else if (MODE_DRAW == m_nNumPass)
{
switch (m_defStyle.nVertAlign)
{
case ALIGN_VCENTER:
y += (m_hline.nHeightLine - nHeight) / 2;
break;
case ALIGN_BASELINE:
y += m_hline.nHeightLine - m_hline.nDescentLine - nHeight;
break;
case ALIGN_BOTTOM:
y += m_hline.nHeightLine - nHeight;
break;
} //switch
} //if
return y;
} //End VerticalAlignImage
void CPPHtmlDrawer::Tag_NewLine(LPPOINT lpPoint, int nNum, LPSIZE lpSize)
{
//New line
if (nNum <= 0)
nNum = 1;
if (MODE_FIRSTPASS == m_nNumPass)
{
if (!m_hline.nHeightLine)
m_hline.nHeightLine = m_tm.tmHeight;
lpSize->cx = max(lpSize->cx, lpPoint->x - m_rcOutput.left);
m_hline.nWidthLine = lpPoint->x - m_rcOutput.left; //Adds the real length of the lines
m_hline.nHeightLine += m_hline.nDescentLine; //Adds the real height of the lines
m_arrHtmlLine [m_nCurLine] = m_hline;
} //if
m_nCurLine ++;
lpPoint->y += m_hline.nHeightLine * nNum;
lpPoint->x = InitNewLine(m_rcOutput.left);
} //End Tag_NewLine
int CPPHtmlDrawer::InitNewLine(int x)
{
if (MODE_FIRSTPASS == m_nNumPass)
{
//ENG: Creates a new line with default parameters
//RUS: �������� ����� ����� � ����������� ��-���������
m_hline.nAddPercentWidth = 0;
m_hline.nDescentLine = 0;
m_hline.nHeightLine = 0;
m_hline.nWidthLine = 0;
m_hline.nHorzAlign = m_defStyle.nHorzAlign;
m_hline.nSpaceChars = 0;
m_arrHtmlLine.push_back(m_hline);
}
else if (MODE_DRAW == m_nNumPass)
{
//ENG: Gets the data of the first line and converts the percent value to the real width
//RUS: �������� ������ ������ ������ � ����������� ���������� ������ � ��������
m_hline = m_arrHtmlLine [m_nCurLine];
int nRealWidth = m_rcOutput.right - m_rcOutput.left;
if (m_hline.nAddPercentWidth)
m_hline.nWidthLine += ::MulDiv(nRealWidth, m_hline.nAddPercentWidth, 100);
if ((ALIGN_JUSTIFY == m_hline.nHorzAlign) && m_hline.bWrappedLine)
::SetTextJustification(m_hDC, nRealWidth - m_hline.nWidthLine, m_hline.nSpaceChars);
else
::SetTextJustification(m_hDC, 0, 0);
//ENG: Horizontal coordinate of the begin output
//RUS: ���������� ������ ������ � ������ ������������
switch (m_hline.nHorzAlign)
{
case ALIGN_CENTER:
x = m_rcOutput.left + (nRealWidth - m_hline.nWidthLine) / 2;
break;
case ALIGN_RIGHT:
x = m_rcOutput.left + nRealWidth - m_hline.nWidthLine;
break;
} //switch
} //if
return x;
} //End of InitNewLine
void CPPHtmlDrawer::Tag_Tabulation(LPPOINT lpPoint, int nNum)
{
//Tabulation
if (!nNum)
nNum = 1;
int nWidth = (lpPoint->x - m_rcOutput.left) % m_nTabSize;
if (nWidth)
{
//aligns with tab
lpPoint->x += m_nTabSize - nWidth;
nNum --;
} //if
lpPoint->x += (nNum * m_nTabSize);
} //End Tag_Tabulation
/////////////////////////////////////////////////////////////////////////////////////////
void CPPHtmlDrawer::Draw(HDC hDC, LPCTSTR lpszHtml, LPPOINT lpPoint)
{
//ENG: Preparing an output text
//RUS: ���������� ������ � ������
SIZE size;
PrepareOutput(hDC, lpszHtml, &size);
//ENG: If output was disabled
//RUS: ���� ����� ��������
if (!size.cx || !size.cy)
return;
//ENG: Calculates an output area
//RUS: ������� ������� ������
RECT rect;
rect.left = lpPoint->x;
rect.top = lpPoint->y;
rect.right = rect.left + size.cx;
rect.bottom = rect.top + size.cy;
//ENG: Output a prepared text
//RUS: ����� ��������������� ������
DrawPreparedOutput(hDC, &rect);
} //End Draw
void CPPHtmlDrawer::PrepareOutput(HDC hDC, LPCTSTR lpszHtml, LPSIZE lpSize)
{
//ENG: Copy initial parameters
//RUS: ����������� ��������� ����������
m_hDC = hDC;
//ENG: Reset text justification
::SetTextJustification(m_hDC, 0, 0);
RECT rect;
rect.left = rect.right = rect.top = rect.bottom = 0;
// if (m_bIsTextWrapEnabled)
rect.right = m_nMaxWidth;
m_csHtmlText = lpszHtml;
ReplaceSpecChars();
lpSize->cx = lpSize->cy = 0;
//ENG: If prepared text wasn't empty then return
//RUS: ���� �������������� ����� �� ������, �� �����
if (!m_csHtmlText.IsEmpty())
{
//ENG: Sets a prepare mode
//RUS: ������������� ����� ����������
m_nNumPass = MODE_FIRSTPASS;
m_arrTables.clear();
//ENG: Prepares to real output
//RUS: ���������� � ��������� ������
DrawHtml(lpSize, &rect);
if (!lpSize->cx && !lpSize->cy)
m_csHtmlText.Empty();
//Cuts a tooltip if his real width more than m_nMaxWidth
if (m_nMaxWidth/*m_bIsTextWrapEnabled*/ && (lpSize->cx > m_nMaxWidth))
lpSize->cx = m_nMaxWidth;
lpSize->cx ++;
lpSize->cy ++;
} //if
} //End PrepareOutput
////////////////////////////////////////////////////////////////////
// CPPHtmlDrawer::DrawPreparedOutput()
// Draw a string prepared by PrepareOutput method.
//------------------------------------------------------------------
// Parameters:
// hDC - Device Context to drawing
// lpRect - Pointer to RECT structure contains a bounding rectangle of
// drawing area.
////////////////////////////////////////////////////////////////////
void CPPHtmlDrawer::DrawPreparedOutput(HDC hDC, LPCRECT lpRect)
{
//ENG: If prepared text was empty then return
//RUS: ���� �������������� ����� ������, �� �����
if (m_csHtmlText.IsEmpty())
return;
//ENG: Copy initial parameters
//RUS: ����������� ��������� ����������
m_hDC = hDC;
SIZE size = {0, 0};
//ENG: Sets a output mode
//RUS: ������������� ����� ������
m_nNumPass = MODE_DRAW;
RECT rect = *lpRect;
// if (((rect.right - rect.left) > m_nMaxWidth) && m_bIsTextWrapEnabled)
// rect.right = rect.left + m_nMaxWidth;
//ENG: Real output the prepared string
//RUS: ����� �������������� ������
DrawHtml(&size, &rect);
} //End of DrawPreparedOutput
// The following appeared in Paul DiLascia's Jan 1998 MSJ articles.
// It loads a "hand" cursor from the winhlp32.exe module
void CPPHtmlDrawer::SetDefaultCursor()
{
if (m_hLinkCursor == NULL) // No cursor handle - load our own
{
#ifdef IDC_HAND
//This code was added from Zorglab's comments to hyperlink control from Chris Maunder
m_hLinkCursor = ::LoadCursor(NULL, IDC_HAND); // Load Windows' hand cursor
if (m_hLinkCursor != NULL) // if not available, load it from winhlp32.exe
return;
#endif //IDC_HAND
// Get the windows directory
CPPString strWndDir;
GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH);
strWndDir.ReleaseBuffer();
strWndDir += _T("\\winhlp32.exe");
// This retrieves cursor #106 from winhlp32.exe, which is a hand pointer
HMODULE hModule = LoadLibrary(strWndDir);
if (hModule)
{
HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106));
if (hHandCursor)
m_hLinkCursor = CopyCursor(hHandCursor);
} //if
FreeLibrary(hModule);
} //if
} //End SetDefaultCursor
void CPPHtmlDrawer::SetHyperlinkCursor(HCURSOR hCursor /* = NULL */)
{
if ((m_hLinkCursor == hCursor) && (NULL != m_hLinkCursor))
return;
if (NULL != m_hLinkCursor)
{
::DestroyCursor(m_hLinkCursor);
m_hLinkCursor = NULL;
} //if
if (NULL == hCursor)
SetDefaultCursor();
else
m_hLinkCursor = hCursor;
} //End SetHyperlinkCursor
HCURSOR CPPHtmlDrawer::GetHyperlinkCursor() const
{
return m_hLinkCursor;
} //End GetHyperlinkCursor
/////////////////////////////////////////////////////////////////////
// CPPHtmlDrawer::SetCallbackHyperlink
// This function sets or removes the notification messages from the control before display.
//
// Parameters:
// hWnd [in] - If non-NULL the control will be send the notification
// to specified window
// Else the notification will not send
///////////////////////////////////////////////////////////////////////
void CPPHtmlDrawer::SetCallbackHyperlink(HWND hWnd, UINT nMessage, LPARAM lParam /* = 0 */)
{
// TRACE(_T("CPPHtmlDrawer::SetCallbackHyperlink()\n"));
m_csCallbackLink.hWnd = hWnd;
if (NULL == hWnd)
{
m_csCallbackLink.nMessage = 0;
m_csCallbackLink.lParam = 0;
}
else
{
m_csCallbackLink.nMessage = nMessage;
m_csCallbackLink.lParam = lParam;
} //if
} //End SetCallbackHyperlink
void CPPHtmlDrawer::SetCallbackRepaint(HWND hWnd, UINT nMessage, LPARAM lParam /* = 0 */)
{
// TRACE(_T("CPPHtmlDrawer::SetCallbackRepaint()\n"));
m_csCallbackRepaint.hWnd = hWnd;
if (NULL == hWnd)
{
m_csCallbackRepaint.nMessage = 0;
m_csCallbackRepaint.lParam = 0;
}
else
{
m_csCallbackRepaint.nMessage = nMessage;
m_csCallbackRepaint.lParam = lParam;
} //if
} //End SetCallbackRepaint
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::SetImageList (public member function)
// sets the image list to tooltip
//
// Parameters :
// nIdBitmap [in] - Resource IDs of the bitmap to be associated with the image list
// cx [in] - Dimensions of each image, in pixels.
// cy [in] - Dimensions of each image, in pixels.
// nCount [in] - Number of images that the image list initially contains.
// crMask [in] - Color used to generate a mask. Each pixel of this color in the
// specified bitmap is changed to black, and the corresponding
// bit in the mask is set to one.
// Returns :
// None
//
/////////////////////////////////////////////////////////////////////////////
void CPPHtmlDrawer::SetImageList(UINT nIdBitmap, int cx, int cy, int nCount, COLORREF crMask /* = RGB(255, 0, 255) */)
{
// Load bitmap
HBITMAP hBitmap = GetBitmapFromResources(nIdBitmap);
SetImageList(hBitmap, cx, cy, nCount, crMask);
} //End SetImageList
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::SetImageList (public member function)
// sets the image list to tooltip
//
// Parameters :
// hBitmap [in] - Handle of the bitmap to be associated with the image list
// cx [in] - Dimensions of each image, in pixels.
// cy [in] - Dimensions of each image, in pixels.
// nCount [in] - Number of images that the image list initially contains.
// crMask [in] - Color used to generate a mask. Each pixel of this color in the
// specified bitmap is changed to black, and the corresponding
// bit in the mask is set to one.
// Returns :
// None
//
/////////////////////////////////////////////////////////////////////////////
void CPPHtmlDrawer::SetImageList(HBITMAP hBitmap, int cx, int cy, int nCount, COLORREF crMask /* = RGB(255, 0, 255) */)
{
//ENG: Removes previously image list
//RUS: ������� ���������� ������ �����������
if (NULL != m_hImageList)
::DeleteObject(m_hImageList);
//ENG: If don't need to create a new image list
//RUS: ���� �� ����� ��������� ����� ������ �����������
if (NULL == hBitmap)
return;
// Ensure that the common control DLL is loaded.
InitCommonControls();
m_hImageList = ImageList_Create(cx, cy, ILC_COLOR32 | ILC_MASK, nCount, 1);
ImageList_AddMasked(m_hImageList, hBitmap, crMask);
m_szImageList.cx = cx;
m_szImageList.cy = cy;
} //End SetImageList
/////////////////////////////////////////////////////////////////////////////
// CPPToolTip::GetImageList (public member function)
// gets the image list from tooltip
//
// Parameters :
// sz [out] - Dimensions of each image, in pixels.
// Returns :
// A pointer to a CImageList object
//
/////////////////////////////////////////////////////////////////////////////
//CImageList * CPPHtmlDrawer::GetImageList(CSize & sz)
//{
// sz = m_szImageList;
// return &m_ImageList;
//} //End GetImageList
void CPPHtmlDrawer::EnableEscapeSequences(BOOL bEnable /* = TRUE */)
{
m_bEnableEscapeSequences = bEnable;
}
void CPPHtmlDrawer::LoadResourceDll(LPCTSTR lpszPathDll, DWORD dwFlags /* = 0 */)
{
HINSTANCE hInst = NULL;
if (NULL != lpszPathDll)
hInst = ::LoadLibraryEx(lpszPathDll, NULL, dwFlags);
SetResourceDll(hInst);
if (NULL != hInst)
m_bFreeInstDll = TRUE;
} //End LoadResourceDll
void CPPHtmlDrawer::SetResourceDll(HINSTANCE hInstDll /* = NULL */)
{
if (NULL != m_hInstDll)
{
if (!m_bFreeInstDll)
return;
::FreeLibrary(m_hInstDll);
m_hInstDll = NULL;
} //if
m_bFreeInstDll = FALSE;
if (NULL != hInstDll)
m_hInstDll = hInstDll;
} //End SetResourceDll
CPPDrawManager * CPPHtmlDrawer::GetDrawManager()
{
return &m_drawmanager;
} //End GetDrawManager
BOOL CPPHtmlDrawer::IsImageWithShadow(_STRUCT_IMAGE & si)
{
DWORD dwStyles = si.nStyles | si.nHotStyles;
if ((dwStyles & IMAGE_EFFECT_MONO_SHADOW) ||
(dwStyles & IMAGE_EFFECT_GRADIENT_SHADOW))
return TRUE;
return FALSE;
}
///////////////////////////////////////////////////////////////////////////
// Map of the styles
void CPPHtmlDrawer::SetDefaultCssStyles()
{
CPPString str = _T("");
str += _T("body {font-size: 10pt; color:black; font-family:Verdana}\r\n");
str += _T("p {font-size: 10pt; color:black; font-family:Verdana; font-weight:bold}\r\n");
str += _T("h1 {font-size: 14pt; color:black; font-family:Verdana; font-weight:bold}\r\n");
str += _T("h2 {font-size: 13pt; color:#ff9900; font-family:Verdana; font-weight:bold}\r\n");
str += _T("h3 {font-size: 12pt; color:#ff9900; font-family:Arial; font-weight:bold}\r\n");
str += _T("h4 {font-size: 10pt; color:black; font-family:Verdana; font-weight:bold}\r\n");
str += _T("h5 {font-size: 9pt; color:#ff9900; font-family:Verdana; font-weight:bold}\r\n");
str += _T("h6 {font-size: 65%; color:#626262; font-family:Verdana; font-weight:normal}\r\n");
str += _T("pre {font-size: 9pt; font-family:\"Courier\"; background-color:#fbedbb}\r\n");
str += _T("code {color:#990000; font-family:Arial}\r\n");
str += _T("a:link {text-decoration:none; color:blue}\r\n");
str += _T("a:hover {text-decoration:underline; color:blue}\r\n");
str += _T("sub {font-size:65%; vertical-align:bottom}\r\n");
str += _T("sup {font-size:65%; vertical-align:top}\r\n");
str += _T("big {font-size:125%}\r\n");
str += _T("small {font-size:75%}\r\n");
str += _T(".cpp-comment {color:green; font-style:italic}\r\n");
// str += _T("td {text-align:center; color:#ff0000; vertical-align:middle}\r\n");
// str += _T("table {padding:2; border-width:1; color:red}\r\n");
SetCssStyles(str);
} //End SetDefaultCssStyle
void CPPHtmlDrawer::SetCssStyles(DWORD dwIdCssString, LPCTSTR lpszPathDll /* = NULL */)
{
CPPString str;
if (NULL == lpszPathDll)
str = GetStringFromResource(dwIdCssString);
else
str = GetStringFromDll(dwIdCssString, lpszPathDll);
SetCssStyles(str);
} //End SetCssStyles
void CPPHtmlDrawer::SetCssStyles(LPCTSTR lpszCssString /* = NULL */)
{
m_mapStyles.clear(); //removes previously styles
if (NULL == lpszCssString)
{
SetDefaultCssStyles();
}
else
{
CPPString str = (CPPString)lpszCssString;
m_strCssStyles = str;
CPPString strName;
CPPString strProperty;
int nBegin;
TCHAR chSymbol;
int nIndex = 0;
while (nIndex < str.GetLength())
{
//Passes a space in begin string
if (GetIndexNextAlphaNum(str, nIndex))
{
nBegin = nIndex;
//Searching end of the style name
chSymbol = GetIndexNextChars(str, nIndex, _T(" {"));
if ((nIndex > nBegin) && (0 != chSymbol))
{
strName = str.Mid(nBegin, nIndex - nBegin);
if (!strName.IsEmpty())
{
if (chSymbol != _T(' '))
nIndex --;
chSymbol = GetIndexNextChars(str, nIndex, _T("{"));
if (0 != chSymbol)
{
nBegin = nIndex + 1;
chSymbol = GetIndexNextChars(str, nIndex, _T("}"));
if ((nIndex > nBegin) && (0 != chSymbol))
{
strProperty = str.Mid(nBegin, nIndex - nBegin);
SetTextStyle(strName, strProperty);
} //if
} //if
} //if
} //if
} //if
} //while
} //if
} //End SetCssStyles
LPCTSTR CPPHtmlDrawer::GetCssStyles()
{
return (LPCTSTR)m_strCssStyles;
} //End GetCssStyles
LPCTSTR CPPHtmlDrawer::GetTextStyle(LPCTSTR lpszStyleName)
{
CPPString name = (CPPString)lpszStyleName;
name.MakeLower();
iter_mapStyles iterMap = m_mapStyles.find(name);
if (iterMap != m_mapStyles.end())
return (LPCTSTR)iterMap->second;
//Not found
return NULL;
} //End GetTextStyle
void CPPHtmlDrawer::SetTextStyle(LPCTSTR lpszStyleName, LPCTSTR lpszStyleValue)
{
CPPString name = (CPPString)lpszStyleName;
name.MakeLower();
iter_mapStyles iterMap = m_mapStyles.find(name);
if (iterMap != m_mapStyles.end())
{
//Modifies
iterMap->second = (CPPString)lpszStyleValue;
}
else
{
//Add new
m_mapStyles.insert(std::make_pair(name, (CPPString)lpszStyleValue));
} //if
} //End SetTextStyle
void CPPHtmlDrawer::RemoveTextStyle(LPCTSTR lpszStyleName)
{
CPPString name = (CPPString)lpszStyleName;
name.MakeLower();
iter_mapStyles iterMap = m_mapStyles.find(name);
if (iterMap == m_mapStyles.end())
return; //item was not found
m_mapStyles.erase(iterMap);
} //End RemoveTextStyle
void CPPHtmlDrawer::AddToTextStyle(LPCTSTR lpszStyleName, LPCTSTR lpszAddStyle)
{
} //End AddToTextStyle
void CPPHtmlDrawer::UnpackTextStyle(CPPString strStyle, _STRUCT_CHANGESTYLE & cs)
{
//Gets a string
strStyle.MakeLower();
if (strStyle.IsEmpty())
return;
CPPString strName;
CPPString strParameter;
int nBegin;
TCHAR chSymbol;
int nIndex = 0;
CPPString str;
while (nIndex < strStyle.GetLength())
{
//Passes a space in begin string
if (GetIndexNextAlphaNum(strStyle, nIndex))
{
nBegin = nIndex;
//Searching end of the style name
chSymbol = GetIndexNextChars(strStyle, nIndex, _T(" :"));
if (0 != chSymbol)
{
//Gets a property's name
strName = strStyle.Mid(nBegin, nIndex - nBegin);
//Gets a property's value
strParameter = GetParameterString(strStyle, nIndex, _T(':'));
//Analyzing name
if (strName == _T("font-size"))
{
cs.nSizeFont = GetLengthUnit(strParameter, cs.nSizeFont, TRUE);
}
else if (strName == _T("font-family"))
{
if (!strParameter.IsEmpty())
cs.sFaceFont = strParameter;
}
else if (strName == _T("font-style"))
{
cs.bItalicFont = GetStyleFontStyle(strParameter, cs.bItalicFont);
}
else if (strName == _T("font-weight"))
{
cs.nWeightFont = GetStyleFontWeight(strParameter, cs.nWeightFont);
}
else if (strName == _T("text-align"))
{
cs.nHorzAlign = GetStyleHorzAlign(strParameter, cs.nHorzAlign);
}
else if (strName == _T("text-transform"))
{
cs.nTextTransform = GetStyleTextTransform(strParameter, cs.nTextTransform);
}
else if (strName == _T("color"))
{
if (m_bIsEnable)
cs.crText = GetStyleColor(strParameter, cs.crText);
else
cs.crText = GetColorByName("");
}
else if (strName == _T("background-color"))
{
if (((strParameter == _T("transparent")) && strParameter.IsEmpty()) || !m_bIsEnable)
{
cs.nBkMode = TRANSPARENT;
}
else
{
cs.nBkMode = OPAQUE;
cs.crBkgnd = GetStyleColor(strParameter, cs.crBkgnd);
} //if
}
else if (strName == _T("text-decoration"))
{
StyleTextDecoration(strParameter, cs);
}
else if (strName == _T("vertical-align"))
{
cs.nVertAlign = GetStyleVertAlign(strParameter, cs.nVertAlign);
}
else if (strName == _T("border-color"))
{
if (m_bIsEnable)
cs.crBorderLight = GetStyleColor(strParameter, cs.crBorderLight);
else
cs.crBorderLight = GetColorByName("");
cs.crBorderDark = cs.crBorderLight;
}
else if ((strName == _T("border-width")) || (strName == _T("size")))
{
cs.nBorderWidth = StyleBorderWidth(strParameter, cs.nBorderWidth);
if (!cs.nBorderWidth)
cs.nBorderStyle = CPPDrawManager::PEN_NULL;
else if (CPPDrawManager::PEN_NULL == cs.nBorderStyle)
cs.nBorderStyle = CPPDrawManager::PEN_SOLID;
}
else if (strName == _T("border-style"))
{
cs.nBorderStyle = StyleBorder(strParameter, cs.nBorderStyle);
if ((CPPDrawManager::PEN_NULL != cs.nBorderStyle) && !cs.nBorderWidth)
cs.nBorderWidth = 1;
}
else if (strName == _T("margin"))
{
cs.nMargin = GetLengthUnit(strParameter, cs.nMargin);
}
else if (strName == _T("padding"))
{
cs.nPadding = GetLengthUnit(strParameter, cs.nPadding);
} //if
} //if
} //if
} //while
} //End UnpackTextStyle
BOOL CPPHtmlDrawer::GetStyleFontStyle(CPPString & str, BOOL bDefault)
{
if ((str == _T("normal")) || str.IsEmpty())
{
bDefault = FALSE;
}
else if ((str == _T("italic")) || (str == _T("oblique")))
{
bDefault = TRUE;
} //if
return bDefault;
} //End GetStyleFontStyle
int CPPHtmlDrawer::GetStyleFontWeight(CPPString & str, int nDefault)
{
if ((str == _T("normal")) || str.IsEmpty())
{
nDefault = FW_NORMAL;
}
else if (str == _T("bold"))
{
nDefault = FW_BOLD;
}
else if (str == _T("bolder"))
{
nDefault = 900;
}
else if (str == _T("lighter"))
{
nDefault = 100;
}
else
{
nDefault = _ttoi(str);
} //if
return nDefault;
} //End GetStyleFontWeight
int CPPHtmlDrawer::GetStyleHorzAlign(CPPString & str, int nDefault)
{
if ((str == _T("left")) || str.IsEmpty())
{
nDefault = ALIGN_LEFT;
}
else if (str == _T("center"))
{
nDefault = ALIGN_CENTER;
}
else if (str == _T("right"))
{
nDefault = ALIGN_RIGHT;
}
return nDefault;
} //End GetStyleHorzAlign
int CPPHtmlDrawer::GetStyleVertAlign(CPPString & str, int nDefault)
{
if ((str == _T("baseline")) || str.IsEmpty())
{
nDefault = ALIGN_BASELINE;
}
else if ((str == _T("middle")) || (str == _T("vcenter")))
{
nDefault = ALIGN_VCENTER;
}
else if (str == _T("top"))
{
nDefault = ALIGN_TOP;
}
else if (str == _T("bottom"))
{
nDefault = ALIGN_BOTTOM;
}
return nDefault;
} //End GetStyleVertAlign
int CPPHtmlDrawer::GetStyleTextTransform(CPPString & str, int nDefault)
{
if ((str == _T("none")) || str.IsEmpty())
{
nDefault = TEXT_TRANSFORM_NONE;
}
else if (str == _T("uppercase"))
{
nDefault = TEXT_TRANSFORM_UPPERCASE;
}
else if (str == _T("lowercase"))
{
nDefault = TEXT_TRANSFORM_LOWERCASE;
}
else if (str == _T("capitalize"))
{
nDefault = TEXT_TRANSFORM_CAPITALIZE;
}
return nDefault;
}
COLORREF CPPHtmlDrawer::GetStyleColor(CPPString & str, COLORREF crDefault)
{
// if (!m_bIsEnable)
// return GetColorByName("");
if (!str.IsEmpty())
{
if (str.GetAt(0) == _T('#'))
{
if (str.GetLength() == 7)
{
CPPString strHex = _T("0x");
strHex += str.Mid(5, 2);
strHex += str.Mid(3, 2);
strHex += str.Mid(1, 2);
crDefault = (COLORREF)_tcstoul(strHex, 0, 0);
} //if
}
else if ((str.GetAt(0) >= '0') && (str.GetAt(0) <= '9'))
crDefault = (COLORREF)_tcstoul(str, 0, 0);
else
crDefault = GetColorByName(str, crDefault);
} //if
return crDefault;
} //End GetStyleColor
int CPPHtmlDrawer::GetLengthUnit(CPPString & str, int nDefault, BOOL bFont /* = FALSE */)
{
if (str.IsEmpty())
return nDefault;
if (IsPercentableValue(str))
{
//Percent value
int percent = _ttoi(str.Left(str.GetLength() - 1));
return ::MulDiv(nDefault, percent, 100);
} //if
int nSign = 0;
if (str.GetAt(0) == _T('+')) nSign = 1;
else if (str.GetAt(0) == _T('-')) nSign = -1;
if (0 != nSign) str = str.Right(str.GetLength() - 1);
//ENG: This code fragment fixed by Reinhard Steiner(2004/10/20).
int nValue = _ttoi(str);
CPPString strUnit;
if(str.GetLength() >= 2)
strUnit = str.Right(2);
if (strUnit == _T("px")) nDefault = nValue;
else if (strUnit == _T("ex"))
{
SIZE szText;
CPPString strText = _T("x");
::GetTextExtentPoint32(m_hDC, strText, strText.GetLength(), &szText);
nDefault = nValue * szText.cy;
}
else if (strUnit == _T("em")) nDefault = nValue * m_tm.tmHeight;
else
{
//Gets pixel in inch
nValue *= ::GetDeviceCaps(m_hDC, LOGPIXELSY);
if (strUnit == _T("in")) nDefault = nValue;
else if (strUnit == _T("cm")) nDefault = (int)((double)nValue / 2.54);
else if (strUnit == _T("mm")) nDefault = (int)((double)nValue / 25.4);
else if (strUnit == _T("pt")) nDefault = nValue / 72;
else if (strUnit == _T("pc")) nDefault = nValue / 6;
else
{
nValue = _tcstoul(str, 0, 0);//_ttoi(str);
if ((nValue > 0) && (nValue < 8) && bFont)
{
int nSize [] = {8, 10, 12, 14, 18, 24, 36};
nDefault = nSize [nValue - 1];
}
else
{
nDefault = nValue;
} //if
} //if
} //if
return nDefault;
} //End GetLengthUnit
void CPPHtmlDrawer::StyleTextDecoration(CPPString & str, _STRUCT_CHANGESTYLE & cs)
{
if (str.IsEmpty())
str = _T("none");
int nBegin = 0;
int nEnd = 0;
CPPString strTemp;
while (nBegin < str.GetLength())
{
if (GetIndexNextAlphaNum(str, nBegin))
{
nEnd = nBegin;
GetIndexNextChars(str, nEnd, _T(" ,"));
strTemp = str.Mid(nBegin, nEnd - nBegin);
nBegin = nEnd;
if (strTemp == _T("none"))
{
cs.bUnderlineFont = FALSE;
cs.bStrikeOutFont = FALSE;
cs.bOverlineFont = FALSE;
}
else if (strTemp == _T("underline"))
{
cs.bUnderlineFont = TRUE;
}
else if (strTemp == _T("line-through"))
{
cs.bStrikeOutFont = TRUE;
}
else if (strTemp == _T("overline"))
{
cs.bOverlineFont = TRUE;
} //if
} //if
} //while
} //End StyleTextDecoration
int CPPHtmlDrawer::StyleBorderWidth(CPPString & str, int nDefault)
{
if (str ==_T("thin")) nDefault = ::MulDiv(75, nDefault, 100);
else if (str ==_T("thick")) nDefault = ::MulDiv(125, nDefault, 100);
else if (str !=_T("medium"))nDefault = GetLengthUnit(str, nDefault);
return nDefault;
} //End StyleBorderWidth
int CPPHtmlDrawer::StyleBorder(CPPString & str, int nDefault)
{
if ((str == _T("none")) || str.IsEmpty()) nDefault = CPPDrawManager::PEN_NULL;
else if (str == _T("solid")) nDefault = CPPDrawManager::PEN_SOLID;
else if (str == _T("dotted")) nDefault = CPPDrawManager::PEN_DOT;
else if (str == _T("dashed")) nDefault = CPPDrawManager::PEN_DASH;
else if (str == _T("double")) nDefault = CPPDrawManager::PEN_DOUBLE;
return nDefault;
} //End StyleBorder
void CPPHtmlDrawer::SetDefaultStyles(_STRUCT_CHANGESTYLE & cs)
{
m_defStyle.strTag.Empty(); //The name of the last opened tag
//Font
m_defStyle.nSizeFont = 16; //The height of the logic font
m_defStyle.nWeightFont = FW_NORMAL; //The weight of the logic font
m_defStyle.bItalicFont = FALSE; //Is italic logic font?
m_defStyle.bUnderlineFont = FALSE;//Is underline logic font?
m_defStyle.bStrikeOutFont = FALSE;//Is strikeout logic font?
m_defStyle.bOverlineFont = FALSE; //Is overline logic font?
m_defStyle.sFaceFont = _T("Verdana"); //The face name of the logic font
//Color
m_defStyle.crText = RGB (0, 0, 0); //The foreground color
m_defStyle.crBkgnd = RGB (255, 255, 255); //The background color (also begin for the gradient)
m_defStyle.crBorderLight = RGB (0, 0, 0); //The border color
m_defStyle.crBorderDark = RGB (0, 0, 0); //The border color
m_defStyle.crMidBkgnd = RGB (255, 255, 255);//The middle background color
m_defStyle.crEndBkgnd = RGB (255, 255, 255);//The end background color
//Fill
m_defStyle.nBkMode = TRANSPARENT; //The background mode for the text (TRANSPARENT, OPAQUE)
m_defStyle.nFillBkgnd = -1; //The fill effect of the background
m_defStyle.strNameResBk.Empty();
//Align
m_defStyle.nHorzAlign = ALIGN_LEFT; //The horizontal align
m_defStyle.nVertAlign = ALIGN_BASELINE; //The vertical align
//Border
m_defStyle.nBorderStyle = CPPDrawManager::PEN_NULL; //The border style
m_defStyle.nBorderWidth = 0; //The width of the border
//Text
m_defStyle.nTextTransform = TEXT_TRANSFORM_NONE;//Transformation of the text (NONE, UPPERCASE, LOWERCASE, CAPITALIZE)
//Margins
m_defStyle.nMargin = 2;
//Padding
m_defStyle.nPadding = 0;
//Hyperlink
m_defStyle.nTypeLink = LINK_NONE; //The type of the link (NONE, HREF, MESSAGE)
m_defStyle.sHyperlink.Empty(); //The additional parameter for the link
} //SetDefaultStyles
/////////////////////////////////////////////////////////////////
// Search body of the next tag
//---------------------------------------------------------------
// Parameters:
// In: str - a string with html text
// nIndex - an index of the first char to the searching in the string
// Out: nIndex - an index of the char in the string after found tag's text
// strTag - a string contained the tag's text if was found
// Return: A string before found tag's text
/////////////////////////////////////////////////////////////////
CPPString CPPHtmlDrawer::SearchNextTag(CPPString & str, CPPString & strTag, int & nIndex)
{
int nBegin;
CPPString sText = _T("");
strTag.Empty();
while (nIndex < str.GetLength())
{
nBegin = nIndex;
//Searching a chars of the begin tag
nIndex = str.Find(_T("<"), nIndex);
if (nIndex < 0)
nIndex = str.GetLength(); //A tag wasn't found
sText += str.Mid(nBegin, nIndex - nBegin);
if (nIndex < str.GetLength())
{
//May be it is a begin of the tag?
if ((nIndex < (str.GetLength() - 1)) && (_T('<') != str.GetAt(nIndex + 1)))
{
//Yes of cause!!!
strTag = GetTagBody(str, nIndex);
return sText;
}
//No, it is a char '<'
sText += _T("<");
nIndex += 2;
break;
} //if
} //while
return sText;
} //End SearchNextTag
/////////////////////////////////////////////////////////////////
// CPPHtmlDrawer::GetTagBody
// Gets a name of tag with a parameters
//---------------------------------------------------------------
// Parameters:
// [in]
// str - a string with html text
// nIndex - an index of the begin of the tag.
// [out]
// nIndex - an index of char after the tag
//---------------------------------------------------------------
// Return values:
// A tag's name .
/////////////////////////////////////////////////////////////////
CPPString CPPHtmlDrawer::GetTagBody(CPPString & str, int & nIndex)
{
CPPString sTagName = _T("");
//ENG: Search the tag's end
//RUS: ���� ��������� ����
int nEndOfTag = str.Find(_T('>'), nIndex);
//ENG: The tag's end was found. Passes a tag's begin char ('<')
//RUS: ����� ���� ������� ���������� ������ ������ ����
nIndex++;
if (nEndOfTag > nIndex)
{
//ENG: Gets a full body of tag
//RUS: �������� ������ ������ ����
sTagName = str.Mid(nIndex, nEndOfTag - nIndex);
//ENG: Jump to next char after the tag
//RUS: ������������ �� ��������� �� ����� ������
nIndex = nEndOfTag + 1;
} //if
return sTagName;
} //End of GetTagBody
/////////////////////////////////////////////////////////////////
// Split a tag to his name and properties
//---------------------------------------------------------------
// Parameters:
// In: sTag - a string with tag's text
// Out: sTag - a tag's name
// Return: A property's string
/////////////////////////////////////////////////////////////////
CPPString CPPHtmlDrawer::SplitTag(CPPString & sTag)
{
CPPString sParam(_T(""));
int nIndex = 0;
TCHAR tch = GetIndexNextChars(sTag, nIndex, _T(" ="));
if (tch != _T('\0'))
{
//ENG: The separator was found. Splits a tag's body to his name and his parameteres
//RUS: ����������� ������. ��������� ���� ���� �� ��� � ���������
sParam = sTag.Mid(nIndex);
sTag = sTag.Left(nIndex);
sParam.TrimLeft(_T(' '));
} //if
return sParam;
} //End of SplitTag
CPPString CPPHtmlDrawer::GetNextProperty(CPPString & str, int & nIndex, CPPString & sProp)
{
CPPString sValue(_T(""));
sProp.Empty();
//Passes the spaces before a property
if (GetIndexNextAlphaNum(str, nIndex))
{
//The begin of the property was found
int nBegin = nIndex;
//Searching end of the property
GetIndexNextChars(str, nIndex, _T(" ="));
//Gets a property's string
sProp = str.Mid(nBegin, nIndex - nBegin);
TCHAR chFound = GetIndexNextNoChars(str, nIndex, _T(" "));
if (_T('=') == chFound)
{
chFound = GetIndexNextNoChars(str, nIndex, _T(" ="));
if ((_T('\'') == chFound) || (_T('\"') == chFound))
{
nIndex++;
}
else
{
chFound = _T(' ');
} //if
sValue += chFound;
nBegin = nIndex;
GetIndexNextChars(str, nIndex, sValue);
sValue = str.Mid(nBegin, nIndex - nBegin);
nIndex ++;
} //if
} //if
return sValue;
} //End of GetNextProperty
/////////////////////////////////////////////////////////////////
// Searching the next property of the tag
//---------------------------------------------------------------
// Parameters:
// In: str - a string with html text
// nIndex - an index of the first char to the searching in the string
// Out: nIndex - an index of the char in the string after found tag's text
// Return: A property's string
/////////////////////////////////////////////////////////////////
CPPString CPPHtmlDrawer::SearchPropertyOfTag(CPPString & str, int & nIndex)
{
CPPString sText = _T("");
//Passes the spaces before a property
if (GetIndexNextAlphaNum(str, nIndex))
{
//The begin of the property was found
int nBegin = nIndex;
//Searching end of the property
TCHAR chFound = GetIndexNextChars(str, nIndex, _T(" ="));
//Gets a property's string
sText = str.Mid(nBegin, nIndex - nBegin);
} //if
return sText;
} //End SearchPropertyOfTag
/////////////////////////////////////////////////////////////////
// Search a tag
//---------------------------------------------------------------
// Parameters:
// In: str - a string with html text
// nIndex - an index of the first char to the searching in the string
// Out: nIndex - an index of the first char of the tag
// Return: TRUE if specified tag was found
//---------------------------------------------------------------
// Example: (strTag = "table") or (strTag = "/table")
/////////////////////////////////////////////////////////////////
BOOL CPPHtmlDrawer::SearchTag(CPPString & str, int & nIndex, CPPString strTag)
{
strTag = _T("<") + strTag;
while (nIndex < str.GetLength())
{
nIndex = str.Find(strTag, nIndex);
if (nIndex < 0)
nIndex = str.GetLength();
else
{
if (nIndex > 0)
{
if (str.GetAt(nIndex - 1) != _T('<'))
return TRUE;
nIndex += 2;
}
else return TRUE;
} //if
}
return FALSE;
} //End SearchTag
/////////////////////////////////////////////////////////////////
// Search a first alpha_num chars or first arithmetic char
//---------------------------------------------------------------
// Parameters:
// In: str - a string with html text
// nIndex - an index of the first char to the searching in the string
// Out: nIndex - an index of the first found char
// Return: TRUE if specified char was found
/////////////////////////////////////////////////////////////////
BOOL CPPHtmlDrawer::GetIndexNextAlphaNum(CPPString & str, int & nIndex, BOOL bArithmetic /* = FALSE */)
{
TCHAR ch;
for (; nIndex < str.GetLength(); nIndex++)
{
ch = str.GetAt(nIndex);
if ((ch >= _T('0')) && (ch <= _T('9')))
return TRUE;
if ((ch >= _T('A')) && (ch <= _T('Z')))
return TRUE;
if ((ch >= _T('a')) && (ch <= _T('z')))
return TRUE;
if (ch == _T('.'))
return TRUE;
if (bArithmetic)
{
if ((_T('+') == ch) || (_T('-') == ch) ||
(_T('*') == ch) || (_T('/') == ch))
return TRUE;
} //if
} //for
return FALSE;
} //End GetIndexNextAlphaNum
/////////////////////////////////////////////////////////////////
// Search a first char of the chars set
//---------------------------------------------------------------
// Parameters:
// In: str - a string with html text
// nIndex - an index of the first char to the searching in the string
// strChars - the set of the chars
// Out: nIndex - an index of the first found char
// Return: A found char or zero if chars was not found
/////////////////////////////////////////////////////////////////
TCHAR CPPHtmlDrawer::GetIndexNextChars(CPPString & str, int & nIndex, CPPString strChars)
{
int i;
for (; nIndex < str.GetLength(); nIndex++)
{
for (i = 0; i < strChars.GetLength(); i++)
{
if (str.GetAt(nIndex) == strChars.GetAt(i))
return str.GetAt(nIndex);
} //for
} //for
return 0;
} //End GetIndexNextChars
/////////////////////////////////////////////////////////////////
// Search a first char isn't specified in chars set
//---------------------------------------------------------------
// Parameters:
// In: str - a string with html text
// nIndex - an index of the first char to the searching in the string
// strChars - the set of the chars
// Out: nIndex - an index of the first char isn't from chars set
// Return: A found char or zero if all chars was specified in the chars set
/////////////////////////////////////////////////////////////////
TCHAR CPPHtmlDrawer::GetIndexNextNoChars(CPPString & str, int & nIndex, CPPString strChars)
{
int i;
BOOL bFound;
for (; nIndex < str.GetLength(); nIndex++)
{
bFound = FALSE;
for (i = 0; (i < strChars.GetLength()) && !bFound; i++)
{
if (str.GetAt(nIndex) == strChars.GetAt(i))
bFound = TRUE;
} //for
if (!bFound)
return str.GetAt(nIndex);
} //for
return 0;
} //End GetIndexNextNoChars
/////////////////////////////////////////////////////////////////
// Is exist a property's parameter?
//---------------------------------------------------------------
// Parameters:
// In: str - a string with html text
// nIndex - an index of the first char to the searching in the string
// chSeparator - the char is a begin of the parameter
// Out: nIndex - an index of the begin parameter (if it exist) or the begin of the next property
// Return: TRUE if parameter was found
/////////////////////////////////////////////////////////////////
BOOL CPPHtmlDrawer::GetBeginParameter(CPPString & str, int & nIndex, TCHAR chSeparator /* = _T(':') */)
{
TCHAR ch;
for (; nIndex < str.GetLength(); nIndex++)
{
//Gets a current char
ch = str.GetAt(nIndex);
if (_T(' ') != ch)
{
//if it is not space char
if (chSeparator == ch)
{
//if begin of the property's parameter was found
nIndex ++; //jump to the next char after a begin parameter
return TRUE;
}
else
{
return FALSE;
}//if
} //if
} //for
return FALSE;
} //End GetBeginParameter
/////////////////////////////////////////////////////////////////
// Gets a parameter for the currrent property
//---------------------------------------------------------------
// Parameters:
// In: str - a string with html text
// nIndex - an index of the first char to the searching in the string
// chSeparator - the char is a begin of the parameter
// Out: nIndex - an index of the first char after the parameter
// Return: String of the property's parameter (empty if it is not exist)
/////////////////////////////////////////////////////////////////
CPPString CPPHtmlDrawer::GetParameterString(CPPString & str, int & nIndex, TCHAR chBeginParam /* = _T(':') */, CPPString strSeparators /* = _T(";") */)
{
if (GetBeginParameter(str, nIndex, chBeginParam))
{
//Parameter for the current property was found
TCHAR ch = GetIndexNextNoChars(str, nIndex, strSeparators + _T(" "));
if (0 != ch)
{
int nBegin = nIndex;
if (_T('"') == str.GetAt(nIndex))
{
nIndex++;
TCHAR ch = GetIndexNextChars(str, nIndex, _T("\""));
if (_T('"') == ch)
{
nIndex ++;
return str.Mid(nBegin + 1, nIndex - nBegin - 2);
} //if
}
else
{
GetIndexNextChars(str, nIndex, strSeparators);
return str.Mid(nBegin, nIndex - nBegin);
} //if
} //if
} //if
return _T("");
} //End GetParameterString
/////////////////////////////////////////////////////////////////
// Gets a name of the tag
//---------------------------------------------------------------
// Parameters:
// In: str - a tag's string
// nIndex - an index of the first char to the searching in the string
// Out: nIndex - an index of the first char after the parameter
// Return: Name of the tag (empty if it is not exist)
/////////////////////////////////////////////////////////////////
CPPString CPPHtmlDrawer::GetNameOfTag(CPPString & str, int & nIndex)
{
CPPString strName = _T("");
GetIndexNextNoChars(str, nIndex, _T(" "));
int nBegin = nIndex;
GetIndexNextChars(str, nIndex, _T(" ="));
if (nIndex > nBegin)
strName = str.Mid(nBegin, nIndex - nBegin);
return strName;
} //End GetNameOfTag
/////////////////////////////////////////////////////
// Gets dimensions of the table
//---------------------------------------------------
// In: sTable - the string contains a HTML table
// Return: cx - number of the columns
// cy - number of the row
/////////////////////////////////////////////////////
SIZE CPPHtmlDrawer::GetTableDimensions(CPPString & sTable)
{
//ENG: A table dimensions by default
//RUS: ������� ������� �� ���������
SIZE szTable = {0, 0};
int nIndex = 0;
int nCol = 0;
while (nIndex < sTable.GetLength())
{
//ENG: Search a begin of the row
//RUS: ���� ������ ������
if (SearchTag(sTable, nIndex, _T("tr")))
{
//ENG: Increment count of the rows
//RUS: ����������� ���������� �����
szTable.cy++;
//ENG: Count of the columns in current row
//RUS: ���������� ������� � ������� ������
nCol = 0;
int nEndRow;
int nNewCell;
do
{
nEndRow = nNewCell = nIndex;
//ENG: Search an end of the row or a begin of the cell
//RUS: ���� ����� ������ ��� ������ ������
SearchTag(sTable, nEndRow, _T("/tr"));
SearchTag(sTable, nNewCell, _T("td"));
if (nNewCell < nEndRow)
{
nIndex = nNewCell;
//ENG: Passes a tag body and get a properties of the tag
//RUS: ���������� ��� ������ ������ � �������� ������ ������� ����
CPPString sTag;
SearchNextTag(sTable, sTag, nNewCell);
CPPString sProperties = SplitTag(sTag);
//ENG: Analyses a properties of the tag
//RUS: ����������� �������� ����
STRUCT_CHANGESTYLE style;
SIZE szSpan = AnalyseCellParam(sProperties, style, TRUE);
//ENG: Increment count of the cells
//RUS: ����������� ���������� ����� � ������
nCol += szSpan.cx;
//ENG: Jump to end of the cell
//RUS: ��������� �� ����� ������
SearchEndOfCell(sTable, nIndex);
} //if
} while (nNewCell < nEndRow);
nIndex = nEndRow;
if (nCol > szTable.cx)
szTable.cx = nCol;
} //if
} //while
return szTable;
} //End GetTableDimensions
/////////////////////////////////////////////////////
// CPPHtmlDrawer::SearchEndOfTable
// Searching the end of the table
//---------------------------------------------------
// Parameter:
// str - the string contains a HTML table
// nIndex - index of the first char after the <table> tag
// Return values:
// nIndex - index of the begin char of a </table> tag
/////////////////////////////////////////////////////
void CPPHtmlDrawer::SearchEndOfTable(CPPString & str, int & nIndex)
{
int nBeginTable = nIndex + 7;
int nEndTable = nIndex + 7;
int nTable = 1;
do
{
SearchTag(str, nBeginTable, _T("table"));
SearchTag(str, nEndTable, _T("/table"));
if (nBeginTable < nEndTable)
{
nTable++;
nBeginTable += 7;
}
else if (nEndTable < nBeginTable)
{
nTable --;
nEndTable += 8;
} //if
}
while ((nBeginTable != nEndTable) && nTable); //while
nIndex = nEndTable - 8;
} //End SearchEndOfTable
/////////////////////////////////////////////////////
// CPPHtmlDrawer::SearchEndOfRow
// Searching the end of the row
//---------------------------------------------------
// Parameter:
// str - the string contains a HTML table
// nIndex - index of the first char after the <tr> tag
// Return values:
// nIndex - index of the begin char of a </tr> tag
/////////////////////////////////////////////////////
void CPPHtmlDrawer::SearchEndOfRow(CPPString & str, int & nIndex)
{
nIndex += 4;
int nBeginRow, nEndRow, nStartTable;
int nRow = 1;
do
{
nBeginRow = nEndRow = nStartTable = nIndex;
SearchTag(str, nBeginRow, _T("tr"));
SearchTag(str, nEndRow, _T("/tr"));
SearchTag(str, nStartTable, _T("table"));
if ((nStartTable < nBeginRow) && (nStartTable < nEndRow))
{
SearchEndOfTable(str, nStartTable);
nIndex = nStartTable + 6;
}
else if (nBeginRow < nEndRow)
{
nRow++;
nIndex = nBeginRow + 4;
}
else if (nEndRow < nBeginRow)
{
nRow --;
nIndex = nEndRow + 5;
} //if
}
while ((nIndex < str.GetLength()) && nRow); //while
nIndex -= 5;
} //End SearchEndOfRow
/////////////////////////////////////////////////////
// CPPHtmlDrawer::SearchEndOfCell
// Searching the end of the cell
//---------------------------------------------------
// Parameter:
// str - the string contains a HTML table
// nIndex - index of the first char after the <td> tag
// Return values:
// nIndex - index of the begin char of a </td> tag
/////////////////////////////////////////////////////
void CPPHtmlDrawer::SearchEndOfCell(CPPString & str, int & nIndex)
{
nIndex += 4;
int nEndCell, nStartTable;
do
{
nEndCell = nStartTable = nIndex;
SearchTag(str, nEndCell, _T("/td"));
SearchTag(str, nStartTable, _T("table"));
if (nStartTable < nEndCell)
{
SearchEndOfTable(str, nStartTable);
nEndCell = nIndex = nStartTable + 6;
}
else
{
nIndex = nEndCell + 5;
} //if
}
while (nStartTable < nEndCell); //while
nIndex -= 5;
} //End SearchEndOfCell
///////////////////////////////////////////////////////////////////////
// Analysing the cell parameters
//---------------------------------------------------------------------
// Parameters:
// In: strTag - str string contains parameters of the <table>, <td> or <tr> tags
// cs - the structures contains the current styles
// bTable -
// Out: cs - the structures contains the new styles
///////////////////////////////////////////////////////////////////////
SIZE CPPHtmlDrawer::AnalyseCellParam(CPPString & sProperties, _STRUCT_CHANGESTYLE & cs, BOOL bTable)
{
SIZE szSpan = {1, 1};
if (sProperties.IsEmpty())
return szSpan;
int i = 0;
CPPString sParameter;
CPPString sValue;
while (i < sProperties.GetLength())
{
//ENG: Searching a parameters of a tag
//RUS: ����� ���������� ����
sValue = GetNextProperty(sProperties, i, sParameter);
//ENG: Processes the specific parameters for <table> tag.
//RUS: ������������ ������������� ��� ���� <table> ���������
if(bTable)
{
if (sParameter == _T("cellpadding"))
{
cs.nMargin = GetLengthUnit(sValue, cs.nMargin);
}
else if (sParameter == _T("cellspacing"))
{
cs.nPadding = GetLengthUnit(sValue, cs.nPadding);
}
else if (sParameter == _T("background"))
{
cs.strNameResBk = sValue;
} //if
} //if
if (sParameter == _T("rowspan"))
{
szSpan.cy = GetLengthUnit(sValue, szSpan.cy);
}
else if (sParameter == _T("colspan"))
{
szSpan.cx = GetLengthUnit(sValue, szSpan.cx);
}
else if (sParameter == _T("border"))
{
cs.nBorderWidth = GetLengthUnit(sValue, cs.nBorderWidth);
if (!cs.nBorderWidth)
cs.nBorderStyle = CPPDrawManager::PEN_NULL;
else if (CPPDrawManager::PEN_NULL == cs.nBorderStyle)
cs.nBorderStyle = CPPDrawManager::PEN_SOLID;
}
else if (sParameter == _T("borderstyle"))
{
cs.nBorderStyle = StyleBorder(sValue, cs.nBorderStyle);
if ((CPPDrawManager::PEN_NULL != cs.nBorderStyle) && !cs.nBorderWidth)
cs.nBorderWidth = 1;
}
else if (sParameter == _T("bordercolor"))
{
if (m_bIsEnable)
cs.crBorderLight = GetStyleColor(sValue, cs.crBorderLight);
else
cs.crBorderLight = GetColorByName("");
cs.crBorderDark = cs.crBorderLight;
}
else if (sParameter == _T("bordercolorlight"))
{
if (m_bIsEnable)
cs.crBorderLight = GetStyleColor(sValue, cs.crBorderLight);
else
cs.crBorderLight = GetColorByName("");
}
else if (sParameter == _T("bordercolordark"))
{
if (m_bIsEnable)
cs.crBorderDark = GetStyleColor(sValue, cs.crBorderDark);
else
cs.crBorderDark = GetColorByName("");
}
else if (sParameter == _T("bgcolor"))
{
if (m_bIsEnable)
{
cs.crBkgnd = GetStyleColor(sValue, cs.crBkgnd);
if (cs.nFillBkgnd < 0)
cs.nFillBkgnd = CPPDrawManager::EFFECT_SOLID;
} //if
}
else if (sParameter == _T("bgmidcolor"))
{
if (m_bIsEnable)
cs.crMidBkgnd = GetStyleColor(sValue, cs.crMidBkgnd);
}
else if (sParameter == _T("bgendcolor"))
{
if (m_bIsEnable)
cs.crEndBkgnd = GetStyleColor(sValue, cs.crEndBkgnd);
}
else if (sParameter == _T("bgeffect"))
{
if (m_bIsEnable)
cs.nFillBkgnd = GetStyleBkgndEffect(sValue, cs.nFillBkgnd);
}
else if (sParameter == _T("align"))
{
cs.nHorzAlign = GetStyleHorzAlign(sValue, cs.nHorzAlign);
}
else if (sParameter == _T("valign"))
{
cs.nVertAlign = GetStyleVertAlign(sValue, cs.nVertAlign);
}
else if (sParameter == _T("width"))
{
cs.nCellWidth = GetLengthUnit(sValue, cs.nCellWidth);
}
else if (sParameter == _T("height"))
{
cs.nCellHeight = GetLengthUnit(sValue, cs.nCellHeight);
} //if
} //for
//ENG:
//RUS:
if ((CPPDrawManager::PEN_NULL == cs.nBorderStyle) || !cs.nBorderWidth)
{
cs.nBorderStyle = CPPDrawManager::PEN_NULL;
cs.nBorderWidth = 0;
}
else if (CPPDrawManager::PEN_SOLID != cs.nBorderStyle)
{
cs.nBorderWidth = 1;
} //if
//ENG:
//RUS: ��� ����� ������ ������ ����� 1
if (!bTable && cs.nBorderWidth)
cs.nBorderWidth = 1;
return szSpan;
} //End AnalyseCellParam
///////////////////////////////////////////////////////////////////////
// Analysing the image parameters
//---------------------------------------------------------------------
// Parameters:
// In: sProperties - the sing contains
// si - the structures contains the image parameters
// Out: si - the structures contains the image parameters
///////////////////////////////////////////////////////////////////////
void CPPHtmlDrawer::AnalyseImageParam(CPPString & sProperties, _STRUCT_IMAGE & si)
{
if (sProperties.IsEmpty())
return;
int i = 0;
CPPString sParameter;
CPPString sValue;
while (i < sProperties.GetLength())
{
//ENG: Searching a parameters of a tag
//RUS: ����� ���������� ����
sValue = GetNextProperty(sProperties, i, sParameter);
// sParameter = SearchPropertyOfTag(sProperties, i);
// sValue = GetParameterString(sProperties, i, _T('='), _T(" "));
if (sParameter == _T("index"))
{
si.nIndexImageList = GetLengthUnit(sValue, si.nIndexImageList);
}
else if (sParameter == _T("idres"))
{
si.nIdRes = GetLengthUnit(sValue, si.nIdRes);
}
else if (sParameter == _T("iddll"))
{
si.nIdDll = GetLengthUnit(sValue, si.nIdDll);
}
else if (sParameter == _T("handle"))
{
si.nHandle = GetLengthUnit(sValue, si.nHandle);
}
else if (sParameter == _T("file"))
{
si.strSrcFile = GetStyleString(sValue, si.strSrcFile);
}
else if (sParameter == _T("srcdll"))
{
si.strPathDll = GetStyleString(sValue, si.strPathDll);
}
else if (sParameter == _T("mask"))
{
si.crMask = GetStyleColor(sValue, si.crMask);
si.bUseMask = TRUE;
}
else if (sParameter == _T("style"))
{
si.nStyles = GetStyleImageShortForm(sValue);
si.nHotStyles = si.nStyles;
}
else if (sParameter == _T("hotstyle"))
{
si.nHotStyles = GetStyleImageShortForm(sValue);
}
else if (sParameter == _T("cx"))
{
si.cx = GetLengthUnit(sValue, si.cx);
}
else if (sParameter == _T("cy"))
{
si.cy = GetLengthUnit(sValue, si.cy);
}
else if (sParameter == _T("width"))
{
si.bPercentWidth = IsPercentableValue(sValue);
si.nWidth = GetLengthUnit(sValue, si.nWidth);
}
else if (sParameter == _T("height"))
{
si.bPercentHeight = IsPercentableValue(sValue);
si.nHeight = GetLengthUnit(sValue, si.nHeight);
}
else if (sParameter == _T("speed"))
{
si.nSpeed = GetLengthUnit(sValue, si.nSpeed);
} //if
} //for
} //End AnalyseImageParam
CPPString CPPHtmlDrawer::GetStyleString(CPPString str, CPPString strDefault)
{
if (!str.IsEmpty())
strDefault = str;
return str;
}
///////////////////////////////////////////////////////////////////////
// Analysing the short form of the font style
//---------------------------------------------------------------------
// Parameters:
// In: str - string contains parameters of the font in the short form
// Short form styles
// [+] - positive style
// [-] - inverse style
// [b] - bold
// [i] - italic
// [u] - underlined
// [s] - strikeout
// [o] - overline
///////////////////////////////////////////////////////////////////////
void CPPHtmlDrawer::GetStyleFontShortForm(CPPString & str)
{
if (!str.IsEmpty())
{
BOOL bSetValue = TRUE;
for (int i = 0; i < str.GetLength(); i++)
{
switch (str.GetAt(i))
{
case _T('-'):
bSetValue = FALSE;
break;
case _T('+'):
bSetValue = TRUE;
break;
case _T('b'):
m_defStyle.nWeightFont = (bSetValue) ? FW_BOLD : FW_NORMAL;
bSetValue = TRUE;
break;
case _T('i'):
m_defStyle.bItalicFont = bSetValue;
bSetValue = TRUE;
break;
case _T('u'):
m_defStyle.bUnderlineFont = bSetValue;
bSetValue = TRUE;
break;
case _T('s'):
m_defStyle.bStrikeOutFont = bSetValue;
bSetValue = TRUE;
break;
case _T('o'):
m_defStyle.bOverlineFont = bSetValue;
bSetValue = TRUE;
break;
} //switch
} //for
} //if
} //End GetStyleFontShortForm
//Get font style value
UINT CPPHtmlDrawer::GetStyleImageShortForm(CPPString & str)
{
UINT uStyle = 0; //Original image
if (!str.IsEmpty())
{
for (int i = 0; i < str.GetLength(); i++)
{
switch (str.GetAt(i))
{
case _T('d'):
uStyle |= IMAGE_EFFECT_DARKEN;
break;
case _T('g'):
uStyle |= IMAGE_EFFECT_GRAYEN;
break;
case _T('s'):
if (m_szOffsetShadow.cx || m_szOffsetShadow.cy)
{
if (m_bGradientShadow)
uStyle |= IMAGE_EFFECT_GRADIENT_SHADOW;
else uStyle |= IMAGE_EFFECT_MONO_SHADOW;
} //if
break;
case _T('l'):
uStyle |= IMAGE_EFFECT_LIGHTEN;
break;
} //switch
} //for
} //if
return uStyle;
} //End GetStyleImageShortForm
BOOL CPPHtmlDrawer::IsPercentableValue(CPPString & str)
{
if (!str.IsEmpty())
{
if (str.GetAt(str.GetLength() - 1) == _T('%'))
return TRUE;
}
return FALSE;
}
int CPPHtmlDrawer::GetStyleBkgndEffect(CPPString & str, int nDefault)
{
if (!str.IsEmpty())
{
if (str == _T("transparent"))
nDefault = -1;
else if (str == _T("solid"))
nDefault = CPPDrawManager::EFFECT_SOLID;
else if (str == _T("hgradient"))
nDefault = CPPDrawManager::EFFECT_HGRADIENT;
else if (str == _T("vgradient"))
nDefault = CPPDrawManager::EFFECT_VGRADIENT;
else if (str == _T("hcgradient"))
nDefault = CPPDrawManager::EFFECT_HCGRADIENT;
else if (str == _T("vcgradient"))
nDefault = CPPDrawManager::EFFECT_VCGRADIENT;
else if (str == _T("3hgradient"))
nDefault = CPPDrawManager::EFFECT_3HGRADIENT;
else if (str == _T("3vgradient"))
nDefault = CPPDrawManager::EFFECT_3VGRADIENT;
#ifdef USE_SHADE
else if (str == _T("noise"))
nDefault = CPPDrawManager::EFFECT_NOISE;
else if (str == _T("diagshade"))
nDefault = CPPDrawManager::EFFECT_DIAGSHADE;
else if (str == _T("hshade"))
nDefault = CPPDrawManager::EFFECT_HSHADE;
else if (str == _T("vshade"))
nDefault = CPPDrawManager::EFFECT_VSHADE;
else if (str == _T("hbump"))
nDefault = CPPDrawManager::EFFECT_HBUMP;
else if (str == _T("vbump"))
nDefault = CPPDrawManager::EFFECT_VBUMP;
else if (str == _T("softbump"))
nDefault = CPPDrawManager::EFFECT_SOFTBUMP;
else if (str == _T("hardbump"))
nDefault = CPPDrawManager::EFFECT_HARDBUMP;
else if (str == _T("metal"))
nDefault = CPPDrawManager::EFFECT_METAL;
#endif
else nDefault = GetLengthUnit(str, nDefault);
} //if
return nDefault;
} //End GetStyleBkgndEffect
int CPPHtmlDrawer::GetTableWidth(CPPString & str, int nClientWidth, int nMinWidth, BOOL bSet /* = FALSE */)
{
if (!str.IsEmpty())
{
int i = 0;
CPPString strProperty;
CPPString strParameter;
while (i < str.GetLength())
{
strProperty = SearchPropertyOfTag(str, i);
strParameter = GetParameterString(str, i, _T('='), _T(" "));
strProperty.MakeLower();
if (strProperty == _T("width"))
{
if (IsPercentableValue(strParameter))
{
int nWidth = GetLengthUnit(strParameter, 100);
if (bSet)
{
if (nWidth <= 100)
nClientWidth = ::MulDiv(nMinWidth, 100, nWidth);
else
nClientWidth = ::MulDiv(nMinWidth, nWidth, 100);
}
else
{
if (nWidth < 100)
nClientWidth = ::MulDiv(nClientWidth, nWidth, 100);
} //if
}
else
{
nClientWidth = GetLengthUnit(strParameter, nMinWidth);
} //if
break;
} //if
} //while
} //if
if (nClientWidth < nMinWidth)
nClientWidth = nMinWidth;
return nClientWidth;
} //End GetTableWidth
void CPPHtmlDrawer::DrawBackgroundImage(HDC hDC, int nDestX, int nDestY, int nWidth, int nHeight, CPPString strNameImage)
{
if (!m_bIsEnable)
return;
if (strNameImage.IsEmpty())
return;
if (strNameImage.GetLength() < 6)
return;
HBITMAP hBitmap = NULL;
int nIndex = 0;
if (GetIndexNextAlphaNum(strNameImage, nIndex))
{
int nBegin = nIndex;
//Searching end of the style name
TCHAR chSymbol = GetIndexNextChars(strNameImage, nIndex, _T(" :"));
if (0 != chSymbol)
{
//Gets a property's name
CPPString strName = strNameImage.Mid(nBegin, nIndex - nBegin);
//Gets a property's value
CPPString strParameter = GetParameterString(strNameImage, nIndex, _T(':'));
if (strName == _T("idres"))
{
UINT nID = (UINT)GetLengthUnit(strParameter, 0);
hBitmap = GetBitmapFromResources(nID);
}
else if (strName == _T("iddll"))
{
UINT nID = (UINT)GetLengthUnit(strParameter, 0);
hBitmap = GetBitmapFromDll(nID);
}
else if (strName == _T("file"))
{
hBitmap = GetBitmapFromFile(strParameter);
} //if
} //if
} //if
if (NULL == hBitmap)
return;
SIZE sz;
m_drawmanager.GetSizeOfBitmap(hBitmap, &sz);
HDC hSrcDC = ::CreateCompatibleDC(hDC);
HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hSrcDC, hBitmap);
m_drawmanager.MultipleCopy(hDC, nDestX, nDestY, nWidth, nHeight, hSrcDC, 0, 0, sz.cx, sz.cy);
::SelectObject(hSrcDC, hOldBitmap);
::DeleteDC(hSrcDC);
::DeleteObject(hBitmap);
hBitmap = NULL;
} //End of DrawBackgroundImage
////////////////////////////////////////////////////////////////////
// CPPHtmlDrawer::SetTooltipShadow()
// Sets a image's shadow.
//------------------------------------------------------------------
// Parameters:
// nOffsetX,
// nOffsetY - The offsets of the tooltip's shadow from the tooltip's window.
// nDarkenPercent - So far as colors under the shadow will be darken (0 - 100)
// bGradient - TRUE to use a gradient shadow.
// nDepthX,
// nDepthY - The gradient depths of the tooltip's shadow.
////////////////////////////////////////////////////////////////////
void CPPHtmlDrawer::SetImageShadow(int nOffsetX, int nOffsetY, BYTE nDarkenPercent /* = 50 */,
BOOL bGradient /* = TRUE */, int nDepthX /* = 7 */, int nDepthY /* = 7 */)
{
m_szOffsetShadow.cx = nOffsetX;
m_szOffsetShadow.cy = nOffsetY;
m_szDepthShadow.cx = nDepthX;
m_szDepthShadow.cy = nDepthY;
m_nDarkenShadow = min(100, nDarkenPercent);
m_bGradientShadow = bGradient;
BYTE nColor = ::MulDiv(255, 100 - m_nDarkenShadow, 100);
m_crShadow = RGB(nColor, nColor, nColor);
} //End of SetTooltipShadow
CPPString CPPHtmlDrawer::GetWordWrap(CPPString & str, int nMaxSize, int & nRealSize)
{
int nCurIndex = 0;
int nLastIndex = 0;
SIZE sz = {0, 0};
TCHAR tch = _T(' ');
CPPString sResult = _T("");
while ((sz.cx <= nRealSize) && (0 != tch))
{
nLastIndex = nCurIndex;
nCurIndex ++;
tch = GetIndexNextChars(str, nCurIndex, PPHTMLDRAWER_BREAK_CHARS);
::GetTextExtentPoint32(m_hDC, str, nCurIndex, &sz);
} //while
if (0 == nLastIndex)
{
if (nMaxSize == nRealSize)
{
//RUS: �������� � ������ �� ����������, ������� ����� ��������� ������
// �� ��������, � �� �� ������
sz.cx = 0;
for (int i = 1; i < str.GetLength(); i++)
{
::GetTextExtentPoint32(m_hDC, str, i + 1, &sz);
if (sz.cx > nRealSize)
{
sResult = str.Left(i);
str = str.Mid(i);
::GetTextExtentPoint32(m_hDC, sResult, i, &sz);
nRealSize = sz.cx;
return sResult;
} //if
} //for
::GetTextExtentPoint32(m_hDC, str, i, &sz);
//RUS: ���������� ������� ������, ������� �������
sResult = str;
str.Empty();
}
else
{
//RUS: � ����������� ����� ������� ������ �� ������ �� ������ �����
sz.cx = 0;
} //if
}
else
{
sResult = str.Left(nLastIndex + 1);
str = str.Mid(nLastIndex + 1);
sResult.TrimRight();
::GetTextExtentPoint32(m_hDC, sResult, sResult.GetLength(), &sz);
// str.TrimRight();
str.TrimLeft();
} //if
nRealSize = sz.cx;
return sResult;
} //End of GetWordWrap
int CPPHtmlDrawer::GetCountOfChars(CPPString str, TCHAR tchar /*= _T(' ')*/)
{
int nCount = 0;
//ENG:
//RUS:
for (int i = 0; i < str.GetLength(); i++)
{
if (tchar == str.GetAt(i))
nCount++;
} //if
return nCount;
}