diff --git a/src/HomePage.cpp b/src/HomePage.cpp index f8cb0d12a0d9..ceb9d1a6c071 100644 --- a/src/HomePage.cpp +++ b/src/HomePage.cpp @@ -6,6 +6,7 @@ #include "utils/Dpi.h" #include "utils/FileUtil.h" #include "utils/WinUtil.h" +#include "utils/SquareTreeParser.h" #include "wingui/UIModels.h" #include "wingui/Layout.h" @@ -37,12 +38,17 @@ #endif #define ABOUT_LINE_SEP_SIZE 1 -constexpr const char* builtIn = R"( +constexpr const char* promoteBuiltIn = R"( [ Name = Edna URL = https://edna.arslexis.io Info = note taking app for develelopers ] +[ + Name = "ArsLexis" + URL = https://arslexis.io + Info = Various web tools +] )"; constexpr COLORREF kAboutBorderCol = RGB(0, 0, 0); @@ -612,20 +618,38 @@ struct ThumbnailLayout { StaticLinkInfo* sl = nullptr; }; +struct Promote { + struct Promote* next = nullptr; + const char* name = nullptr; + const char* url = nullptr; + const char* info = nullptr; + Promote() = default; + ~Promote(); +}; + +Promote::~Promote() { + str::Free(name); + str::Free(url); + str::Free(info); +} + struct HomePageLayout { // args in - HWND hwnd; - HDC hdc; + HWND hwnd = nullptr; + HDC hdc = nullptr; Rect rc; - MainWindow* win; + MainWindow* win = nullptr; + + Promote* promote = nullptr; Rect rcAppWithVer; // SumatraPDF colorful text + version Rect rcLine; // line under bApp Rect rcIconOpen; - HIMAGELIST himlOpen; - VirtWndText* freqRead; - VirtWndText* openDoc; + HIMAGELIST himlOpen = nullptr; + VirtWndText* freqRead = nullptr; + VirtWndText* openDoc = nullptr; + VirtWndText* hideShowFreqRead = nullptr; Vec thumbnails; // info for each thumbnail ~HomePageLayout(); }; @@ -633,10 +657,44 @@ struct HomePageLayout { HomePageLayout::~HomePageLayout() { delete freqRead; delete openDoc; + ListDelete(promote); +} + +static Promote* ParsePromote(const char* s) { + if (str::IsEmptyOrWhiteSpace(s)) { + return nullptr; + } + SquareTreeNode* root = ParseSquareTree(s); + if (!root) { + return nullptr; + } + SquareTreeNode* node; + Promote* first = nullptr; + for (auto& i : root->data) { + node = i.child; + if (!node || node->data.Size() != 3) { + continue; + } + Promote* p = new Promote(); + p->name = str::Dup(node->GetValue("Name")); + p->url = str::Dup(node->GetValue("URL")); + p->info = str::Dup(node->GetValue("Info")); + bool ok = !str::IsEmptyOrWhiteSpace(p->name) && !str::IsEmptyOrWhiteSpace(p->url) && !str::IsEmptyOrWhiteSpace(p->info); + if (!ok) { + delete p; + continue; + } + ListInsertEnd(&first, p); + } + delete root; + return first; } // layout homepage in r void LayoutHomePage(HomePageLayout& l) { + + l.promote = ParsePromote(promoteBuiltIn); + Vec fileStates; gFileHistory.GetFrequencyOrder(fileStates); auto hwnd = l.hwnd; diff --git a/src/utils/SquareTreeParser.cpp b/src/utils/SquareTreeParser.cpp index 08b41690a179..26484fa22909 100644 --- a/src/utils/SquareTreeParser.cpp +++ b/src/utils/SquareTreeParser.cpp @@ -99,11 +99,13 @@ SquareTreeNode::~SquareTreeNode() { } const char* SquareTreeNode::GetValue(const char* key, size_t* startIdx) const { - for (size_t i = startIdx ? *startIdx : 0; i < data.size(); i++) { - DataItem& item = data.at(i); + int start = startIdx ? (int)*startIdx : 0; + int n = data.Size(); + for (int i = start; i < n; i++) { + DataItem& item = data.At(i); if (str::EqI(key, item.key) && !item.child) { if (startIdx) { - *startIdx = i + 1; + *startIdx = (size_t)(i + 1); } return item.str; } @@ -112,11 +114,13 @@ const char* SquareTreeNode::GetValue(const char* key, size_t* startIdx) const { } SquareTreeNode* SquareTreeNode::GetChild(const char* key, size_t* startIdx) const { - for (size_t i = startIdx ? *startIdx : 0; i < data.size(); i++) { - DataItem& item = data.at(i); + int start = startIdx ? (int)*startIdx : 0; + int n = data.Size(); + for (int i = start; i < n; i++) { + DataItem& item = data.At(i); if (str::EqI(key, item.key) && item.child) { if (startIdx) { - *startIdx = i + 1; + *startIdx = (size_t)(i + 1); } return item.child; } diff --git a/src/wingui/VirtWnd.cpp b/src/wingui/VirtWnd.cpp index 77717bfa190e..bfd137810c8f 100644 --- a/src/wingui/VirtWnd.cpp +++ b/src/wingui/VirtWnd.cpp @@ -85,6 +85,12 @@ Size VirtWndText::GetIdealSize(bool onlyIfEmpty) { void VirtWndText::Draw(HDC hdc) { ReportIf(lastBounds.IsEmpty()); + COLORREF prevCol = kColorUnset; + int prevBkMode = 0; + if (textColor != kColorUnset) { + prevCol = SetTextColor(hdc, textColor); + } + prevBkMode = SetBkMode(hdc, TRANSPARENT); UINT fmt = DT_NOCLIP | DT_NOPREFIX; if (isRtl) { fmt = fmt | DT_RTLREADING; @@ -94,6 +100,14 @@ void VirtWndText::Draw(HDC hdc) { if (withUnderline) { auto& r = lastBounds; Rect lineRect = {r.x, r.y + sz.dy, sz.dx, 0}; + auto col = GetTextColor(hdc); + ScopedSelectObject pen(hdc, CreatePen(PS_SOLID, 1, col), true); DrawLine(hdc, lineRect); } + if (textColor != kColorUnset) { + SetTextColor(hdc, prevCol); + } + if (prevBkMode != 0) { + SetBkMode(hdc, prevBkMode); + } } diff --git a/src/wingui/VirtWnd.h b/src/wingui/VirtWnd.h index 66e75e463dc6..7a2d08284a10 100644 --- a/src/wingui/VirtWnd.h +++ b/src/wingui/VirtWnd.h @@ -32,6 +32,7 @@ struct VirtWndText : VirtWnd { HFONT font = nullptr; bool withUnderline = false; bool isRtl = false; + COLORREF textColor = kColorUnset; Size sz = {0, 0};