#pragma once #include #include #include #include #include #include "activities/Activity.h" #include "util/ButtonNavigator.h" // Paged viewer for one dictionary definition. HTML definitions are laid out // through the EPUB chapter parser into styled Pages; anything else (plain // text, or HTML too damaged to parse) is word-wrapped once on entry and each // page renders spans of the original string, so no per-line copies are held. class DictionaryDefinitionActivity final : public Activity { public: explicit DictionaryDefinitionActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::string headword, std::string definition, bool htmlDefinition = false) : Activity("DictionaryDefinition", renderer, mappedInput), headword(std::move(headword)), definition(std::move(definition)), htmlDefinition(htmlDefinition) {} void onEnter() override; void onExit() override; void loop() override; void render(RenderLock&&) override; private: // One wrapped display line: a byte span of `definition`. Wrapping keeps // lines under the screen width, so uint16_t length is ample. struct Line { uint32_t start; uint16_t len; }; // Usable body-text area between the header and the button hints. struct BodyArea { int width; int height; }; BodyArea bodyArea() const; bool layoutHtmlPages(); void wrapText(); int measureSpan(int fontId, const char* text, size_t len) const; void drawBody(int fontId, int x, int startY) const; const std::string headword; // Not const: onEnter() normalizes embedded NULs (StarDict multi-type // separators) to newlines so C-string APIs see the whole text. std::string definition; const bool htmlDefinition; // Styled path: reader-identical Pages laid out from the HTML definition. // Empty means the plain-text span path below is active. std::vector> pages; std::vector lines; int currentPage = 0; int totalPages = 1; int linesPerPage = 1; ButtonNavigator buttonNavigator; };