clang-format-fix

This commit is contained in:
Jérôme Launay 2025-12-17 13:00:21 +01:00
parent dcf2b257f4
commit c4430793e7
15 changed files with 173 additions and 249 deletions

View File

@ -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;

View File

@ -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));
}

View File

@ -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);

View File

@ -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;

View File

@ -178,9 +178,9 @@ 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)); },
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,10 +322,10 @@ 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++) {
for (int i = 0; i < visitor.paragraphNoteCount; i++) {
const char* pnoteId = visitor.paragraphNotes[i].id;
const char* pnoteText = visitor.paragraphNotes[i].text;
@ -382,7 +379,7 @@ for (int i = 0; i < visitor.paragraphNoteCount; i++) {
snprintf(newHref, sizeof(newHref), "%s#%s", pnoteFilename, pnoteId);
epub->markAsFootnotePage(newHref);
}
}
}
Serial.printf("[%lu] [SCT] Total noterefs found: %d\n", millis(), noterefCount);

View File

@ -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,8 +196,7 @@ 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;
}
}
@ -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;
}
@ -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,8 +373,7 @@ 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
@ -443,32 +439,23 @@ 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++;
}
@ -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;
}
}

View File

@ -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,9 +26,7 @@ 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">
@ -35,9 +34,7 @@ struct ParagraphNote {
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; }
};

View File

@ -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() {

View File

@ -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,

View File

@ -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,8 +84,7 @@ void EpubReaderFootnotesScreen::render() {
}
// Instructions at bottom
renderer.drawText(SMALL_FONT_ID, marginLeft,
GfxRenderer::getScreenHeight() - 40,
renderer.drawText(SMALL_FONT_ID, marginLeft, GfxRenderer::getScreenHeight() - 40,
"UP/DOWN: Select CONFIRM: Go to footnote BACK: Return");
renderer.displayBuffer();

View File

@ -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,11 +42,8 @@ class EpubReaderFootnotesScreen final : public Screen {
const std::function<void(const char*)> onSelectFootnote;
int selectedIndex;
public:
EpubReaderFootnotesScreen(
GfxRenderer& renderer,
InputManager& inputManager,
const FootnotesData& footnotes,
public:
EpubReaderFootnotesScreen(GfxRenderer& renderer, InputManager& inputManager, const FootnotesData& footnotes,
const std::function<void()>& onGoBack,
const std::function<void(const char*)>& onSelectFootnote)
: Screen(renderer, inputManager),
@ -62,6 +56,6 @@ public:
void onExit() override;
void handleInput() override;
private:
private:
void render();
};

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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) {}