aboutsummaryrefslogtreecommitdiffstats
path: root/src/modules/swmodule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/swmodule.cpp')
-rw-r--r--src/modules/swmodule.cpp661
1 files changed, 661 insertions, 0 deletions
diff --git a/src/modules/swmodule.cpp b/src/modules/swmodule.cpp
new file mode 100644
index 0000000..f37df27
--- /dev/null
+++ b/src/modules/swmodule.cpp
@@ -0,0 +1,661 @@
+/******************************************************************************
+ * swmodule.cpp -code for base class 'module'. Module is the basis for all
+ * types of modules (e.g. texts, commentaries, maps, lexicons,
+ * etc.)
+ */
+
+#include <string.h>
+#include <swmodule.h>
+#include <utilfuns.h>
+#include <regex.h> // GNU
+#include <swfilter.h>
+#include <versekey.h> // KLUDGE for Search
+#ifndef _MSC_VER
+#include <iostream>
+#endif
+
+SWDisplay SWModule::rawdisp;
+void SWModule::nullPercent(char percent, void *percentUserData) {}
+
+/******************************************************************************
+ * SWModule Constructor - Initializes data for instance of SWModule
+ *
+ * ENT: imodname - Internal name for module
+ * imoddesc - Name to display to user for module
+ * idisp - Display object to use for displaying
+ * imodtype - Type of Module (All modules will be displayed with
+ * others of same type under their modtype heading
+ * unicode - if this module is unicode
+ */
+
+SWModule::SWModule(const char *imodname, const char *imoddesc, SWDisplay *idisp, char *imodtype, SWTextEncoding encoding, SWTextDirection direction, SWTextMarkup markup, const char* imodlang) {
+ key = CreateKey();
+ entrybuf = new char [1];
+ *entrybuf = 0;
+ config = &ownConfig;
+ entrybufallocsize = 0;
+ modname = 0;
+ error = 0;
+ moddesc = 0;
+ modtype = 0;
+ modlang = 0;
+ this->encoding = encoding;
+ this->direction = direction;
+ this->markup = markup;
+ entrySize= -1;
+ disp = (idisp) ? idisp : &rawdisp;
+ stdstr(&modname, imodname);
+ stdstr(&moddesc, imoddesc);
+ stdstr(&modtype, imodtype);
+ stdstr(&modlang, imodlang);
+ stripFilters = new FilterList();
+ rawFilters = new FilterList();
+ renderFilters = new FilterList();
+ optionFilters = new FilterList();
+ encodingFilters = new FilterList();
+ skipConsecutiveLinks = true;
+ procEntAttr = true;
+}
+
+
+/******************************************************************************
+ * SWModule Destructor - Cleans up instance of SWModule
+ */
+
+SWModule::~SWModule()
+{
+ if (entrybuf)
+ delete [] entrybuf;
+ if (modname)
+ delete [] modname;
+ if (moddesc)
+ delete [] moddesc;
+ if (modtype)
+ delete [] modtype;
+ if (modlang)
+ delete [] modlang;
+
+ if (key) {
+ if (!key->Persist())
+ delete key;
+ }
+
+ stripFilters->clear();
+ rawFilters->clear();
+ renderFilters->clear();
+ optionFilters->clear();
+ encodingFilters->clear();
+ entryAttributes.clear();
+
+ delete stripFilters;
+ delete rawFilters;
+ delete renderFilters;
+ delete optionFilters;
+ delete encodingFilters;
+}
+
+
+/******************************************************************************
+ * SWModule::CreateKey - Allocates a key of specific type for module
+ *
+ * RET: pointer to allocated key
+ */
+
+SWKey *SWModule::CreateKey()
+{
+ return new SWKey();
+}
+
+
+/******************************************************************************
+ * SWModule::Error - Gets and clears error status
+ *
+ * RET: error status
+ */
+
+char SWModule::Error()
+{
+ char retval = error;
+
+ error = 0;
+ return retval;
+}
+
+
+/******************************************************************************
+ * SWModule::Name - Sets/gets module name
+ *
+ * ENT: imodname - value which to set modname
+ * [0] - only get
+ *
+ * RET: pointer to modname
+ */
+
+char *SWModule::Name(const char *imodname)
+{
+ return stdstr(&modname, imodname);
+}
+
+
+/******************************************************************************
+ * SWModule::Description - Sets/gets module description
+ *
+ * ENT: imoddesc - value which to set moddesc
+ * [0] - only get
+ *
+ * RET: pointer to moddesc
+ */
+
+char *SWModule::Description(const char *imoddesc)
+{
+ return stdstr(&moddesc, imoddesc);
+}
+
+
+/******************************************************************************
+ * SWModule::Type - Sets/gets module type
+ *
+ * ENT: imodtype - value which to set modtype
+ * [0] - only get
+ *
+ * RET: pointer to modtype
+ */
+
+char *SWModule::Type(const char *imodtype)
+{
+ return stdstr(&modtype, imodtype);
+}
+
+/******************************************************************************
+ * SWModule::Direction - Sets/gets module direction
+ *
+ * ENT: newdir - value which to set direction
+ * [-1] - only get
+ *
+ * RET: char direction
+ */
+char SWModule::Direction(signed char newdir) {
+ if (newdir != -1)
+ direction = newdir;
+ return direction;
+}
+
+/******************************************************************************
+ * SWModule::Encoding - Sets/gets module encoding
+ *
+ * ENT: newdir - value which to set direction
+ * [-1] - only get
+ *
+ * RET: char encoding
+ */
+char SWModule::Encoding(signed char newenc) {
+ if (newenc != -1)
+ encoding = newenc;
+ return encoding;
+}
+
+/******************************************************************************
+ * SWModule::Markup - Sets/gets module markup
+ *
+ * ENT: newdir - value which to set direction
+ * [-1] - only get
+ *
+ * RET: char markup
+ */
+char SWModule::Markup(signed char newmark) {
+ if (newmark != -1)
+ markup = newmark;
+ return markup;
+}
+
+
+/******************************************************************************
+ * SWModule::Lang - Sets/gets module language
+ *
+ * ENT: imodlang - value which to set modlang
+ * [0] - only get
+ *
+ * RET: pointer to modname
+ */
+
+char *SWModule::Lang(const char *imodlang)
+{
+ return stdstr(&modlang, imodlang);
+}
+
+
+/******************************************************************************
+ * SWModule::Disp - Sets/gets display driver
+ *
+ * ENT: idisp - value which to set disp
+ * [0] - only get
+ *
+ * RET: pointer to disp
+ */
+
+SWDisplay *SWModule::Disp(SWDisplay *idisp)
+{
+ if (idisp)
+ disp = idisp;
+
+ return disp;
+}
+
+
+/******************************************************************************
+ * SWModule::Display - Calls this modules display object and passes itself
+ *
+ * RET: error status
+ */
+
+char SWModule::Display()
+{
+ disp->Display(*this);
+ return 0;
+}
+
+
+/******************************************************************************
+ * SWModule::SetKey - Sets a key to this module for position to a particular
+ * record or set of records
+ *
+ * ENT: ikey - key with which to set this module
+ *
+ * RET: error status
+ */
+
+char SWModule::SetKey(const SWKey &ikey) {
+ return SetKey(&ikey);
+}
+
+char SWModule::SetKey(const SWKey *ikey)
+{
+ SWKey *oldKey = 0;
+
+ if (key) {
+ if (!key->Persist()) // if we have our own copy
+ oldKey = key;
+ }
+
+ if (!ikey->Persist()) { // if we are to keep our own copy
+ key = CreateKey();
+ *key = *ikey;
+ }
+ else key = (SWKey *)ikey; // if we are to just point to an external key
+
+ if (oldKey)
+ delete oldKey;
+
+ return 0;
+}
+
+
+/******************************************************************************
+ * SWModule::KeyText - Sets/gets module KeyText
+ *
+ * ENT: ikeytext - value which to set keytext
+ * [0] - only get
+ *
+ * RET: pointer to keytext
+ */
+
+const char *SWModule::KeyText(const char *ikeytext)
+{
+ if (ikeytext)
+ SetKey(ikeytext);
+
+ return *key;
+}
+
+
+/******************************************************************************
+ * SWModule::setPosition(SW_POSITION) - Positions this modules to an entry
+ *
+ * ENT: p - position (e.g. TOP, BOTTOM)
+ *
+ * RET: *this
+ */
+
+void SWModule::setPosition(SW_POSITION p) {
+ *key = p;
+ char saveError = key->Error();
+
+ switch (p) {
+ case POS_TOP:
+ (*this)++;
+ (*this)--;
+ break;
+
+ case POS_BOTTOM:
+ (*this)--;
+ (*this)++;
+ break;
+ }
+
+ error = saveError;
+}
+
+
+/******************************************************************************
+ * SWModule::increment - Increments module key a number of entries
+ *
+ * ENT: increment - Number of entries to jump forward
+ *
+ * RET: *this
+ */
+
+void SWModule::increment(int steps) {
+ (*key) += steps;
+ error = key->Error();
+}
+
+
+/******************************************************************************
+ * SWModule::decrement - Decrements module key a number of entries
+ *
+ * ENT: decrement - Number of entries to jump backward
+ *
+ * RET: *this
+ */
+
+void SWModule::decrement(int steps) {
+ (*key) -= steps;
+ error = key->Error();
+}
+
+
+/******************************************************************************
+ * SWModule::Search - Searches a module for a string
+ *
+ * ENT: istr - string for which to search
+ * searchType - type of search to perform
+ * >=0 - regex
+ * -1 - phrase
+ * -2 - multiword
+ * flags - options flags for search
+ * justCheckIfSupported - if set, don't search, only tell if this
+ * function supports requested search.
+ *
+ * RET: listkey set to verses that contain istr
+ */
+
+ListKey &SWModule::Search(const char *istr, int searchType, int flags, SWKey *scope, bool *justCheckIfSupported, void (*percent)(char, void *), void *percentUserData)
+{
+ SWKey *savekey = 0;
+ SWKey *searchkey = 0;
+ regex_t preg;
+ SWKey textkey;
+ char **words = 0;
+ char *wordBuf = 0;
+ int wordCount = 0;
+ const char *sres;
+ terminateSearch = false;
+ char perc = 1;
+ bool savePEA = isProcessEntryAttributes();
+
+ processEntryAttributes(false);
+ listkey.ClearList();
+
+ if (!key->Persist()) {
+ savekey = CreateKey();
+ *savekey = *key;
+ }
+ else savekey = key;
+
+ searchkey = (scope)?scope->clone():(key->Persist())?key->clone():0;
+ if (searchkey) {
+ searchkey->Persist(1);
+ SetKey(*searchkey);
+ }
+
+ (*percent)(perc, percentUserData);
+ // MAJOR KLUDGE: VerseKey::Index still return index within testament.
+ // VerseKey::NewIndex should be moved to Index and Index should be some
+ // VerseKey specific name
+ VerseKey *vkcheck = 0;
+#ifndef _WIN32_WCE
+ try {
+#endif
+ vkcheck = SWDYNAMIC_CAST(VerseKey, key);
+#ifndef _WIN32_WCE
+ }
+ catch (...) {}
+#endif
+ // end MAJOR KLUDGE
+
+ *this = BOTTOM;
+ // fix below when we find out the bug
+ long highIndex = (vkcheck)?32300/*vkcheck->NewIndex()*/:key->Index();
+ if (!highIndex)
+ highIndex = 1; // avoid division by zero errors.
+ *this = TOP;
+ if (searchType >= 0) {
+ flags |=searchType|REG_NOSUB|REG_EXTENDED;
+ regcomp(&preg, istr, flags);
+ }
+
+ (*percent)(++perc, percentUserData);
+ if (searchType == -2) {
+ wordBuf = (char *)calloc(sizeof(char), strlen(istr) + 1);
+ strcpy(wordBuf, istr);
+ words = (char **)calloc(sizeof(char *), 10);
+ int allocWords = 10;
+ words[wordCount] = strtok(wordBuf, " ");
+ while (words[wordCount]) {
+ wordCount++;
+ if (wordCount == allocWords) {
+ allocWords+=10;
+ words = (char **)realloc(words, sizeof(char *)*allocWords);
+ }
+ words[wordCount] = strtok(NULL, " ");
+ }
+ }
+
+ perc = 5;
+ (*percent)(perc, percentUserData);
+
+ while (!Error() && !terminateSearch) {
+
+
+ long mindex = 0;
+ if (vkcheck)
+ mindex = vkcheck->NewIndex();
+ else mindex = key->Index();
+ float per = (float)mindex / highIndex;
+ per *= 93;
+ per += 5;
+ char newperc = (char)per;
+// char newperc = (char)(5+(93*(((float)((vkcheck)?vkcheck->NewIndex():key->Index()))/highIndex)));
+ if (newperc > perc) {
+ perc = newperc;
+ (*percent)(perc, percentUserData);
+ }
+ else if (newperc < perc) {
+#ifndef _MSC_VER
+ std::cerr << "Serious error: new percentage complete is less than previous value\n";
+ std::cerr << "using vk? " << ((vkcheck)?"yes":"no") << "\n";
+ std::cerr << "index: " << ((vkcheck)?vkcheck->NewIndex():key->Index()) << "\n";
+ std::cerr << "highIndex: " << highIndex << "\n";
+ std::cerr << "newperc ==" << (int)newperc << "%" << "is smaller than\n";
+ std::cerr << "perc == " << (int )perc << "% \n";
+#endif
+ }
+ if (searchType >= 0) {
+ if (!regexec(&preg, StripText(), 0, 0, 0)) {
+ textkey = KeyText();
+ listkey << textkey;
+ }
+ }
+ else {
+ if (searchType == -1) {
+ sres = ((flags & REG_ICASE) == REG_ICASE) ? stristr(StripText(), istr) : strstr(StripText(), istr);
+ if (sres) {
+ textkey = KeyText();
+ listkey << textkey;
+ }
+ }
+ if (searchType == -2) {
+ int i;
+ const char *stripBuf = StripText();
+ for (i = 0; i < wordCount; i++) {
+ sres = ((flags & REG_ICASE) == REG_ICASE) ? stristr(stripBuf, words[i]) : strstr(stripBuf, words[i]);
+ if (!sres)
+ break;
+ }
+ if (i == wordCount) {
+ textkey = KeyText();
+ listkey << textkey;
+ }
+
+ }
+ }
+ (*this)++;
+ }
+ if (searchType >= 0)
+ regfree(&preg);
+
+ if (searchType == -2) {
+ free(words);
+ free(wordBuf);
+ }
+
+ SetKey(*savekey);
+
+ if (!savekey->Persist())
+ delete savekey;
+
+ if (searchkey)
+ delete searchkey;
+
+ listkey = TOP;
+ processEntryAttributes(savePEA);
+ (*percent)(100, percentUserData);
+
+ return listkey;
+}
+
+
+/******************************************************************************
+ * SWModule::StripText() - calls all stripfilters on current text
+ *
+ * ENT: buf - buf to massage instead of this modules current text
+ * len - max len of buf
+ *
+ * RET: this module's text at specified key location massaged by Strip filters
+ */
+
+const char *SWModule::StripText(char *buf, int len)
+{
+ return RenderText(buf, len, false);
+}
+
+
+/******************************************************************************
+ * SWModule::RenderText - calls all renderfilters on current text
+ *
+ * ENT: buf - buffer to Render instead of current module position
+ *
+ * RET: listkey set to verses that contain istr
+ */
+
+ const char *SWModule::RenderText(char *buf, int len, bool render) {
+ entryAttributes.clear();
+ char *tmpbuf = (buf) ? buf : getRawEntry();
+ SWKey *key = 0;
+ static char *null = "";
+
+ if (tmpbuf) {
+ unsigned long size = (len < 0) ? ((getEntrySize()<0) ? strlen(tmpbuf) : getEntrySize()) * FILTERPAD : len;
+ if (size > 0) {
+ key = (SWKey *)*this;
+
+ optionFilter(tmpbuf, size, key);
+
+ if (render) {
+ renderFilter(tmpbuf, size, key);
+ encodingFilter(tmpbuf, size, key);
+ }
+ else stripFilter(tmpbuf, size, key);
+ }
+ }
+ else {
+ tmpbuf = null;
+ }
+
+ return tmpbuf;
+}
+
+
+/******************************************************************************
+ * SWModule::RenderText - calls all renderfilters on current text
+ *
+ * ENT: tmpKey - key to use to grab text
+ *
+ * RET: this module's text at specified key location massaged by RenderFilers
+ */
+
+ const char *SWModule::RenderText(SWKey *tmpKey)
+{
+ SWKey *savekey;
+ const char *retVal;
+
+ if (!key->Persist()) {
+ savekey = CreateKey();
+ *savekey = *key;
+ }
+ else savekey = key;
+
+ SetKey(*tmpKey);
+
+ retVal = RenderText();
+
+ SetKey(*savekey);
+
+ if (!savekey->Persist())
+ delete savekey;
+
+ return retVal;
+}
+
+
+/******************************************************************************
+ * SWModule::StripText - calls all StripTextFilters on current text
+ *
+ * ENT: tmpKey - key to use to grab text
+ *
+ * RET: this module's text at specified key location massaged by Strip filters
+ */
+
+const char *SWModule::StripText(SWKey *tmpKey)
+{
+ SWKey *savekey;
+ const char *retVal;
+
+ if (!key->Persist()) {
+ savekey = CreateKey();
+ *savekey = *key;
+ }
+ else savekey = key;
+
+ SetKey(*tmpKey);
+
+ retVal = StripText();
+
+ SetKey(*savekey);
+
+ if (!savekey->Persist())
+ delete savekey;
+
+ return retVal;
+}
+
+
+const char *SWModule::getConfigEntry(const char *key) const {
+ ConfigEntMap::iterator it = config->find(key);
+ return (it != config->end()) ? it->second.c_str() : 0;
+}
+
+
+void SWModule::setConfig(ConfigEntMap *config) {
+ this->config = config;
+}