#pragma once #include #include #include #include "activities/Activity.h" class DictionaryDefinitionActivity final : public Activity { public: explicit DictionaryDefinitionActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, const std::string& headword, const std::string& definition, int readerFontId, uint8_t orientation, bool hasDoneButton = false) : Activity("DictionaryDefinition", renderer, mappedInput), headword(headword), definition(definition), readerFontId(readerFontId), orientation(orientation), hasDoneButton(hasDoneButton) {} void onEnter() override; void onExit() override; void loop() override; void render(RenderLock&&) override; private: // A positioned text segment within a wrapped line (pre-calculated x offset and style). struct Segment { std::string text; int16_t x; EpdFontFamily::Style style; }; // An intermediate token produced by the HTML parser before word-wrapping. struct TextAtom { std::string text; EpdFontFamily::Style style; bool isNewline; int indent; // pixels to indent the new line (for nested lists) }; // Tracks ordered/unordered list nesting during HTML parsing. struct ListState { int counter; // incremented per
  • , 0 = not yet used bool isAlpha; // true for list-style-type: lower-alpha }; std::string headword; std::string definition; int readerFontId; uint8_t orientation; bool hasDoneButton; // If true, Confirm shows "Done" and finishes with !isCancelled (exit to reader) std::vector> wrappedLines; int currentPage = 0; int linesPerPage = 0; int totalPages = 0; bool firstRender = true; std::vector parseHtml(const std::string& html); static std::string decodeEntity(const std::string& entity); static bool isRenderableCodepoint(uint32_t cp); void wrapText(); };