#include "readerview.h" #include #include #include using namespace std; std::string getCurrMod() { auto mods = libbible::getModuleNames(); std::string currMod = libbible::settingsRead("biblereader::currMod"); if(std::find(mods.begin(), mods.end(), currMod) == mods.end()) { currMod = libbible::settingsRead("module"); if(std::find(mods.begin(), mods.end(), currMod) == mods.end()) { if(! mods.empty()) { // New default mod (previous was deleted) currMod = *mods.begin(); libbible::settingsWrite("module", currMod); libbible::settingsWrite("biblereader::currMod", currMod); } else { currMod = std::string(); } } } return currMod; } void updateConfig(string book, int chapter, struct config *conf) { string currMod = getCurrMod(); if(currMod.empty()) { conf->chapter = 0; conf->book = ""; conf->bookFull = ""; conf->maxChapter = 0; conf->version = ""; } else { auto passages = libbible::getPassages(currMod, book); conf->chapter = chapter; conf->book = passages[0].bookShort; conf->bookFull = passages[0].book; conf->maxChapter = passages.back().chapterStart; conf->version = currMod; } } ReaderView::ReaderView() : text() { this->conf = new struct config; text.set_editable(false); text.set_cursor_visible(false); text.set_wrap_mode(Gtk::WrapMode::WRAP_WORD_CHAR); //text.override_background_color(*(new Gdk::RGBA("#1d1f21"))); //text.override_color(*(new Gdk::RGBA("#c5c8c6"))); auto scroll = new Gtk::ScrolledWindow(); scroll->add(text); add(*scroll); // Open the passage we had last time std::string book = libbible::settingsRead("book"); int chapter = libbible::settingsReadInt("chapter"); if(book.empty() || chapter == 0) { book = "Genesis"; chapter = 1; } updateConfig(book, chapter, conf); refresh(); } ReaderView::~ReaderView() {} void ReaderView::setChapter(int chapter) { conf->chapter = chapter; refresh(); } int ReaderView::getChapter() { return conf->chapter; } int ReaderView::getChapterMax() { return conf->maxChapter; } void ReaderView::setBook(std::string book) { conf->book = book; refresh(); } std::string ReaderView::getBook() { return conf->book; } std::string ReaderView::getBookFull() { return conf->bookFull; } std::vector ReaderView::getAllBooks() { string currMod = getCurrMod(); if(currMod.empty()) { return vector(); } return libbible::getBooks(currMod); } std::string ReaderView::getVersion() { return conf->version; } void ReaderView::refresh() { auto buf = text.get_buffer(); libbible::settingsWrite("book", conf->book); libbible::settingsWriteInt("chapter", conf->chapter); updateConfig(conf->book, conf->chapter, conf); // Get passage back string ref = conf->book + " " + std::to_string(conf->chapter); buf->set_text(""); // Clear contents string currMod = getCurrMod(); if(currMod.empty()) { auto iter = buf->get_iter_at_offset(0); iter = buf->insert_markup(iter, "No modules installed.\n"); iter = buf->insert_markup(iter, "Please download some modules at:\n"); iter = buf->insert_markup(iter, "\thttp://crosswire.org/sword/modules/ModDisp.jsp?modType=Bibles\n"); iter = buf->insert_markup(iter, "Then install them using the menu in the upper right corner, or use the built-in installer to download and install modules."); return; } auto texts = libbible::getText(libbible::getPassage(currMod, ref)); auto iter = buf->get_iter_at_offset(0); auto verseSize = buf->create_tag(); verseSize->property_size() = libbible::settingsReadInt("fontsize"); if(verseSize->property_size() == 0) { verseSize->property_size() = 12000; } auto verseScale = buf->create_tag(); verseScale->property_scale() = 0.8; auto titleScale = buf->create_tag(); titleScale->property_scale() = 1.5; titleScale->property_weight() = 600; auto verseOffset = buf->create_tag(); verseOffset->property_rise() = 3000; auto indent = buf->create_tag(); indent->property_left_margin() = 40; auto redletter = buf->create_tag(); redletter->property_foreground_gdk() = Gdk::Color("red"); int verse = 0; string indentString = " "; bool isNewline = true; for(auto tex : texts) { std::vector> tags = {verseSize}; bool isParagraph = false; bool isIndent = false; bool isDivineName = false; bool isPreverse = false; for(string modifier : tex.modifiers) { if(modifier == "paragraph") { isParagraph = true; } else if (modifier == "line indent0") { isIndent = true; } else if (modifier == "divineName") { isDivineName = true; } else if (modifier == "wordsOfJesus") { tags.push_back(redletter); } else if (modifier == "title") { tags.push_back(titleScale); // Ensure newline if(!tex.text.empty() and tex.text.back() != '\n') { tex.text.push_back('\n'); } } else if (modifier == "preverse") { isPreverse = true; } else if (modifier == "parallel") { // We don't support this (yet) tex.text = ""; } } if(isIndent) { isParagraph = false; if(isNewline) { tags.push_back(indent); } } if(isParagraph) { iter = buf->insert_with_tags(iter, indentString, tags); } if(tex.verse != verse && ! isPreverse) { std::vector> verseTags(tags.begin(), tags.end()); verseTags.push_back(verseScale); verseTags.push_back(verseOffset); iter = buf->insert_with_tags(iter, " " + std::to_string(tex.verse), verseTags); verse = tex.verse; } if(isDivineName) { // There's no small caps support. Sigh. We do fake small caps instead. // Because i lazy, first letter is normal caps and rest small caps, always. transform(tex.text.begin(), tex.text.end(), tex.text.begin(), ::toupper); iter = buf->insert_with_tags(iter, tex.text.substr(0, 1), tags); auto tag = buf->create_tag(); tag->property_scale() = 0.75; tags.push_back(tag); iter = buf->insert_with_tags(iter, tex.text.substr(1), tags); } else { iter = buf->insert_with_tags(iter, tex.text, tags); } if(!tex.text.empty() and tex.text.back() == '\n') { isNewline = true; } else { isNewline = false; } } }