233 lines
6.8 KiB
C++
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); */
|
|
|