diff options
Diffstat (limited to 'src/readerview.cc')
| -rw-r--r-- | src/readerview.cc | 192 | 
1 files changed, 154 insertions, 38 deletions
diff --git a/src/readerview.cc b/src/readerview.cc index aef003d..d008be6 100644 --- a/src/readerview.cc +++ b/src/readerview.cc @@ -1,12 +1,50 @@  #include "readerview.h" -#include "sword.h"  #include <libbible.h>  #include <gdkmm/rgba.h> +#include <algorithm> + +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() +    : text()  { -    this->sword = new Sword();      this->conf = new struct config;      text.set_editable(false);      text.set_cursor_visible(false); @@ -17,43 +55,18 @@ ReaderView::ReaderView()      scroll->add(text);      add(*scroll);      // Open the passage we had last time -    string book = libbible::settingsRead("book"); +    std::string book = libbible::settingsRead("book");      int chapter = libbible::settingsReadInt("chapter");      if(book.empty() || chapter == 0) {          book = "Genesis";          chapter = 1;      } -    sword->getConfig(book, chapter, conf); +    updateConfig(book, chapter, conf);      refresh();  }  ReaderView::~ReaderView() {} -// Returns all new mods -std::vector<std::string> ReaderView::modsUpdated() { -    auto oldMods = getAllVersions(); -    std::sort(oldMods.begin(), oldMods.end()); -    sword = new Sword(); -    auto newMods = getAllVersions(); -    std::sort(newMods.begin(), newMods.end()); -    std::vector<std::string> justNew; -    std::set_difference(newMods.begin(), newMods.end(), oldMods.begin(), oldMods.end(), std::back_inserter(justNew)); -    refresh(); -    return justNew; -} - -void ReaderView::refresh() { -    auto textBuffer = text.get_buffer(); -    libbible::settingsWrite("book", conf->book); -    libbible::settingsWriteInt("chapter", conf->chapter); -    sword->getConfig(conf->book, conf->chapter, conf); -    // Get passage back -    string passage = conf->book + " " + std::to_string(conf->chapter); -    textBuffer->set_text(""); // Clear contents -    //auto iter = textBuffer->get_iter_at_offset(0); -    sword->fillBuffer(passage, textBuffer); -} -  void ReaderView::setChapter(int chapter) {      conf->chapter = chapter;      refresh(); @@ -81,18 +94,121 @@ std::string ReaderView::getBookFull() {  }  std::vector<std::string> ReaderView::getAllBooks() { -    return sword->getBooks(); -} - -void ReaderView::setVersion(std::string version) { -    sword->setModule(version); -    refresh(); +    string currMod = getCurrMod(); +    if(currMod.empty()) { +        return vector<string>(); +    } +    return libbible::getBooks(currMod);  }  std::string ReaderView::getVersion() {      return conf->version;  } -std::vector<std::string> ReaderView::getAllVersions() { -    return sword->getModules(); +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, "<big><b>No modules installed.</b></big>\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<Glib::RefPtr<Gtk::TextBuffer::Tag>> 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<Glib::RefPtr<Gtk::TextBuffer::Tag>> 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; +        } +    }  }  | 
