diff options
author | George Hazan <ghazan@miranda.im> | 2020-04-03 20:05:55 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2020-04-03 20:05:55 +0300 |
commit | 6d89b6043c333831aed709e6576fa7d6c247b2ff (patch) | |
tree | 47c6ce4712fc90b1daaed8e37a515f9bcffdcb02 /libs/mTextControl/src/fancy_rtf.cpp | |
parent | e3f92ff9b8922e06a717a84b76c4e43cbb165f28 (diff) |
mTextControl moved to /libs
Diffstat (limited to 'libs/mTextControl/src/fancy_rtf.cpp')
-rw-r--r-- | libs/mTextControl/src/fancy_rtf.cpp | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/libs/mTextControl/src/fancy_rtf.cpp b/libs/mTextControl/src/fancy_rtf.cpp new file mode 100644 index 0000000000..8746d2fc65 --- /dev/null +++ b/libs/mTextControl/src/fancy_rtf.cpp @@ -0,0 +1,171 @@ +#include "stdafx.h" +#include "ImageDataObjectHlp.h" +#include "FormattedTextDraw.h" + +struct BBCodeInfo +{ + wchar_t *start; + wchar_t *end; + bool(*func)(IFormattedTextDraw *ftd, CHARRANGE range, wchar_t *txt, DWORD cookie); + DWORD cookie; +}; + +enum { + BBS_BOLD_S, BBS_BOLD_E, BBS_ITALIC_S, BBS_ITALIC_E, BBS_UNDERLINE_S, BBS_UNDERLINE_E, + BBS_STRIKEOUT_S, BBS_STRIKEOUT_E, BBS_COLOR_S, BBS_COLOR_E, BBS_URL1, BBS_URL2, + BBS_IMG1, BBS_IMG2 +}; + +static bool bbCodeSimpleFunc(IFormattedTextDraw *ftd, CHARRANGE range, wchar_t *, DWORD cookie) +{ + CHARFORMAT cf = { 0 }; + cf.cbSize = sizeof(cf); + switch (cookie) { + case BBS_BOLD_S: + cf.dwMask = CFM_BOLD; + cf.dwEffects = CFE_BOLD; + break; + case BBS_BOLD_E: + cf.dwMask = CFM_BOLD; + break; + case BBS_ITALIC_S: + cf.dwMask = CFM_ITALIC; + cf.dwEffects = CFE_ITALIC; + break; + case BBS_ITALIC_E: + cf.dwMask = CFM_ITALIC; + break; + case BBS_UNDERLINE_S: + cf.dwMask = CFM_UNDERLINE; + cf.dwEffects = CFE_UNDERLINE; + break; + case BBS_UNDERLINE_E: + cf.dwMask = CFM_UNDERLINE; + break; + case BBS_STRIKEOUT_S: + cf.dwMask = CFM_STRIKEOUT; + cf.dwEffects = CFE_STRIKEOUT; + break; + case BBS_STRIKEOUT_E: + cf.dwMask = CFM_STRIKEOUT; + break; + } + + ITextServices *ts = ftd->getTextService(); + + LRESULT lResult; + ts->TxSendMessage(EM_SETSEL, range.cpMin, -1, &lResult); + ts->TxSendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf, &lResult); + ts->TxSendMessage(EM_SETSEL, range.cpMin, range.cpMax, &lResult); + ts->TxSendMessage(EM_REPLACESEL, FALSE, (LPARAM)L"", &lResult); + + return true; +} + +static bool bbCodeImageFunc(IFormattedTextDraw *ftd, CHARRANGE range, wchar_t *txt, DWORD) +{ + ITextServices *ts = ftd->getTextService(); + ITextDocument *td = ftd->getTextDocument(); + + long cnt; + LRESULT lResult; + ts->TxSendMessage(EM_SETSEL, range.cpMin, range.cpMax, &lResult); + IRichEditOle* RichEditOle; + ts->TxSendMessage(EM_GETOLEINTERFACE, 0, (LPARAM)&RichEditOle, &lResult); + td->Freeze(&cnt); + +#ifdef _WIN64 + bool res = InsertBitmap(RichEditOle, CacheIconToEmf((HICON)_wtoi64(txt))); +#else + bool res = InsertBitmap(RichEditOle, CacheIconToEmf((HICON)_wtoi(txt))); +#endif + + td->Unfreeze(&cnt); + RichEditOle->Release(); + return res; +} + +static BBCodeInfo bbCodes[] = +{ + { L"[b]", nullptr, bbCodeSimpleFunc, BBS_BOLD_S }, + { L"[/b]", nullptr, bbCodeSimpleFunc, BBS_BOLD_E }, + { L"[i]", nullptr, bbCodeSimpleFunc, BBS_ITALIC_S }, + { L"[/i]", nullptr, bbCodeSimpleFunc, BBS_ITALIC_E }, + { L"[u]", nullptr, bbCodeSimpleFunc, BBS_UNDERLINE_S }, + { L"[/u]", nullptr, bbCodeSimpleFunc, BBS_UNDERLINE_E }, + { L"[s]", nullptr, bbCodeSimpleFunc, BBS_STRIKEOUT_S }, + { L"[/s]", nullptr, bbCodeSimpleFunc, BBS_STRIKEOUT_E }, + + // { L"[color=", L"]", bbCodeSimpleFunc, BBS_COLOR_S }, + // { L"[/color]", 0, bbCodeSimpleFunc, BBS_COLOR_E } + + { L"[$hicon=", L"$]", bbCodeImageFunc, 0 } + + // { L"[url]", L"[/url]", bbCodeSimpleFunc, BBS_URL1 }, + // { L"[url=", L"]", bbCodeSimpleFunc, BBS_URL2 }, + // { L"[url]", L"[/url]", bbCodeSimpleFunc, BBS_IMG1 }, + // { L"[url=", L"]", bbCodeSimpleFunc, BBS_IMG2 }, +}; +static int bbCodeCount = sizeof(bbCodes) / sizeof(*bbCodes); + +void bbCodeParse(IFormattedTextDraw *ftd) +{ + ITextServices *ts = ftd->getTextService(); + LRESULT lResult; + + int pos = 0; + for (bool found = true; found;) { + found = false; + CHARRANGE fRange; fRange.cpMin = -1; + wchar_t *fText = nullptr; + BBCodeInfo *fBBCode = nullptr; + + for (int i = 0; i < bbCodeCount; i++) { + CHARRANGE range; + + FINDTEXTEX fte; + fte.chrg.cpMin = pos; + fte.chrg.cpMax = -1; + + fte.lpstrText = bbCodes[i].start; + ts->TxSendMessage(EM_FINDTEXTEX, (WPARAM)FR_DOWN, (LPARAM)&fte, &lResult); + if (lResult == -1) + continue; + range = fte.chrgText; + + if (bbCodes[i].end) { + fte.chrg.cpMin = fte.chrgText.cpMax; + fte.lpstrText = bbCodes[i].end; + ts->TxSendMessage(EM_FINDTEXTEX, (WPARAM)FR_DOWN, (LPARAM)&fte, &lResult); + if (lResult == -1) + continue; + range.cpMax = fte.chrgText.cpMax; + } + + if ((fRange.cpMin == -1) || (fRange.cpMin > range.cpMin)) { + fRange = range; + fBBCode = bbCodes + i; + found = true; + + if (fText) + { + delete[] fText; + fText = nullptr; + } + if (bbCodes[i].end) { + TEXTRANGE trg; + trg.chrg.cpMin = fte.chrg.cpMin; + trg.chrg.cpMax = fte.chrgText.cpMin; + trg.lpstrText = new wchar_t[trg.chrg.cpMax - trg.chrg.cpMin + 1]; + ts->TxSendMessage(EM_GETTEXTRANGE, 0, (LPARAM)&trg, &lResult); + fText = trg.lpstrText; + } + } + } + + if (found) { + found = fBBCode->func(ftd, fRange, fText, fBBCode->cookie); + if (fText) delete[] fText; + } + } +} |