scriptura/scabbard.cpp

233 lines
6.8 KiB
C++

// Copyright 2021, Paul Mosier
//
// This file is part of Scriptura, a ncurses-based Bible study
// software for the libsword backend.
//
// Scriptura is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, under version 2 of the License.
//
// Scriptura is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Scriptura. If not, see <https://www.gnu.org/licenses/>.
// scabbard.cpp - manage interface to Sword
// it's funny, right?
#include <iostream>
#include <string.h>
#include "scabbard.h"
scabbard::scabbard() {
/* store what markup information the user has requested be shown
* SWBuf.c_str() returns the ascii code 48 for '0', so we have to do some
* math to get the proper boolean setting */
markred = parseConf(config["markup"]["redletters"]);
markstrongs = parseConf(config["markup"]["strongs"]);
markfoot = parseConf(config["markup"]["footnotes"]);
/* everything following is based on constructing the menu used to display
* to the reader about what modules the system has - start with a
* temporary array of module types */
int tmpnum = 4;
modtype tmpmods[4];
strcpy(tmpmods[0].label, "Generic Books");
tmpmods[0].keytype = 1;
strcpy(tmpmods[1].label, "Biblical Texts");
tmpmods[1].keytype = 0;
strcpy(tmpmods[2].label, "Lexicons / Dictionaries");
tmpmods[2].keytype = 2;
strcpy(tmpmods[3].label, "Commentaries");
tmpmods[3].keytype = 0;
// need some throwaway ints
int index[tmpnum];
for (int i = 0; i < tmpnum; i++) index[i] = 0;
// initialize other parts of modtype struct
for (int i = 0; i < tmpnum; i++) {
tmpmods[i].modlen = 1;
tmpmods[i].modlist =
(sword::SWModule**) malloc(sizeof(sword::SWModule));
if (! tmpmods[i].modlist)
wrapup(1, "Error allocating memory for scabbard\n");
}
// get list of installed tmpmods and store
for (iter = swrd.Modules.begin(); iter != swrd.Modules.end(); iter++) {
sword::SWBuf modName = iter->first;
sword::SWModule *mod = iter->second;
for (int i = 0; i < tmpnum; i++) {
// determine which classification of module this is
if (! strcmp(mod->getType(), tmpmods[i].label)) {
// increase array size if needed
if (tmpmods[i].modlen == index[i]) {
void* extarray = realloc(tmpmods[i].modlist,
sizeof(sword::SWModule) * (tmpmods[i].modlen+1));
if (extarray != NULL) {
tmpmods[i].modlist = (sword::SWModule**) extarray;
} else {
wrapup(1, "Error allocating memory for scabbard\n");
}
tmpmods[i].modlen++;
}
// catalog the module
(tmpmods[i].modlist)[index[i]] = mod;
index[i]++;
}
}
}
/* if a module type has no modules in it, we don't want to look at it again
* - do this by copying our temp array to the final array if elements
* exist */
nummods = 0;
for (int i = 0; i < tmpnum; i++) {
if (index[i] > 0) {
modules[nummods] = tmpmods[i];
nummods++;
}
}
}
const char* scabbard::parseVerses(sword::SWModule *text, sword::ListKey lk) {
// set output filters for text based on what we want to have
if (markred) {
text->addRenderFilter(new sword::OSISRedLetterWords());
text->addRenderFilter(new sword::GBFRedLetterWords());
}
if (markstrongs) text->addRenderFilter(new sword::OSISStrongs());
if (markfoot) {
text->addRenderFilter(new sword::OSISFootnotes());
text->addRenderFilter(new sword::GBFFootnotes());
}
// retrieve
sword::SWBuf excerpt = sword::SWBuf("", 0);
for (lk = sword::SW_POSITION(POS_TOP); !lk.popError(); lk++) {
text->setKey(lk);
// add verse heading
excerpt.append(lk.getShortText());
sword::VerseKey vk = (sword::VerseKey) lk.getElement();
if (vk.getVerse() < 10) excerpt.append(" ");
excerpt.append(" -- ");
/* if no filters selected, use stripText, otherwise we have as the
* default content whatever filters are written into the module */
if (markred + markstrongs + markfoot == 0) {
excerpt.append(text->stripText());
} else {
excerpt.append(text->renderText());
}
excerpt.append("\n");
}
excerpt.append("\0");
// excerpt will free itself on exit, make a copy to send back
const char* retval = strdup(excerpt.c_str());
return retval;
}
const char* scabbard::directSearch(sword::SWModule *text, modkey mod) {
text->setKey(mod.searchkey);
text->renderText(); // give the best fit to the searchkey
sword::SWBuf buf = sword::SWBuf("", 0);
buf.append(text->getKeyText());
buf.append("\n");
buf.append(text->getRawEntry());
buf.append("\0");
// buf will free itself on exit, make a copy
const char* retval = strdup(buf.c_str());
return retval;
}
starray scabbard::getModClassifications() {
starray retval;
retval = stinit(retval);
for (int i = 0; i < nummods; i++)
retval = stappend(retval, modules[i].label);
return retval;
}
starray scabbard::getModDescriptions(int type) {
starray retval;
retval = stinit(retval);
for (int i = 0; i < modules[type].modlen; i++)
retval = stappend(retval,
(modules[type].modlist)[i]->getDescription());
return retval;
}
const char* scabbard::getModName(int modt, int mod) {
return (modules[modt].modlist)[mod]->getName();
}
const char* scabbard::getModDescription(int modt, int mod) {
return (modules[modt].modlist)[mod]->getDescription();
}
int scabbard::getKeyType(int modt) {
return modules[modt].keytype;
}
const char* scabbard::getSpan(modkey mod) {
// get module and material specified
sword::SWModule *text = swrd.getModule(mod.modname);
// with the absence of certain config settings, getModule may return 0
if (text == 0) return "";
if (mod.keytype == 0) {
sword::VerseKey *key = (sword::VerseKey*) text->createKey();
sword::ListKey lk =
key->parseVerseList(mod.searchkey, mod.searchkey, true);
delete(key);
return parseVerses(text, lk);
} else return directSearch(text, mod);
}
const char* scabbard::search(modkey mod) {
sword::SWModule *text = swrd.getModule(mod.modname);
// with the absence of certain config settings, getModule may return 0
if (text == 0) return "";
if (mod.keytype == 0) {
sword::VerseKey *key = (sword::VerseKey*) text->createKey();
sword::SWKey *clone =
(key->parseVerseList(mod.scope, mod.scope, true)).clone();
sword::ListKey lk =
text->search(mod.searchkey, mod.searchtype, 0, clone);
const char* retval = parseVerses(text, lk);
delete(text);
delete(key);
delete(clone);
return retval;
} else return directSearch(text, mod);
}
/* really old code in case we need to pull output from diatheke
FILE *modlist = popen("diatheke -b system -k modulelist", "r");
char buf[1024];
fread(buf, sizeof(char), 1024, modlist);
pclose(modlist); */