mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2025-12-19 15:47:40 +03:00
clang-format-fix
This commit is contained in:
parent
dcf2b257f4
commit
c4430793e7
@ -337,9 +337,7 @@ void Epub::markAsFootnotePage(const std::string& href) {
|
||||
|
||||
// Extract filename from href (remove #anchor if present)
|
||||
size_t hashPos = href.find('#');
|
||||
std::string filename = (hashPos != std::string::npos)
|
||||
? href.substr(0, hashPos)
|
||||
: href;
|
||||
std::string filename = (hashPos != std::string::npos) ? href.substr(0, hashPos) : href;
|
||||
|
||||
// Extract just the filename without path
|
||||
size_t lastSlash = filename.find_last_of('/');
|
||||
@ -356,7 +354,6 @@ bool Epub::isFootnotePage(const std::string& filename) const {
|
||||
return footnotePages->find(filename) != footnotePages->end();
|
||||
}
|
||||
|
||||
|
||||
bool Epub::shouldHideFromToc(int spineIndex) const {
|
||||
// Always hide virtual spine items
|
||||
if (isVirtualSpineItem(spineIndex)) {
|
||||
@ -371,9 +368,7 @@ bool Epub::shouldHideFromToc(int spineIndex) const {
|
||||
|
||||
// Extract filename from spine item
|
||||
size_t lastSlash = spineItem.find_last_of('/');
|
||||
std::string filename = (lastSlash != std::string::npos)
|
||||
? spineItem.substr(lastSlash + 1)
|
||||
: spineItem;
|
||||
std::string filename = (lastSlash != std::string::npos) ? spineItem.substr(lastSlash + 1) : spineItem;
|
||||
|
||||
return isFootnotePage(filename);
|
||||
}
|
||||
@ -387,14 +382,11 @@ int Epub::addVirtualSpineItem(const std::string& path) {
|
||||
|
||||
virtualSpineItems->push_back(path);
|
||||
int newIndex = spine.size() + virtualSpineItems->size() - 1;
|
||||
Serial.printf("[%lu] [EPUB] Added virtual spine item: %s (index %d)\n",
|
||||
millis(), path.c_str(), newIndex);
|
||||
Serial.printf("[%lu] [EPUB] Added virtual spine item: %s (index %d)\n", millis(), path.c_str(), newIndex);
|
||||
return newIndex;
|
||||
}
|
||||
|
||||
bool Epub::isVirtualSpineItem(int spineIndex) const {
|
||||
return spineIndex >= static_cast<int>(spine.size());
|
||||
}
|
||||
bool Epub::isVirtualSpineItem(int spineIndex) const { return spineIndex >= static_cast<int>(spine.size()); }
|
||||
|
||||
int Epub::findVirtualSpineIndex(const std::string& filename) const {
|
||||
if (!virtualSpineItems) return -1;
|
||||
@ -402,9 +394,7 @@ int Epub::findVirtualSpineIndex(const std::string& filename) const {
|
||||
for (size_t i = 0; i < virtualSpineItems->size(); i++) {
|
||||
std::string virtualPath = (*virtualSpineItems)[i];
|
||||
size_t lastSlash = virtualPath.find_last_of('/');
|
||||
std::string virtualFilename = (lastSlash != std::string::npos)
|
||||
? virtualPath.substr(lastSlash + 1)
|
||||
: virtualPath;
|
||||
std::string virtualFilename = (lastSlash != std::string::npos) ? virtualPath.substr(lastSlash + 1) : virtualPath;
|
||||
|
||||
if (virtualFilename == filename) {
|
||||
return spine.size() + i;
|
||||
|
||||
@ -30,9 +30,7 @@ class Epub {
|
||||
|
||||
public:
|
||||
explicit Epub(std::string filepath, const std::string& cacheDir)
|
||||
: filepath(std::move(filepath)),
|
||||
footnotePages(nullptr),
|
||||
virtualSpineItems(nullptr) {
|
||||
: filepath(std::move(filepath)), footnotePages(nullptr), virtualSpineItems(nullptr) {
|
||||
cachePath = cacheDir + "/epub_" + std::to_string(std::hash<std::string>{}(this->filepath));
|
||||
}
|
||||
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
#include "Page.h"
|
||||
|
||||
#include <HardwareSerial.h>
|
||||
#include <Serialization.h>
|
||||
|
||||
constexpr uint8_t PAGE_FILE_VERSION = 6; // Incremented
|
||||
|
||||
void PageLine::render(GfxRenderer& renderer, const int fontId) {
|
||||
block->render(renderer, fontId, xPos, yPos);
|
||||
}
|
||||
void PageLine::render(GfxRenderer& renderer, const int fontId) { block->render(renderer, fontId, xPos, yPos); }
|
||||
|
||||
void PageLine::serialize(std::ostream& os) {
|
||||
serialization::writePod(os, xPos);
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "FootnoteEntry.h"
|
||||
#include "blocks/TextBlock.h"
|
||||
@ -24,7 +24,7 @@ class PageElement {
|
||||
class PageLine final : public PageElement {
|
||||
std::shared_ptr<TextBlock> block;
|
||||
|
||||
public:
|
||||
public:
|
||||
PageLine(std::shared_ptr<TextBlock> block, const int16_t xPos, const int16_t yPos)
|
||||
: PageElement(xPos, yPos), block(std::move(block)) {}
|
||||
void render(GfxRenderer& renderer, int fontId) override;
|
||||
@ -33,14 +33,14 @@ public:
|
||||
};
|
||||
|
||||
class Page {
|
||||
private:
|
||||
private:
|
||||
std::shared_ptr<PageElement>* elements;
|
||||
int elementCapacity;
|
||||
|
||||
FootnoteEntry* footnotes;
|
||||
int footnoteCapacity;
|
||||
|
||||
public:
|
||||
public:
|
||||
int elementCount;
|
||||
int footnoteCount;
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ static bool writeEscapedXml(File& file, const char* text) {
|
||||
static char buffer[2048];
|
||||
int bufferPos = 0;
|
||||
|
||||
while (*text && bufferPos < sizeof(buffer) - 10) { // Leave margin for entities
|
||||
while (*text && bufferPos < sizeof(buffer) - 10) { // Leave margin for entities
|
||||
unsigned char c = (unsigned char)*text;
|
||||
|
||||
// Only escape the 5 XML special characters
|
||||
@ -178,10 +178,10 @@ bool Section::persistPageDataToSD(const int fontId, const float lineCompression,
|
||||
|
||||
const auto sdPath = "/sd" + localPath;
|
||||
|
||||
ChapterHtmlSlimParser visitor(sdPath.c_str(), renderer, fontId, lineCompression, marginTop, marginRight,
|
||||
marginBottom, marginLeft, extraParagraphSpacing,
|
||||
[this](std::unique_ptr<Page> page) { this->onPageComplete(std::move(page)); },
|
||||
cachePath);
|
||||
ChapterHtmlSlimParser visitor(
|
||||
sdPath.c_str(), renderer, fontId, lineCompression, marginTop, marginRight, marginBottom, marginLeft,
|
||||
extraParagraphSpacing, [this](std::unique_ptr<Page> page) { this->onPageComplete(std::move(page)); },
|
||||
cachePath);
|
||||
|
||||
bool success = visitor.parseAndBuildPages();
|
||||
|
||||
@ -190,7 +190,8 @@ bool Section::persistPageDataToSD(const int fontId, const float lineCompression,
|
||||
return false;
|
||||
}
|
||||
|
||||
writeCacheMetadata(fontId, lineCompression, marginTop, marginRight, marginBottom, marginLeft, extraParagraphSpacing);
|
||||
writeCacheMetadata(fontId, lineCompression, marginTop, marginRight, marginBottom, marginLeft,
|
||||
extraParagraphSpacing);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -209,10 +210,9 @@ bool Section::persistPageDataToSD(const int fontId, const float lineCompression,
|
||||
|
||||
const auto sdTmpHtmlPath = "/sd" + tmpHtmlPath;
|
||||
|
||||
ChapterHtmlSlimParser visitor(sdTmpHtmlPath.c_str(), renderer, fontId, lineCompression, marginTop, marginRight,
|
||||
marginBottom, marginLeft, extraParagraphSpacing,
|
||||
[this](std::unique_ptr<Page> page) { this->onPageComplete(std::move(page)); },
|
||||
cachePath);
|
||||
ChapterHtmlSlimParser visitor(
|
||||
sdTmpHtmlPath.c_str(), renderer, fontId, lineCompression, marginTop, marginRight, marginBottom, marginLeft,
|
||||
extraParagraphSpacing, [this](std::unique_ptr<Page> page) { this->onPageComplete(std::move(page)); }, cachePath);
|
||||
|
||||
// Track which inline footnotes AND paragraph notes are actually referenced in this file
|
||||
std::set<std::string> rewrittenInlineIds;
|
||||
@ -232,10 +232,9 @@ bool Section::persistPageDataToSD(const int fontId, const float lineCompression,
|
||||
if (underscorePos != std::string::npos && dotPos != std::string::npos) {
|
||||
std::string noteId = href.substr(underscorePos + 1, dotPos - underscorePos - 1);
|
||||
rewrittenInlineIds.insert(noteId);
|
||||
Serial.printf("[%lu] [SCT] Marked note as rewritten: %s\n",
|
||||
millis(), noteId.c_str());
|
||||
Serial.printf("[%lu] [SCT] Marked note as rewritten: %s\n", millis(), noteId.c_str());
|
||||
}
|
||||
}else {
|
||||
} else {
|
||||
// Normal external footnote
|
||||
epub->markAsFootnotePage(noteref.href);
|
||||
}
|
||||
@ -254,8 +253,8 @@ bool Section::persistPageDataToSD(const int fontId, const float lineCompression,
|
||||
}
|
||||
|
||||
// NOW generate inline footnote HTML files ONLY for rewritten ones
|
||||
Serial.printf("[%lu] [SCT] Found %d inline footnotes, %d were referenced\n",
|
||||
millis(), visitor.inlineFootnoteCount, rewrittenInlineIds.size());
|
||||
Serial.printf("[%lu] [SCT] Found %d inline footnotes, %d were referenced\n", millis(), visitor.inlineFootnoteCount,
|
||||
rewrittenInlineIds.size());
|
||||
|
||||
for (int i = 0; i < visitor.inlineFootnoteCount; i++) {
|
||||
const char* inlineId = visitor.inlineFootnotes[i].id;
|
||||
@ -263,8 +262,7 @@ bool Section::persistPageDataToSD(const int fontId, const float lineCompression,
|
||||
|
||||
// Only generate if this inline footnote was actually referenced
|
||||
if (rewrittenInlineIds.find(std::string(inlineId)) == rewrittenInlineIds.end()) {
|
||||
Serial.printf("[%lu] [SCT] Skipping unreferenced inline footnote: %s\n",
|
||||
millis(), inlineId);
|
||||
Serial.printf("[%lu] [SCT] Skipping unreferenced inline footnote: %s\n", millis(), inlineId);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -274,8 +272,7 @@ bool Section::persistPageDataToSD(const int fontId, const float lineCompression,
|
||||
continue;
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [SCT] Processing inline footnote: %s (len=%d)\n",
|
||||
millis(), inlineId, strlen(inlineText));
|
||||
Serial.printf("[%lu] [SCT] Processing inline footnote: %s (len=%d)\n", millis(), inlineId, strlen(inlineText));
|
||||
|
||||
char inlineFilename[64];
|
||||
snprintf(inlineFilename, sizeof(inlineFilename), "inline_%s.html", inlineId);
|
||||
@ -325,64 +322,64 @@ bool Section::persistPageDataToSD(const int fontId, const float lineCompression,
|
||||
}
|
||||
}
|
||||
|
||||
// Generate paragraph note HTML files
|
||||
Serial.printf("[%lu] [SCT] Found %d paragraph notes\n", millis(), visitor.paragraphNoteCount);
|
||||
// Generate paragraph note HTML files
|
||||
Serial.printf("[%lu] [SCT] Found %d paragraph notes\n", millis(), visitor.paragraphNoteCount);
|
||||
|
||||
for (int i = 0; i < visitor.paragraphNoteCount; i++) {
|
||||
const char* pnoteId = visitor.paragraphNotes[i].id;
|
||||
const char* pnoteText = visitor.paragraphNotes[i].text;
|
||||
for (int i = 0; i < visitor.paragraphNoteCount; i++) {
|
||||
const char* pnoteId = visitor.paragraphNotes[i].id;
|
||||
const char* pnoteText = visitor.paragraphNotes[i].text;
|
||||
|
||||
if (!pnoteText || strlen(pnoteText) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if this paragraph note was referenced
|
||||
if (rewrittenInlineIds.find(std::string(pnoteId)) == rewrittenInlineIds.end()) {
|
||||
Serial.printf("[%lu] [SCT] Skipping unreferenced paragraph note: %s\n", millis(), pnoteId);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create filename: pnote_rnote1.html
|
||||
char pnoteFilename[64];
|
||||
snprintf(pnoteFilename, sizeof(pnoteFilename), "pnote_%s.html", pnoteId);
|
||||
|
||||
std::string fullPath = epub->getCachePath() + "/" + std::string(pnoteFilename);
|
||||
|
||||
Serial.printf("[%lu] [SCT] Generating paragraph note file: %s\n", millis(), fullPath.c_str());
|
||||
|
||||
File file = SD.open(fullPath.c_str(), FILE_WRITE, true);
|
||||
if (file) {
|
||||
file.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
file.println("<!DOCTYPE html>");
|
||||
file.println("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
|
||||
file.println("<head>");
|
||||
file.println("<meta charset=\"UTF-8\"/>");
|
||||
file.println("<title>Note</title>");
|
||||
file.println("</head>");
|
||||
file.println("<body>");
|
||||
file.print("<p id=\"");
|
||||
file.print(pnoteId);
|
||||
file.print("\">");
|
||||
|
||||
if (!writeEscapedXml(file, pnoteText)) {
|
||||
Serial.printf("[%lu] [SCT] Warning: writeEscapedXml may have failed\n", millis());
|
||||
if (!pnoteText || strlen(pnoteText) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
file.println("</p>");
|
||||
file.println("</body>");
|
||||
file.println("</html>");
|
||||
file.close();
|
||||
// Check if this paragraph note was referenced
|
||||
if (rewrittenInlineIds.find(std::string(pnoteId)) == rewrittenInlineIds.end()) {
|
||||
Serial.printf("[%lu] [SCT] Skipping unreferenced paragraph note: %s\n", millis(), pnoteId);
|
||||
continue;
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [SCT] Generated paragraph note file\n", millis());
|
||||
// Create filename: pnote_rnote1.html
|
||||
char pnoteFilename[64];
|
||||
snprintf(pnoteFilename, sizeof(pnoteFilename), "pnote_%s.html", pnoteId);
|
||||
|
||||
int virtualIndex = epub->addVirtualSpineItem(fullPath);
|
||||
Serial.printf("[%lu] [SCT] Added virtual spine item at index %d\n", millis(), virtualIndex);
|
||||
std::string fullPath = epub->getCachePath() + "/" + std::string(pnoteFilename);
|
||||
|
||||
char newHref[128];
|
||||
snprintf(newHref, sizeof(newHref), "%s#%s", pnoteFilename, pnoteId);
|
||||
epub->markAsFootnotePage(newHref);
|
||||
Serial.printf("[%lu] [SCT] Generating paragraph note file: %s\n", millis(), fullPath.c_str());
|
||||
|
||||
File file = SD.open(fullPath.c_str(), FILE_WRITE, true);
|
||||
if (file) {
|
||||
file.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
file.println("<!DOCTYPE html>");
|
||||
file.println("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
|
||||
file.println("<head>");
|
||||
file.println("<meta charset=\"UTF-8\"/>");
|
||||
file.println("<title>Note</title>");
|
||||
file.println("</head>");
|
||||
file.println("<body>");
|
||||
file.print("<p id=\"");
|
||||
file.print(pnoteId);
|
||||
file.print("\">");
|
||||
|
||||
if (!writeEscapedXml(file, pnoteText)) {
|
||||
Serial.printf("[%lu] [SCT] Warning: writeEscapedXml may have failed\n", millis());
|
||||
}
|
||||
|
||||
file.println("</p>");
|
||||
file.println("</body>");
|
||||
file.println("</html>");
|
||||
file.close();
|
||||
|
||||
Serial.printf("[%lu] [SCT] Generated paragraph note file\n", millis());
|
||||
|
||||
int virtualIndex = epub->addVirtualSpineItem(fullPath);
|
||||
Serial.printf("[%lu] [SCT] Added virtual spine item at index %d\n", millis(), virtualIndex);
|
||||
|
||||
char newHref[128];
|
||||
snprintf(newHref, sizeof(newHref), "%s#%s", pnoteFilename, pnoteId);
|
||||
epub->markAsFootnotePage(newHref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [SCT] Total noterefs found: %d\n", millis(), noterefCount);
|
||||
|
||||
|
||||
@ -90,7 +90,7 @@ void ChapterHtmlSlimParser::addFootnoteToCurrentPage(const char* number, const c
|
||||
}
|
||||
}
|
||||
|
||||
//Check if we have this as a paragraph note
|
||||
// Check if we have this as a paragraph note
|
||||
if (!foundInline) {
|
||||
for (int i = 0; i < paragraphNoteCount; i++) {
|
||||
if (strcmp(paragraphNotes[i].id, inlineId) == 0) {
|
||||
@ -120,10 +120,9 @@ void ChapterHtmlSlimParser::addFootnoteToCurrentPage(const char* number, const c
|
||||
|
||||
currentPageFootnoteCount++;
|
||||
|
||||
Serial.printf("[%lu] [ADDFT] Stored as: num=%s, href=%s\n",
|
||||
millis(),
|
||||
currentPageFootnotes[currentPageFootnoteCount-1].number,
|
||||
currentPageFootnotes[currentPageFootnoteCount-1].href);
|
||||
Serial.printf("[%lu] [ADDFT] Stored as: num=%s, href=%s\n", millis(),
|
||||
currentPageFootnotes[currentPageFootnoteCount - 1].number,
|
||||
currentPageFootnotes[currentPageFootnoteCount - 1].href);
|
||||
}
|
||||
|
||||
void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* name, const XML_Char** atts) {
|
||||
@ -173,8 +172,8 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
|
||||
if (epubType && strcmp(epubType, "footnote") == 0 && id) {
|
||||
if (self->isPass1CollectingAsides) {
|
||||
// Pass 1: Collect aside
|
||||
Serial.printf("[%lu] [ASIDE] Found inline footnote: id=%s (pass1=%d)\n",
|
||||
millis(), id, self->isPass1CollectingAsides);
|
||||
Serial.printf("[%lu] [ASIDE] Found inline footnote: id=%s (pass1=%d)\n", millis(), id,
|
||||
self->isPass1CollectingAsides);
|
||||
|
||||
self->insideAsideFootnote = true;
|
||||
self->asideDepth = self->depth;
|
||||
@ -189,8 +188,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
|
||||
|
||||
// Find the inline footnote text
|
||||
for (int i = 0; i < self->inlineFootnoteCount; i++) {
|
||||
if (strcmp(self->inlineFootnotes[i].id, id) == 0 &&
|
||||
self->inlineFootnotes[i].text) {
|
||||
if (strcmp(self->inlineFootnotes[i].id, id) == 0 && self->inlineFootnotes[i].text) {
|
||||
// Output the footnote text as normal text
|
||||
const char* text = self->inlineFootnotes[i].text;
|
||||
int textLen = strlen(text);
|
||||
@ -198,10 +196,9 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
|
||||
// Process it through characterData
|
||||
self->characterData(self, text, textLen);
|
||||
|
||||
Serial.printf("[%lu] [ASIDE] Rendered aside text: %.80s...\n",
|
||||
millis(), text);
|
||||
Serial.printf("[%lu] [ASIDE] Rendered aside text: %.80s...\n", millis(), text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skip the aside element itself
|
||||
@ -332,13 +329,13 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
|
||||
void XMLCALL ChapterHtmlSlimParser::characterData(void* userData, const XML_Char* s, const int len) {
|
||||
auto* self = static_cast<ChapterHtmlSlimParser*>(userData);
|
||||
|
||||
//Collect paragraph note text in Pass 1
|
||||
// Collect paragraph note text in Pass 1
|
||||
if (self->insideParagraphNote && self->isPass1CollectingAsides) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (self->currentParagraphNoteTextLen >= self->MAX_PNOTE_BUFFER - 2) {
|
||||
if (self->currentParagraphNoteTextLen == self->MAX_PNOTE_BUFFER - 2) {
|
||||
Serial.printf("[%lu] [PNOTE] WARNING: Note text truncated at %d chars\n",
|
||||
millis(), self->MAX_PNOTE_BUFFER - 2);
|
||||
Serial.printf("[%lu] [PNOTE] WARNING: Note text truncated at %d chars\n", millis(),
|
||||
self->MAX_PNOTE_BUFFER - 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -349,7 +346,7 @@ void XMLCALL ChapterHtmlSlimParser::characterData(void* userData, const XML_Char
|
||||
if (self->currentParagraphNoteTextLen > 0 &&
|
||||
self->currentParagraphNoteText[self->currentParagraphNoteTextLen - 1] != ' ') {
|
||||
self->currentParagraphNoteText[self->currentParagraphNoteTextLen++] = ' ';
|
||||
}
|
||||
}
|
||||
} else if (c >= 32 || c >= 0x80) { // Accept printable ASCII AND UTF-8
|
||||
self->currentParagraphNoteText[self->currentParagraphNoteTextLen++] = c;
|
||||
}
|
||||
@ -367,8 +364,8 @@ void XMLCALL ChapterHtmlSlimParser::characterData(void* userData, const XML_Char
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (self->currentAsideTextLen >= self->MAX_ASIDE_BUFFER - 2) {
|
||||
if (self->currentAsideTextLen == self->MAX_ASIDE_BUFFER - 2) {
|
||||
Serial.printf("[%lu] [ASIDE] WARNING: Footnote text truncated at %d chars (id=%s)\n",
|
||||
millis(), self->MAX_ASIDE_BUFFER - 2, self->currentAsideId);
|
||||
Serial.printf("[%lu] [ASIDE] WARNING: Footnote text truncated at %d chars (id=%s)\n", millis(),
|
||||
self->MAX_ASIDE_BUFFER - 2, self->currentAsideId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -376,10 +373,9 @@ void XMLCALL ChapterHtmlSlimParser::characterData(void* userData, const XML_Char
|
||||
unsigned char c = (unsigned char)s[i]; // Cast to unsigned char
|
||||
|
||||
if (isWhitespace(c)) {
|
||||
if (self->currentAsideTextLen > 0 &&
|
||||
self->currentAsideText[self->currentAsideTextLen - 1] != ' ') {
|
||||
if (self->currentAsideTextLen > 0 && self->currentAsideText[self->currentAsideTextLen - 1] != ' ') {
|
||||
self->currentAsideText[self->currentAsideTextLen++] = ' ';
|
||||
}
|
||||
}
|
||||
} else if (c >= 32 || c >= 0x80) { // Accept printable ASCII AND UTF-8 bytes
|
||||
self->currentAsideText[self->currentAsideTextLen++] = c;
|
||||
}
|
||||
@ -443,36 +439,27 @@ void XMLCALL ChapterHtmlSlimParser::characterData(void* userData, const XML_Char
|
||||
void XMLCALL ChapterHtmlSlimParser::endElement(void* userData, const XML_Char* name) {
|
||||
auto* self = static_cast<ChapterHtmlSlimParser*>(userData);
|
||||
|
||||
//Closing paragraph note in Pass 1
|
||||
if (strcmp(name, "p") == 0 && self->insideParagraphNote &&
|
||||
self->depth - 1 == self->paragraphNoteDepth) {
|
||||
|
||||
if (self->isPass1CollectingAsides &&
|
||||
self->currentParagraphNoteTextLen > 0 &&
|
||||
self->paragraphNoteCount < 32 &&
|
||||
// Closing paragraph note in Pass 1
|
||||
if (strcmp(name, "p") == 0 && self->insideParagraphNote && self->depth - 1 == self->paragraphNoteDepth) {
|
||||
if (self->isPass1CollectingAsides && self->currentParagraphNoteTextLen > 0 && self->paragraphNoteCount < 32 &&
|
||||
self->currentParagraphNoteId[0] != '\0') {
|
||||
|
||||
// Copy ID
|
||||
strncpy(self->paragraphNotes[self->paragraphNoteCount].id,
|
||||
self->currentParagraphNoteId, 15);
|
||||
strncpy(self->paragraphNotes[self->paragraphNoteCount].id, self->currentParagraphNoteId, 15);
|
||||
self->paragraphNotes[self->paragraphNoteCount].id[15] = '\0';
|
||||
|
||||
// Allocate memory for text
|
||||
size_t textLen = strlen(self->currentParagraphNoteText);
|
||||
self->paragraphNotes[self->paragraphNoteCount].text =
|
||||
static_cast<char*>(malloc(textLen + 1));
|
||||
self->paragraphNotes[self->paragraphNoteCount].text = static_cast<char*>(malloc(textLen + 1));
|
||||
|
||||
if (self->paragraphNotes[self->paragraphNoteCount].text) {
|
||||
strcpy(self->paragraphNotes[self->paragraphNoteCount].text,
|
||||
self->currentParagraphNoteText);
|
||||
strcpy(self->paragraphNotes[self->paragraphNoteCount].text, self->currentParagraphNoteText);
|
||||
|
||||
Serial.printf("[%lu] [PNOTE] Stored: %s -> %.80s... (allocated %d bytes)\n",
|
||||
millis(), self->currentParagraphNoteId,
|
||||
self->currentParagraphNoteText, textLen + 1);
|
||||
Serial.printf("[%lu] [PNOTE] Stored: %s -> %.80s... (allocated %d bytes)\n", millis(),
|
||||
self->currentParagraphNoteId, self->currentParagraphNoteText, textLen + 1);
|
||||
|
||||
self->paragraphNoteCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self->insideParagraphNote = false;
|
||||
self->depth -= 1;
|
||||
@ -480,35 +467,27 @@ void XMLCALL ChapterHtmlSlimParser::endElement(void* userData, const XML_Char* n
|
||||
}
|
||||
|
||||
// Closing aside - handle differently for Pass 1 vs Pass 2
|
||||
if (strcmp(name, "aside") == 0 && self->insideAsideFootnote &&
|
||||
self->depth - 1 == self->asideDepth) {
|
||||
|
||||
if (strcmp(name, "aside") == 0 && self->insideAsideFootnote && self->depth - 1 == self->asideDepth) {
|
||||
// Store footnote ONLY in Pass 1
|
||||
if (self->isPass1CollectingAsides &&
|
||||
self->currentAsideTextLen > 0 &&
|
||||
self->inlineFootnoteCount < 16) {
|
||||
|
||||
if (self->isPass1CollectingAsides && self->currentAsideTextLen > 0 && self->inlineFootnoteCount < 16) {
|
||||
// Copy ID (max 2 digits)
|
||||
strncpy(self->inlineFootnotes[self->inlineFootnoteCount].id,
|
||||
self->currentAsideId, 2);
|
||||
strncpy(self->inlineFootnotes[self->inlineFootnoteCount].id, self->currentAsideId, 2);
|
||||
self->inlineFootnotes[self->inlineFootnoteCount].id[2] = '\0';
|
||||
|
||||
// DYNAMIC ALLOCATION: allocate exactly the needed size + 1
|
||||
size_t textLen = strlen(self->currentAsideText);
|
||||
self->inlineFootnotes[self->inlineFootnoteCount].text =
|
||||
static_cast<char*>(malloc(textLen + 1));
|
||||
self->inlineFootnotes[self->inlineFootnoteCount].text = static_cast<char*>(malloc(textLen + 1));
|
||||
|
||||
if (self->inlineFootnotes[self->inlineFootnoteCount].text) {
|
||||
strcpy(self->inlineFootnotes[self->inlineFootnoteCount].text,
|
||||
self->currentAsideText);
|
||||
strcpy(self->inlineFootnotes[self->inlineFootnoteCount].text, self->currentAsideText);
|
||||
|
||||
Serial.printf("[%lu] [ASIDE] Stored: %s -> %.80s... (allocated %d bytes)\n",
|
||||
millis(), self->currentAsideId, self->currentAsideText, textLen + 1);
|
||||
Serial.printf("[%lu] [ASIDE] Stored: %s -> %.80s... (allocated %d bytes)\n", millis(), self->currentAsideId,
|
||||
self->currentAsideText, textLen + 1);
|
||||
|
||||
self->inlineFootnoteCount++;
|
||||
} else {
|
||||
Serial.printf("[%lu] [ASIDE] ERROR: Failed to allocate %d bytes for footnote %s\n",
|
||||
millis(), textLen + 1, self->currentAsideId);
|
||||
Serial.printf("[%lu] [ASIDE] ERROR: Failed to allocate %d bytes for footnote %s\n", millis(), textLen + 1,
|
||||
self->currentAsideId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -529,9 +508,7 @@ void XMLCALL ChapterHtmlSlimParser::endElement(void* userData, const XML_Char* n
|
||||
self->insideNoteref = false;
|
||||
|
||||
if (self->currentNoterefTextLen > 0) {
|
||||
Serial.printf("[%lu] [NOTEREF] %s -> %s\n", millis(),
|
||||
self->currentNoterefText,
|
||||
self->currentNoterefHref);
|
||||
Serial.printf("[%lu] [NOTEREF] %s -> %s\n", millis(), self->currentNoterefText, self->currentNoterefHref);
|
||||
|
||||
// Add footnote first (this does the rewriting)
|
||||
self->addFootnoteToCurrentPage(self->currentNoterefText, self->currentNoterefHref);
|
||||
@ -668,8 +645,7 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() {
|
||||
done = feof(file);
|
||||
|
||||
if (XML_ParseBuffer(parser1, static_cast<int>(len), done) == XML_STATUS_ERROR) {
|
||||
Serial.printf("[%lu] [EHP] Parse error at line %lu:\n%s\n", millis(),
|
||||
XML_GetCurrentLineNumber(parser1),
|
||||
Serial.printf("[%lu] [EHP] Parse error at line %lu:\n%s\n", millis(), XML_GetCurrentLineNumber(parser1),
|
||||
XML_ErrorString(XML_GetErrorCode(parser1)));
|
||||
XML_ParserFree(parser1);
|
||||
fclose(file);
|
||||
@ -680,11 +656,9 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() {
|
||||
XML_ParserFree(parser1);
|
||||
fclose(file);
|
||||
|
||||
Serial.printf("[%lu] [PARSER] Pass 1 complete: found %d inline footnotes\n",
|
||||
millis(), inlineFootnoteCount);
|
||||
Serial.printf("[%lu] [PARSER] Pass 1 complete: found %d inline footnotes\n", millis(), inlineFootnoteCount);
|
||||
for (int i = 0; i < inlineFootnoteCount; i++) {
|
||||
Serial.printf("[%lu] [PARSER] - %s: %.80s\n",
|
||||
millis(), inlineFootnotes[i].id, inlineFootnotes[i].text);
|
||||
Serial.printf("[%lu] [PARSER] - %s: %.80s\n", millis(), inlineFootnotes[i].id, inlineFootnotes[i].text);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@ -743,8 +717,7 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() {
|
||||
done = feof(file);
|
||||
|
||||
if (XML_ParseBuffer(parser2, static_cast<int>(len), done) == XML_STATUS_ERROR) {
|
||||
Serial.printf("[%lu] [EHP] Parse error at line %lu:\n%s\n", millis(),
|
||||
XML_GetCurrentLineNumber(parser2),
|
||||
Serial.printf("[%lu] [EHP] Parse error at line %lu:\n%s\n", millis(), XML_GetCurrentLineNumber(parser2),
|
||||
XML_ErrorString(XML_GetErrorCode(parser2)));
|
||||
XML_ParserFree(parser2);
|
||||
fclose(file);
|
||||
@ -819,4 +792,3 @@ void ChapterHtmlSlimParser::makePages() {
|
||||
currentPageNextY += lineHeight / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <expat.h>
|
||||
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include "../FootnoteEntry.h"
|
||||
#include "../ParsedText.h"
|
||||
#include "../blocks/TextBlock.h"
|
||||
#include "../FootnoteEntry.h"
|
||||
|
||||
class Page;
|
||||
class GfxRenderer;
|
||||
@ -25,19 +26,15 @@ struct InlineFootnote {
|
||||
char id[3];
|
||||
char* text;
|
||||
|
||||
InlineFootnote() : text(nullptr) {
|
||||
id[0] = '\0';
|
||||
}
|
||||
InlineFootnote() : text(nullptr) { id[0] = '\0'; }
|
||||
};
|
||||
|
||||
// Struct to store collected inline footnotes from <p class="note">
|
||||
struct ParagraphNote {
|
||||
char id[16]; // ID from <a id="rnote1">
|
||||
char* text; // Pointer to dynamically allocated text
|
||||
char id[16]; // ID from <a id="rnote1">
|
||||
char* text; // Pointer to dynamically allocated text
|
||||
|
||||
ParagraphNote() : text(nullptr) {
|
||||
id[0] = '\0';
|
||||
}
|
||||
ParagraphNote() : text(nullptr) { id[0] = '\0'; }
|
||||
|
||||
~ParagraphNote() {
|
||||
if (text) {
|
||||
@ -88,7 +85,7 @@ class ChapterHtmlSlimParser {
|
||||
int asideDepth = 0;
|
||||
char currentAsideId[3] = {0};
|
||||
|
||||
//Paragraph note tracking
|
||||
// Paragraph note tracking
|
||||
bool insideParagraphNote = false;
|
||||
int paragraphNoteDepth = 0;
|
||||
char currentParagraphNoteId[16] = {0};
|
||||
@ -120,7 +117,7 @@ class ChapterHtmlSlimParser {
|
||||
// inline footnotes
|
||||
InlineFootnote inlineFootnotes[16];
|
||||
int inlineFootnoteCount = 0;
|
||||
//paragraph notes
|
||||
// paragraph notes
|
||||
ParagraphNote paragraphNotes[32];
|
||||
int paragraphNoteCount = 0;
|
||||
|
||||
@ -161,7 +158,5 @@ class ChapterHtmlSlimParser {
|
||||
bool parseAndBuildPages();
|
||||
void addLineToPage(std::shared_ptr<TextBlock> line);
|
||||
|
||||
void setNoterefCallback(const std::function<void(Noteref&)>& callback) {
|
||||
noterefCallback = callback;
|
||||
}
|
||||
void setNoterefCallback(const std::function<void(Noteref&)>& callback) { noterefCallback = callback; }
|
||||
};
|
||||
@ -73,8 +73,8 @@ void EpubReaderChapterSelectionScreen::buildFilteredChapterList() {
|
||||
filteredSpineIndices.push_back(i);
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [CHAP] Filtered chapters: %d out of %d\n",
|
||||
millis(), filteredSpineIndices.size(), epub->getSpineItemsCount());
|
||||
Serial.printf("[%lu] [CHAP] Filtered chapters: %d out of %d\n", millis(), filteredSpineIndices.size(),
|
||||
epub->getSpineItemsCount());
|
||||
}
|
||||
|
||||
void EpubReaderChapterSelectionScreen::handleInput() {
|
||||
|
||||
@ -27,7 +27,7 @@ class EpubReaderChapterSelectionScreen final : public Screen {
|
||||
void renderScreen();
|
||||
void buildFilteredChapterList();
|
||||
|
||||
public:
|
||||
public:
|
||||
explicit EpubReaderChapterSelectionScreen(GfxRenderer& renderer, InputManager& inputManager,
|
||||
const std::shared_ptr<Epub>& epub, const int currentSpineIndex,
|
||||
const std::function<void()>& onGoBack,
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
#include "EpubReaderFootnotesScreen.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <GfxRenderer.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
void EpubReaderFootnotesScreen::onEnter() {
|
||||
selectedIndex = 0;
|
||||
render();
|
||||
@ -20,8 +22,7 @@ void EpubReaderFootnotesScreen::handleInput() {
|
||||
if (inputManager.wasPressed(InputManager::BTN_CONFIRM)) {
|
||||
const FootnoteEntry* entry = footnotes.getEntry(selectedIndex);
|
||||
if (entry) {
|
||||
Serial.printf("[%lu] [FNS] Selected footnote: %s -> %s\n",
|
||||
millis(), entry->number, entry->href);
|
||||
Serial.printf("[%lu] [FNS] Selected footnote: %s -> %s\n", millis(), entry->number, entry->href);
|
||||
|
||||
// Appeler le callback - EpubReaderScreen gère la navigation
|
||||
onSelectFootnote(entry->href);
|
||||
@ -83,9 +84,8 @@ void EpubReaderFootnotesScreen::render() {
|
||||
}
|
||||
|
||||
// Instructions at bottom
|
||||
renderer.drawText(SMALL_FONT_ID, marginLeft,
|
||||
GfxRenderer::getScreenHeight() - 40,
|
||||
"UP/DOWN: Select CONFIRM: Go to footnote BACK: Return");
|
||||
renderer.drawText(SMALL_FONT_ID, marginLeft, GfxRenderer::getScreenHeight() - 40,
|
||||
"UP/DOWN: Select CONFIRM: Go to footnote BACK: Return");
|
||||
|
||||
renderer.displayBuffer();
|
||||
}
|
||||
@ -1,16 +1,17 @@
|
||||
#pragma once
|
||||
#include "Screen.h"
|
||||
#include "../../lib/Epub/Epub/FootnoteEntry.h"
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
|
||||
#include "../../lib/Epub/Epub/FootnoteEntry.h"
|
||||
#include "Screen.h"
|
||||
|
||||
class FootnotesData {
|
||||
private:
|
||||
private:
|
||||
FootnoteEntry entries[32];
|
||||
int count;
|
||||
|
||||
public:
|
||||
public:
|
||||
FootnotesData() : count(0) {}
|
||||
|
||||
void addFootnote(const char* number, const char* href) {
|
||||
@ -23,13 +24,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void clear() {
|
||||
count = 0;
|
||||
}
|
||||
void clear() { count = 0; }
|
||||
|
||||
int getCount() const {
|
||||
return count;
|
||||
}
|
||||
int getCount() const { return count; }
|
||||
|
||||
const FootnoteEntry* getEntry(int index) const {
|
||||
if (index >= 0 && index < count) {
|
||||
@ -45,13 +42,10 @@ class EpubReaderFootnotesScreen final : public Screen {
|
||||
const std::function<void(const char*)> onSelectFootnote;
|
||||
int selectedIndex;
|
||||
|
||||
public:
|
||||
EpubReaderFootnotesScreen(
|
||||
GfxRenderer& renderer,
|
||||
InputManager& inputManager,
|
||||
const FootnotesData& footnotes,
|
||||
const std::function<void()>& onGoBack,
|
||||
const std::function<void(const char*)>& onSelectFootnote)
|
||||
public:
|
||||
EpubReaderFootnotesScreen(GfxRenderer& renderer, InputManager& inputManager, const FootnotesData& footnotes,
|
||||
const std::function<void()>& onGoBack,
|
||||
const std::function<void(const char*)>& onSelectFootnote)
|
||||
: Screen(renderer, inputManager),
|
||||
footnotes(footnotes),
|
||||
onGoBack(onGoBack),
|
||||
@ -62,6 +56,6 @@ public:
|
||||
void onExit() override;
|
||||
void handleInput() override;
|
||||
|
||||
private:
|
||||
private:
|
||||
void render();
|
||||
};
|
||||
@ -2,7 +2,9 @@
|
||||
// Created by jlaunay on 13/12/2025.
|
||||
//
|
||||
#include "EpubReaderMenuScreen.h"
|
||||
|
||||
#include <GfxRenderer.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
constexpr int MENU_ITEMS_COUNT = 2;
|
||||
@ -74,10 +76,7 @@ void EpubReaderMenuScreen::renderScreen() {
|
||||
const auto pageWidth = renderer.getScreenWidth();
|
||||
renderer.drawCenteredText(READER_FONT_ID, 10, "Menu", true, BOLD);
|
||||
|
||||
const char* menuItems[MENU_ITEMS_COUNT] = {
|
||||
"Go to chapter",
|
||||
"View footnotes"
|
||||
};
|
||||
const char* menuItems[MENU_ITEMS_COUNT] = {"Go to chapter", "View footnotes"};
|
||||
|
||||
const int startY = 100;
|
||||
const int itemHeight = 40;
|
||||
|
||||
@ -12,13 +12,10 @@
|
||||
#include "Screen.h"
|
||||
|
||||
class EpubReaderMenuScreen final : public Screen {
|
||||
public:
|
||||
enum MenuOption {
|
||||
CHAPTERS,
|
||||
FOOTNOTES
|
||||
};
|
||||
public:
|
||||
enum MenuOption { CHAPTERS, FOOTNOTES };
|
||||
|
||||
private:
|
||||
private:
|
||||
TaskHandle_t displayTaskHandle = nullptr;
|
||||
SemaphoreHandle_t renderingMutex = nullptr;
|
||||
int selectorIndex = 0;
|
||||
@ -30,13 +27,11 @@ private:
|
||||
[[noreturn]] void displayTaskLoop();
|
||||
void renderScreen();
|
||||
|
||||
public:
|
||||
public:
|
||||
explicit EpubReaderMenuScreen(GfxRenderer& renderer, InputManager& inputManager,
|
||||
const std::function<void()>& onGoBack,
|
||||
const std::function<void(MenuOption option)>& onSelectOption)
|
||||
: Screen(renderer, inputManager),
|
||||
onGoBack(onGoBack),
|
||||
onSelectOption(onSelectOption) {}
|
||||
: Screen(renderer, inputManager), onGoBack(onGoBack), onSelectOption(onSelectOption) {}
|
||||
|
||||
void onEnter() override;
|
||||
void onExit() override;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#include "EpubReaderScreen.h"
|
||||
|
||||
#include "EpubReaderFootnotesScreen.h"
|
||||
#include <Epub/Page.h>
|
||||
#include <GfxRenderer.h>
|
||||
#include <SD.h>
|
||||
@ -8,6 +7,7 @@
|
||||
#include "Battery.h"
|
||||
#include "CrossPointSettings.h"
|
||||
#include "EpubReaderChapterSelectionScreen.h"
|
||||
#include "EpubReaderFootnotesScreen.h"
|
||||
#include "EpubReaderMenuScreen.h"
|
||||
#include "config.h"
|
||||
|
||||
@ -46,11 +46,8 @@ void EpubReaderScreen::onEnter() {
|
||||
updateRequired = true;
|
||||
|
||||
xTaskCreate(&EpubReaderScreen::taskTrampoline, "EpubReaderScreenTask",
|
||||
24576, //32768
|
||||
this,
|
||||
1,
|
||||
&displayTaskHandle
|
||||
);
|
||||
24576, // 32768
|
||||
this, 1, &displayTaskHandle);
|
||||
}
|
||||
|
||||
void EpubReaderScreen::onExit() {
|
||||
@ -126,8 +123,7 @@ void EpubReaderScreen::handleInput() {
|
||||
subScreen->onExit();
|
||||
|
||||
subScreen.reset(new EpubReaderFootnotesScreen(
|
||||
this->renderer,
|
||||
this->inputManager,
|
||||
this->renderer, this->inputManager,
|
||||
currentPageFootnotes, // Pass collected footnotes (reference)
|
||||
[this] {
|
||||
// onGoBack from footnotes
|
||||
@ -460,8 +456,7 @@ void EpubReaderScreen::navigateToHref(const char* href, bool savePosition) {
|
||||
savedSpineIndex = currentSpineIndex;
|
||||
savedPageNumber = section->currentPage;
|
||||
isViewingFootnote = true;
|
||||
Serial.printf("[%lu] [ERS] Saved position: spine %d, page %d\n",
|
||||
millis(), savedSpineIndex, savedPageNumber);
|
||||
Serial.printf("[%lu] [ERS] Saved position: spine %d, page %d\n", millis(), savedSpineIndex, savedPageNumber);
|
||||
}
|
||||
|
||||
// Parse href: "filename.html#anchor"
|
||||
@ -483,8 +478,7 @@ void EpubReaderScreen::navigateToHref(const char* href, bool savePosition) {
|
||||
filename = filename.substr(lastSlash + 1);
|
||||
}
|
||||
|
||||
Serial.printf("[%lu] [ERS] Navigate to: %s (anchor: %s)\n",
|
||||
millis(), filename.c_str(), anchor.c_str());
|
||||
Serial.printf("[%lu] [ERS] Navigate to: %s (anchor: %s)\n", millis(), filename.c_str(), anchor.c_str());
|
||||
|
||||
int targetSpineIndex = -1;
|
||||
|
||||
@ -492,23 +486,20 @@ void EpubReaderScreen::navigateToHref(const char* href, bool savePosition) {
|
||||
if (!anchor.empty()) {
|
||||
// Try inline footnote first
|
||||
std::string inlineFilename = "inline_" + anchor + ".html";
|
||||
Serial.printf("[%lu] [ERS] Looking for inline footnote: %s\n",
|
||||
millis(), inlineFilename.c_str());
|
||||
Serial.printf("[%lu] [ERS] Looking for inline footnote: %s\n", millis(), inlineFilename.c_str());
|
||||
|
||||
targetSpineIndex = epub->findVirtualSpineIndex(inlineFilename);
|
||||
|
||||
// If not found, try paragraph note
|
||||
if (targetSpineIndex == -1) {
|
||||
std::string pnoteFilename = "pnote_" + anchor + ".html";
|
||||
Serial.printf("[%lu] [ERS] Looking for paragraph note: %s\n",
|
||||
millis(), pnoteFilename.c_str());
|
||||
Serial.printf("[%lu] [ERS] Looking for paragraph note: %s\n", millis(), pnoteFilename.c_str());
|
||||
|
||||
targetSpineIndex = epub->findVirtualSpineIndex(pnoteFilename);
|
||||
}
|
||||
|
||||
if (targetSpineIndex != -1) {
|
||||
Serial.printf("[%lu] [ERS] Found note at virtual index: %d\n",
|
||||
millis(), targetSpineIndex);
|
||||
Serial.printf("[%lu] [ERS] Found note at virtual index: %d\n", millis(), targetSpineIndex);
|
||||
|
||||
// Navigate to the note
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
@ -520,8 +511,7 @@ void EpubReaderScreen::navigateToHref(const char* href, bool savePosition) {
|
||||
updateRequired = true;
|
||||
return;
|
||||
} else {
|
||||
Serial.printf("[%lu] [ERS] No virtual note found, trying normal navigation\n",
|
||||
millis());
|
||||
Serial.printf("[%lu] [ERS] No virtual note found, trying normal navigation\n", millis());
|
||||
}
|
||||
}
|
||||
|
||||
@ -531,9 +521,7 @@ void EpubReaderScreen::navigateToHref(const char* href, bool savePosition) {
|
||||
|
||||
std::string spineItem = epub->getSpineItem(i);
|
||||
size_t lastSlash = spineItem.find_last_of('/');
|
||||
std::string spineFilename = (lastSlash != std::string::npos)
|
||||
? spineItem.substr(lastSlash + 1)
|
||||
: spineItem;
|
||||
std::string spineFilename = (lastSlash != std::string::npos) ? spineItem.substr(lastSlash + 1) : spineItem;
|
||||
|
||||
if (spineFilename == filename) {
|
||||
targetSpineIndex = i;
|
||||
@ -542,8 +530,7 @@ void EpubReaderScreen::navigateToHref(const char* href, bool savePosition) {
|
||||
}
|
||||
|
||||
if (targetSpineIndex == -1) {
|
||||
Serial.printf("[%lu] [ERS] Could not find spine index for: %s\n",
|
||||
millis(), filename.c_str());
|
||||
Serial.printf("[%lu] [ERS] Could not find spine index for: %s\n", millis(), filename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -556,15 +543,13 @@ void EpubReaderScreen::navigateToHref(const char* href, bool savePosition) {
|
||||
|
||||
updateRequired = true;
|
||||
|
||||
Serial.printf("[%lu] [ERS] Navigated to spine index: %d\n",
|
||||
millis(), targetSpineIndex);
|
||||
Serial.printf("[%lu] [ERS] Navigated to spine index: %d\n", millis(), targetSpineIndex);
|
||||
}
|
||||
|
||||
// Method to restore saved position
|
||||
void EpubReaderScreen::restoreSavedPosition() {
|
||||
if (savedSpineIndex >= 0 && savedPageNumber >= 0) {
|
||||
Serial.printf("[%lu] [ERS] Restoring position: spine %d, page %d\n",
|
||||
millis(), savedSpineIndex, savedPageNumber);
|
||||
Serial.printf("[%lu] [ERS] Restoring position: spine %d, page %d\n", millis(), savedSpineIndex, savedPageNumber);
|
||||
|
||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||
currentSpineIndex = savedSpineIndex;
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include <freertos/task.h>
|
||||
#include "EpubReaderFootnotesScreen.h"
|
||||
|
||||
#include "EpubReaderFootnotesScreen.h"
|
||||
#include "Screen.h"
|
||||
|
||||
class EpubReaderScreen final : public Screen {
|
||||
@ -35,7 +35,7 @@ class EpubReaderScreen final : public Screen {
|
||||
void navigateToHref(const char* href, bool savePosition = false);
|
||||
void restoreSavedPosition();
|
||||
|
||||
public:
|
||||
public:
|
||||
explicit EpubReaderScreen(GfxRenderer& renderer, InputManager& inputManager, std::unique_ptr<Epub> epub,
|
||||
const std::function<void()>& onGoBack)
|
||||
: Screen(renderer, inputManager), epub(std::move(epub)), onGoBack(onGoBack) {}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user