summaryrefslogtreecommitdiff
path: root/src/keys/versekey.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/keys/versekey.cpp')
-rw-r--r--src/keys/versekey.cpp1193
1 files changed, 636 insertions, 557 deletions
diff --git a/src/keys/versekey.cpp b/src/keys/versekey.cpp
index cb7bbfc..9c50a04 100644
--- a/src/keys/versekey.cpp
+++ b/src/keys/versekey.cpp
@@ -1,7 +1,24 @@
/******************************************************************************
* VerseKey.cpp - code for class 'VerseKey'- a standard Biblical verse key
+ *
+ *
+ * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org)
+ * CrossWire Bible Society
+ * P. O. Box 2528
+ * Tempe, AZ 85280-2528
+ *
+ * This program 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 version 2.
+ *
+ * This program 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.
+ *
*/
+
#include <swmacs.h>
#include <stdio.h>
#include <fcntl.h>
@@ -13,9 +30,9 @@
#include <swkey.h>
#include <swlog.h>
#include <versekey.h>
-#include <localemgr.h>
#include <swlocale.h>
#include <roman.h>
+#include <versemgr.h>
SWORD_NAMESPACE_START
@@ -26,23 +43,15 @@ SWClass VerseKey::classdef(classes);
* Initialize static members of VerseKey
*/
-#include <canon.h> // Initialize static members of canonical books structure
-
-struct sbook *VerseKey::builtin_books[2] = {0,0};
-const char VerseKey::builtin_BMAX[2] = {39, 27};
-long *VerseKey::offsets[2][2] = {{VerseKey::otbks, VerseKey::otcps}, {VerseKey::ntbks, VerseKey::ntcps}};
int VerseKey::instance = 0;
-VerseKey::LocaleCache VerseKey::localeCache;
/******************************************************************************
* VerseKey::init - initializes instance of VerseKey
*/
-void VerseKey::init() {
+void VerseKey::init(const char *v11n) {
myclass = &classdef;
- if (!instance)
- initstatics();
instance++;
autonorm = 1; // default auto normalization to true
@@ -50,13 +59,15 @@ void VerseKey::init() {
upperBound = 0;
lowerBound = 0;
boundSet = false;
- testament = 0;
- book = 0;
- chapter = 0;
- verse = 0;
- locale = 0;
-
- setLocale(LocaleMgr::getSystemLocaleMgr()->getDefaultLocaleName());
+ testament = 1;
+ book = 1;
+ chapter = 1;
+ verse = 1;
+ suffix = 0;
+ tmpClone = 0;
+ refSys = 0;
+
+ setVersificationSystem(v11n);
}
/******************************************************************************
@@ -104,6 +115,57 @@ VerseKey::VerseKey(VerseKey const &k) : SWKey(k)
/******************************************************************************
+ * VerseKey::setFromOther - Positions this VerseKey to another VerseKey
+ */
+
+void VerseKey::setFromOther(const VerseKey &ikey) {
+ if (refSys == ikey.refSys) {
+ testament = ikey.Testament();
+ book = ikey.Book();
+ chapter = ikey.Chapter();
+ verse = ikey.Verse();
+ suffix = ikey.getSuffix();
+ }
+ // Here is where we will do v11n system conversions in the future
+ // when we have a conversion mechanism (Ben Morgan has started
+ // thinking about this)
+ else {
+ // For now, this is the best we can do
+ setText(ikey.getText());
+ }
+}
+
+
+void VerseKey::positionFrom(const SWKey &ikey) {
+ error = 0;
+ const SWKey *fromKey = &ikey;
+ ListKey *tryList = SWDYNAMIC_CAST(ListKey, fromKey);
+ if (tryList) {
+ SWKey *k = tryList->getElement();
+ if (k) fromKey = k;
+ }
+ VerseKey *tryVerse = SWDYNAMIC_CAST(VerseKey, fromKey);
+ if (tryVerse) {
+ setFromOther(*tryVerse);
+ }
+ else {
+ SWKey::positionFrom(*fromKey);
+ parse();
+ }
+
+ // should we always perform bounds checks? Tried but seems to cause infinite recursion
+ if (_compare(UpperBound()) > 0) {
+ setFromOther(UpperBound());
+ error = KEYERR_OUTOFBOUNDS;
+ }
+ if (_compare(LowerBound()) < 0) {
+ setFromOther(LowerBound());
+ error = KEYERR_OUTOFBOUNDS;
+ }
+}
+
+
+/******************************************************************************
* VerseKey::copyFrom - Equates this VerseKey to another VerseKey
*/
@@ -114,6 +176,9 @@ void VerseKey::copyFrom(const VerseKey &ikey) {
book = ikey.Book();
chapter = ikey.Chapter();
verse = ikey.Verse();
+ suffix = ikey.getSuffix();
+ setLocale(ikey.getLocale());
+ setVersificationSystem(ikey.getVersificationSystem());
if (ikey.isBoundSet()) {
LowerBound(ikey.LowerBound());
UpperBound(ikey.UpperBound());
@@ -145,11 +210,19 @@ void VerseKey::copyFrom(const SWKey &ikey) {
}
-VerseKey::VerseKey(const char *min, const char *max) : SWKey()
+VerseKey::VerseKey(const char *min, const char *max, const char *v11n) : SWKey()
{
- init();
- LowerBound(min);
- UpperBound(max);
+ init(v11n);
+ ListKey tmpListKey = ParseVerseList(min);
+ if (tmpListKey.Count()) {
+ VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.GetElement(0));
+ LowerBound(*newElement);
+ }
+ tmpListKey = ParseVerseList(max, min, true);
+ if (tmpListKey.Count()) {
+ VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.GetElement(0));
+ UpperBound((newElement->isBoundSet())?newElement->UpperBound():*newElement);
+ }
setPosition(TOP);
}
@@ -167,117 +240,33 @@ SWKey *VerseKey::clone() const
*/
VerseKey::~VerseKey() {
- if (upperBound)
- delete upperBound;
- if (lowerBound)
- delete lowerBound;
- if (locale)
- delete [] locale;
+
+ delete tmpClone;
--instance;
}
-void VerseKey::setLocale(const char *name) {
- char *BMAX;
- struct sbook **lbooks;
- bool useCache = false;
+void VerseKey::setVersificationSystem(const char *name) {
+ const VerseMgr::System *newRefSys = VerseMgr::getSystemVerseMgr()->getVersificationSystem(name);
+ // TODO: cheese, but what should we do if requested v11n system isn't found?
+ if (!newRefSys) newRefSys = VerseMgr::getSystemVerseMgr()->getVersificationSystem("KJV");
+ if (refSys != newRefSys) {
+ refSys = newRefSys;
+ BMAX[0] = refSys->getBMAX()[0];
+ BMAX[1] = refSys->getBMAX()[1];
- if (localeCache.name)
- useCache = (!strcmp(localeCache.name, name));
-
- if (!useCache) { // if we're setting params for a new locale
- stdstr(&(localeCache.name), name);
- localeCache.abbrevsCnt = 0;
- }
-
- SWLocale *locale = (useCache) ? localeCache.locale : LocaleMgr::getSystemLocaleMgr()->getLocale(name);
- localeCache.locale = locale;
-
- if (locale) {
- locale->getBooks(&BMAX, &lbooks);
- setBooks(BMAX, lbooks);
- setBookAbbrevs(locale->getBookAbbrevs(), localeCache.abbrevsCnt);
- localeCache.abbrevsCnt = abbrevsCnt;
+ // TODO: adjust bounds for versificaion system ???
+ // TODO: when we have mapping done, rethink this
+ //necessary as our bounds might not mean anything in the new v11n system
+ ClearBounds();
}
- else {
- setBooks(builtin_BMAX, builtin_books);
- setBookAbbrevs(builtin_abbrevs, localeCache.abbrevsCnt);
- localeCache.abbrevsCnt = abbrevsCnt;
- }
- stdstr(&(this->locale), localeCache.name);
-
- if (lowerBound)
- LowerBound().setLocale(name);
- if (upperBound)
- UpperBound().setLocale(name);
-}
-
-void VerseKey::setBooks(const char *iBMAX, struct sbook **ibooks) {
- BMAX = iBMAX;
- books = ibooks;
-}
-
-void VerseKey::setBookAbbrevs(const struct abbrev *bookAbbrevs, unsigned int size) {
- abbrevs = bookAbbrevs;
- if (!size) {
- for (abbrevsCnt = 0; *abbrevs[abbrevsCnt].ab; abbrevsCnt++) {
- /*
- if (strcmp(abbrevs[abbrevsCnt-1].ab, abbrevs[abbrevsCnt].ab) > 0) {
- fprintf(stderr, "ERROR: book abbreviation (canon.h or locale) misordered at entry: %s\n", abbrevs[abbrevsCnt].ab);
- exit(-1);
- }
- */
- }
-
- if (SWLog::getSystemLog()->getLogLevel() > 0) { //make sure log is wanted, this loop stuff costs a lot of time
- for (int t = 0; t < 2; t++) {
- for (int i = 0; i < BMAX[t]; i++) {
- const int bn = getBookAbbrev(books[t][i].name);
- if ((bn-1)%39 != i) {
- SWLog::getSystemLog()->logError("VerseKey::Book: %s does not have a matching toupper abbrevs entry! book number returned was: %d(%d). Required entry should be:",
- books[t][i].name, bn, i);
- char *abbr = 0;
- stdstr(&abbr, books[t][i].name, 2);
- strstrip(abbr);
-
- StringMgr* stringMgr = StringMgr::getSystemStringMgr();
- const bool hasUTF8Support = StringMgr::hasUTF8Support();
- if (hasUTF8Support) { //we have support for UTF-8 handling; we expect UTF-8 encoded locales
- stringMgr->upperUTF8(abbr, strlen(abbr)*2);
- }
- else {
- stringMgr->upperLatin1(abbr);
- }
- SWLog::getSystemLog()->logError("%s=%d", abbr, (t*39)+i+1);
- }
- }
- }
- }
- }
- else abbrevsCnt = size;
}
-/******************************************************************************
- * VerseKey::initstatics - initializes statics. Performed only when first
- * instance on VerseKey (or descendent) is created.
- */
-
-void VerseKey::initstatics() {
- int l1, l2, chaptmp = 0;
-
- builtin_books[0] = otbooks;
- builtin_books[1] = ntbooks;
+const char *VerseKey::getVersificationSystem() const { return refSys->getName(); }
- for (l1 = 0; l1 < 2; l1++) {
- for (l2 = 0; l2 < builtin_BMAX[l1]; l2++) {
- builtin_books[l1][l2].versemax = &vm[chaptmp];
- chaptmp += builtin_books[l1][l2].chapmax;
- }
- }
-}
/******************************************************************************
@@ -288,37 +277,18 @@ void VerseKey::initstatics() {
char VerseKey::parse(bool checkAutoNormalize)
{
-
-
- testament = 2;
- book = BMAX[1];
+ testament = BMAX[1]?2:1;
+ book = BMAX[BMAX[1]?1:0];
chapter = 1;
verse = 1;
- int booklen = 0;
int error = 0;
if (keytext) {
- ListKey tmpListKey = VerseKey::ParseVerseList(keytext);
+ ListKey tmpListKey = ParseVerseList(keytext);
if (tmpListKey.Count()) {
- SWKey::setText((const char *)tmpListKey);
- for (int i = 1; i < 3; i++) {
- for (int j = 1; j <= BMAX[i-1]; j++) {
- int matchlen = strlen(books[i-1][j-1].name);
- if (!strncmp(keytext, books[i-1][j-1].name, matchlen)) {
- if (matchlen > booklen) {
- booklen = matchlen;
- testament = i;
- book = j;
- }
- }
- }
- }
-
- if (booklen) {
- sscanf(&keytext[booklen], "%d:%d", &chapter, &verse);
- }
- else error = 1;
+ this->positionFrom(*tmpListKey.getElement(0));
+ error = this->error;
} else error = 1;
}
if (checkAutoNormalize) {
@@ -338,7 +308,7 @@ char VerseKey::parse(bool checkAutoNormalize)
void VerseKey::freshtext() const
{
char buf[2024];
- int realtest = testament;
+ int realTest = testament;
int realbook = book;
if (book < 1) {
@@ -347,14 +317,18 @@ void VerseKey::freshtext() const
else sprintf(buf, "[ Testament %d Heading ]", (int)testament);
}
else {
- if (realbook > BMAX[realtest-1]) {
- realbook -= BMAX[realtest-1];
- if (realtest < 2)
- realtest++;
- if (realbook > BMAX[realtest-1])
- realbook = BMAX[realtest-1];
+ if (realbook > BMAX[realTest-1]) {
+ realbook -= BMAX[realTest-1];
+ if (realTest < 2)
+ realTest++;
+ if (realbook > BMAX[realTest-1])
+ realbook = BMAX[realTest-1];
+ }
+ sprintf(buf, "%s %d:%d", getBookName(), chapter, verse);
+ if (suffix) {
+ buf[strlen(buf)+1] = 0;
+ buf[strlen(buf)] = suffix;
}
- sprintf(buf, "%s %d:%d", books[realtest-1][realbook-1].name, chapter, verse);
}
stdstr((char **)&keytext, buf);
@@ -362,19 +336,24 @@ void VerseKey::freshtext() const
-/******************************************************************************
- * VerseKey::getBookAbbrev - Attempts to find a book abbreviation for a buffer
+/************************************************************************
+ * VerseKey::getBookAbbrev - Attempts to find a book no from a name or
+ * abbreviation
*
* ENT: abbr - key for which to search;
* RET: book number or < 0 = not valid
*/
-int VerseKey::getBookAbbrev(const char *iabbr)
+int VerseKey::getBookAbbrev(const char *iabbr) const
{
int diff, abLen, min, max, target, retVal = -1;
char *abbr = 0;
+ int abbrevsCnt;
+
+ const struct abbrev *abbrevs = getPrivateLocale()->getBookAbbrevs(&abbrevsCnt);
+
StringMgr* stringMgr = StringMgr::getSystemStringMgr();
const bool hasUTF8Support = StringMgr::hasUTF8Support();
@@ -420,7 +399,15 @@ int VerseKey::getBookAbbrev(const char *iabbr)
break;
}
- retVal = (!diff) ? abbrevs[target].book : -1;
+ if (!diff) {
+ // lets keep moving forward till we find an abbrev in our refSys
+ retVal = refSys->getBookNumberByOSISName(abbrevs[target].osis);
+ while ((retVal < 0) && (target < max) && (!strncmp(abbr, abbrevs[target+1].ab, abLen))) {
+ target++;
+ retVal = refSys->getBookNumberByOSISName(abbrevs[target].osis);
+ }
+ }
+ else retVal = -1;
}
if (retVal > 0)
break;
@@ -431,6 +418,36 @@ int VerseKey::getBookAbbrev(const char *iabbr)
/******************************************************************************
+ * VerseKey::validateCurrentLocale - be sure a locale book abbrevs set is complete
+ *
+ */
+void VerseKey::validateCurrentLocale() const {
+ if (SWLog::getSystemLog()->getLogLevel() >= SWLog::LOG_DEBUG) { //make sure log is wanted, this loop stuff costs a lot of time
+ for (int i = 0; i < refSys->getBookCount(); i++) {
+ const int bn = getBookAbbrev(getPrivateLocale()->translate(refSys->getBook(i)->getLongName()));
+ if (bn != i+1) {
+ char *abbr = 0;
+ stdstr(&abbr, getPrivateLocale()->translate(refSys->getBook(i)->getLongName()), 2);
+ strstrip(abbr);
+ SWLog::getSystemLog()->logDebug("VerseKey::Book: %s does not have a matching toupper abbrevs entry! book number returned was: %d, should be %d. Required entry to add to locale:", abbr, bn, i);
+
+ StringMgr* stringMgr = StringMgr::getSystemStringMgr();
+ const bool hasUTF8Support = StringMgr::hasUTF8Support();
+ if (hasUTF8Support) { //we have support for UTF-8 handling; we expect UTF-8 encoded locales
+ stringMgr->upperUTF8(abbr, strlen(abbr)*2);
+ }
+ else {
+ stringMgr->upperLatin1(abbr);
+ }
+ SWLog::getSystemLog()->logDebug("%s=%s\n", abbr, refSys->getBook(i)->getOSISName());
+ delete [] abbr;
+ }
+ }
+ }
+}
+
+
+/******************************************************************************
* VerseKey::ParseVerseList - Attempts to parse a buffer into separate
* verse entries returned in a ListKey
*
@@ -446,19 +463,24 @@ int VerseKey::getBookAbbrev(const char *iabbr)
* COMMENT: This code works but wreaks. Rewrite to make more maintainable.
*/
-ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool expandRange) {
- char book[2048];
- char number[2048];
+ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool expandRange, bool useChapterAsVerse) {
+
+ // hold on to our own copy of params, as threads/recursion may change outside values
+ const char *bufStart = buf;
+ SWBuf iBuf = buf;
+ buf = iBuf.c_str();
+ SWBuf iDefaultKey = defaultKey;
+ if (defaultKey) defaultKey = iDefaultKey.c_str();
+
+ char book[2048]; // TODO: bad, remove
+ char number[2048]; // TODO: bad, remove
*book = 0;
*number = 0;
int tobook = 0;
int tonumber = 0;
+ char suffix = 0;
int chap = -1, verse = -1;
int bookno = 0;
- VerseKey curKey, lBound, lastKey;
- curKey.setLocale(getLocale());
- lBound.setLocale(getLocale());
- lastKey.setLocale(getLocale());
int loop;
char comma = 0;
char dash = 0;
@@ -470,13 +492,50 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
bool inTerm = true;
int notAllDigits = 0;
- curKey.AutoNormalize(0);
- if (defaultKey) lastKey = defaultKey;
-
+ // assert we have a buffer
+ if (!buf) return internalListKey;
+
+ VerseKey *curKey = (VerseKey *)this->clone();
+ VerseKey *lastKey = (VerseKey *)this->clone();
+ lastKey->ClearBounds();
+ curKey->ClearBounds();
+
+ // some silly checks for corner cases
+ if (!strcmp(buf, "[ Module Heading ]")) {
+ curKey->Verse(0);
+ curKey->Chapter(0);
+ curKey->Book(0);
+ curKey->Testament(0);
+ lastKey->LowerBound(*curKey);
+ lastKey->UpperBound(*curKey);
+ internalListKey << *lastKey;
+ delete curKey;
+ delete lastKey;
+ return internalListKey;
+ }
+ if ((!strncmp(buf, "[ Testament ", 12)) &&
+ (isdigit(buf[12])) &&
+ (!strcmp(buf+13, " Heading ]"))) {
+ curKey->Verse(0);
+ curKey->Chapter(0);
+ curKey->Book(0);
+ curKey->Testament(buf[12]-48);
+ lastKey->LowerBound(*curKey);
+ lastKey->UpperBound(*curKey);
+ internalListKey << *lastKey;
+ delete curKey;
+ delete lastKey;
+ return internalListKey;
+ }
+
+ curKey->AutoNormalize(AutoNormalize());
+ lastKey->AutoNormalize(0);
+ if (defaultKey) *lastKey = defaultKey;
+
while (*buf) {
switch (*buf) {
case ':':
- if (buf[1] != ' ') { // for silly Mat 1:1: this verse....
+ if (buf[1] != ' ') { // for silly "Mat 1:1: this verse...."
number[tonumber] = 0;
tonumber = 0;
if (*number)
@@ -502,7 +561,7 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
break;
}
- case '-':
+ case '-':
case ',': // on number new verse
case ';': // on number new chapter
number[tonumber] = 0;
@@ -535,7 +594,8 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
for (loop = strlen(book) - 1; loop+1; loop--) {
if (book[loop] == ' ') {
- if (isroman(&book[loop+1])) {
+ // "PS C" is ok, but "II C" is not ok
+ if (isroman(&book[loop+1]) && !isroman(book,loop)) {
if (verse == -1) {
verse = chap;
chap = from_rom(&book[loop+1]);
@@ -549,49 +609,64 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
if ((!stricmp(book, "V")) || (!stricmp(book, "VER"))) { // Verse abbrev
if (verse == -1) {
verse = chap;
- chap = lastKey.Chapter();
+ chap = lastKey->Chapter();
*book = 0;
}
}
if ((!stricmp(book, "ch")) || (!stricmp(book, "chap"))) { // Verse abbrev
- strcpy(book, lastKey.getBookName());
+ strcpy(book, lastKey->getBookName());
}
bookno = getBookAbbrev(book);
}
if (((bookno > -1) || (!*book)) && ((*book) || (chap >= 0) || (verse >= 0))) {
char partial = 0;
- curKey.Verse(1);
- curKey.Chapter(1);
- curKey.Book(1);
+ curKey->Verse(1);
+ curKey->Chapter(1);
+ curKey->Book(1);
if (bookno < 0) {
- curKey.Testament(lastKey.Testament());
- curKey.Book(lastKey.Book());
+ curKey->Testament(lastKey->Testament());
+ curKey->Book(lastKey->Book());
}
else {
- curKey.Testament(1);
- curKey.Book(bookno);
+ int t = 1;
+ if (bookno > BMAX[0]) {
+ t++;
+ bookno -= BMAX[0];
+ }
+ curKey->Testament(t);
+ curKey->Book(bookno);
}
+
if (((comma)||((verse < 0)&&(bookno < 0)))&&(!lastPartial)) {
// if (comma) {
- curKey.Chapter(lastKey.Chapter());
- curKey.Verse(chap); // chap because this is the first number captured
+ curKey->Chapter(lastKey->Chapter());
+ curKey->Verse(chap); // chap because this is the first number captured
}
else {
+ if (useChapterAsVerse && verse < 0 && chap > 0 && curKey->getChapterMax() == 1) {
+ verse = chap;
+ chap = 1;
+ }
+
+
if (chap >= 0) {
- curKey.Chapter(chap);
+ curKey->Chapter(chap);
}
else {
partial++;
- curKey.Chapter(1);
+ curKey->Chapter(1);
}
if (verse >= 0) {
- curKey.Verse(verse);
+ curKey->Verse(verse);
+ if (suffix) {
+ curKey->setSuffix(suffix);
+ }
}
else {
partial++;
- curKey.Verse(1);
+ curKey->Verse(1);
}
}
@@ -599,43 +674,42 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
for (q = 0; ((buf[q]) && (buf[q] == ' ')); q++);
if ((buf[q] == '-') && (expandRange)) { // if this is a dash save lowerBound and wait for upper
buf+=q;
- lastKey.LowerBound(curKey);
- lastKey.setPosition(TOP);
- tmpListKey << lastKey;
- tmpListKey.GetElement()->userData = (void *)buf;
+ lastKey->LowerBound(*curKey);
+ lastKey->setPosition(TOP);
+ tmpListKey << *lastKey;
+ tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str()));
}
else {
if (!dash) { // if last separator was not a dash just add
if (expandRange && partial) {
- lastKey.LowerBound(curKey);
+ lastKey->LowerBound(*curKey);
if (partial > 1)
- curKey.setPosition(MAXCHAPTER);
+ curKey->setPosition(MAXCHAPTER);
if (partial > 0)
- curKey = MAXVERSE;
- lastKey.UpperBound(curKey);
- lastKey = TOP;
- tmpListKey << lastKey;
- tmpListKey.GetElement()->userData = (void *)buf;
+ *curKey = MAXVERSE;
+ lastKey->UpperBound(*curKey);
+ *lastKey = TOP;
+ tmpListKey << *lastKey;
+ tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str()));
}
else {
- // we store non-range entries as strings so we don't traverse
- // maybe we should consider just setting
- // lowerBound and upperBound to the same value
- tmpListKey << curKey.getText();
- tmpListKey.GetElement()->userData = (void *)buf;
- lastKey = curKey;
+ lastKey->LowerBound(*curKey);
+ lastKey->UpperBound(*curKey);
+ *lastKey = TOP;
+ tmpListKey << *lastKey;
+ tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str()));
}
}
else if (expandRange) {
VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.GetElement());
if (newElement) {
if (partial > 1)
- curKey = MAXCHAPTER;
+ *curKey = MAXCHAPTER;
if (partial > 0)
- curKey = MAXVERSE;
- newElement->UpperBound(curKey);
+ *curKey = MAXVERSE;
+ newElement->UpperBound(*curKey);
*newElement = TOP;
- tmpListKey.GetElement()->userData = (void *)buf;
+ tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str()));
}
}
}
@@ -644,6 +718,7 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
*book = 0;
chap = -1;
verse = -1;
+ suffix = 0;
if (*buf == ',')
comma = 1;
else comma = 0;
@@ -652,13 +727,13 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
else dash = 0;
break;
case 10: // ignore these
- case 13:
- case '[':
- case ']':
- case '(':
- case ')':
- case '{':
- case '}':
+ case 13:
+ case '[':
+ case ']':
+ case '(':
+ case ')':
+ case '{':
+ case '}':
break;
case '.':
if (buf > orig) // ignore (break) if preceeding char is not a digit
@@ -675,7 +750,7 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
chap = atoi(number);
*number = 0;
break;
-
+
default:
if (isdigit(*buf)) {
number[tonumber++] = *buf;
@@ -683,12 +758,17 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
else {
switch (*buf) {
case ' ': // ignore these and don't reset number
- case 'f':
case 'F':
break;
default:
- number[tonumber] = 0;
- tonumber = 0;
+ // suffixes (and oddly 'f'-- ff.)
+ if ((*buf >= 'a' && *buf <= 'z') && (chap >=0)) {
+ suffix = *buf;
+ }
+ else {
+ number[tonumber] = 0;
+ tonumber = 0;
+ }
break;
}
}
@@ -726,7 +806,8 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
for (loop = strlen(book) - 1; loop+1; loop--) {
if (book[loop] == ' ') {
- if (isroman(&book[loop+1])) {
+ // "PS C" is ok, but "II C" is not ok
+ if (isroman(&book[loop+1]) && !isroman(book,loop)) {
if (verse == -1) {
verse = chap;
chap = from_rom(&book[loop+1]);
@@ -735,92 +816,109 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
}
break;
}
- }
-
+ }
+
if ((!stricmp(book, "V")) || (!stricmp(book, "VER"))) { // Verse abbrev.
if (verse == -1) {
verse = chap;
- chap = lastKey.Chapter();
+ chap = lastKey->Chapter();
*book = 0;
}
}
-
+
if ((!stricmp(book, "ch")) || (!stricmp(book, "chap"))) { // Verse abbrev
- strcpy(book, lastKey.getBookName());
+ strcpy(book, lastKey->getBookName());
}
bookno = getBookAbbrev(book);
}
if (((bookno > -1) || (!*book)) && ((*book) || (chap >= 0) || (verse >= 0))) {
char partial = 0;
- curKey.Verse(1);
- curKey.Chapter(1);
- curKey.Book(1);
+ curKey->Verse(1);
+ curKey->Chapter(1);
+ curKey->Book(1);
if (bookno < 0) {
- curKey.Testament(lastKey.Testament());
- curKey.Book(lastKey.Book());
+ curKey->Testament(lastKey->Testament());
+ curKey->Book(lastKey->Book());
}
else {
- curKey.Testament(1);
- curKey.Book(bookno);
+ int t = 1;
+ if (bookno > BMAX[0]) {
+ t++;
+ bookno -= BMAX[0];
+ }
+ curKey->Testament(t);
+ curKey->Book(bookno);
}
if (((comma)||((verse < 0)&&(bookno < 0)))&&(!lastPartial)) {
- curKey.Chapter(lastKey.Chapter());
- curKey.Verse(chap); // chap because this is the first number captured
+ curKey->Chapter(lastKey->Chapter());
+ curKey->Verse(chap); // chap because this is the first number captured
}
else {
+ if (useChapterAsVerse && verse < 0 && chap > 0 && curKey->getChapterMax() == 1) {
+ verse = chap;
+ chap = 1;
+ }
+
+
if (chap >= 0) {
- curKey.Chapter(chap);
+ curKey->Chapter(chap);
}
else {
partial++;
- curKey.Chapter(1);
+ curKey->Chapter(1);
}
if (verse >= 0) {
- curKey.Verse(verse);
+ curKey->Verse(verse);
+ if (suffix) {
+ curKey->setSuffix(suffix);
+ }
}
else {
partial++;
- curKey.Verse(1);
+ curKey->Verse(1);
}
}
if ((*buf == '-') && (expandRange)) { // if this is a dash save lowerBound and wait for upper
- lastKey.LowerBound(curKey);
- lastKey = TOP;
- tmpListKey << lastKey;
- tmpListKey.GetElement()->userData = (void *)buf;
+ lastKey->LowerBound(*curKey);
+ *lastKey = TOP;
+ tmpListKey << *lastKey;
+ tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str()));
}
else {
if (!dash) { // if last separator was not a dash just add
if (expandRange && partial) {
- lastKey.LowerBound(curKey);
+ lastKey->LowerBound(*curKey);
if (partial > 1)
- curKey = MAXCHAPTER;
+ *curKey = MAXCHAPTER;
if (partial > 0)
- curKey = MAXVERSE;
- lastKey.UpperBound(curKey);
- lastKey = TOP;
- tmpListKey << lastKey;
- tmpListKey.GetElement()->userData = (void *)buf;
+ *curKey = MAXVERSE;
+ lastKey->UpperBound(*curKey);
+ *lastKey = TOP;
+ tmpListKey << *lastKey;
+ tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str()));
}
else {
- tmpListKey << curKey.getText();
- tmpListKey.GetElement()->userData = (void *)buf;
- lastKey = curKey;
+ lastKey->LowerBound(*curKey);
+ lastKey->UpperBound(*curKey);
+ *lastKey = TOP;
+ tmpListKey << *lastKey;
+// tmpListKey << curKey->getText();
+ tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str()));
}
}
else if (expandRange) {
VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.GetElement());
if (newElement) {
if (partial > 1)
- curKey = MAXCHAPTER;
+ *curKey = MAXCHAPTER;
if (partial > 0)
- curKey = MAXVERSE;
- newElement->UpperBound(curKey);
+ *curKey = MAXVERSE;
+ newElement->UpperBound(*curKey);
*newElement = TOP;
- tmpListKey.GetElement()->userData = (void *)buf;
+ tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str()));
}
}
}
@@ -830,6 +928,9 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
internalListKey = tmpListKey;
internalListKey = TOP; // Align internalListKey to first element before passing back;
+ delete curKey;
+ delete lastKey;
+
return internalListKey;
}
@@ -838,16 +939,23 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
* VerseKey::LowerBound - sets / gets the lower boundary for this key
*/
-VerseKey &VerseKey::LowerBound(const char *lb)
+VerseKey &VerseKey::LowerBound(const VerseKey &lb)
{
- if (!lowerBound)
- initBounds();
+ initBounds();
- (*lowerBound) = lb;
- lowerBound->Normalize();
- lowerBound->setLocale( this->getLocale() );
+ lowerBound = lb.Index();
+ lowerBoundComponents.test = lb.getTestament();
+ lowerBoundComponents.book = lb.getBook();
+ lowerBoundComponents.chap = lb.getChapter();
+ lowerBoundComponents.verse = lb.getVerse();
+
+ // both this following check and UpperBound check force upperBound to
+ // change allowing LowerBound then UpperBound logic to always flow
+ // and set values without restrictions, as expected
+ if (upperBound < lowerBound) upperBound = lowerBound;
boundSet = true;
- return (*lowerBound);
+
+ return LowerBound();
}
@@ -855,40 +963,21 @@ VerseKey &VerseKey::LowerBound(const char *lb)
* VerseKey::UpperBound - sets / gets the upper boundary for this key
*/
-VerseKey &VerseKey::UpperBound(const char *ub)
+VerseKey &VerseKey::UpperBound(const VerseKey &ub)
{
- if (!upperBound)
- initBounds();
-
-// need to set upperbound parsing to resolve to max verse/chap if not specified
- (*upperBound) = ub;
- if (*upperBound < *lowerBound)
- *upperBound = *lowerBound;
- upperBound->Normalize();
- upperBound->setLocale( this->getLocale() );
-
-// until we have a proper method to resolve max verse/chap use this kludge
- int len = strlen(ub);
- bool alpha = false;
- bool versespec = false;
- bool chapspec = false;
- for (int i = 0; i < len; i++) {
- if (isalpha(ub[i]))
- alpha = true;
- if (ub[i] == ':') // if we have a : we assume verse spec
- versespec = true;
- if ((isdigit(ub[i])) && (alpha)) // if digit after alpha assume chap spec
- chapspec = true;
- }
- if (!chapspec)
- *upperBound = MAXCHAPTER;
- if (!versespec)
- *upperBound = MAXVERSE;
-
+ initBounds();
+
+ upperBound = ub.Index();
+ upperBoundComponents.test = ub.getTestament();
+ upperBoundComponents.book = ub.getBook();
+ upperBoundComponents.chap = ub.getChapter();
+ upperBoundComponents.verse = ub.getVerse();
-// -- end kludge
+ // see LowerBound comment, above
+ if (upperBound < lowerBound) upperBound = lowerBound;
boundSet = true;
- return (*upperBound);
+
+ return UpperBound();
}
@@ -898,10 +987,16 @@ VerseKey &VerseKey::UpperBound(const char *ub)
VerseKey &VerseKey::LowerBound() const
{
- if (!lowerBound)
- initBounds();
+ initBounds();
+ if (!isAutoNormalize()) {
+ tmpClone->testament = lowerBoundComponents.test;
+ tmpClone->book = lowerBoundComponents.book;
+ tmpClone->chapter = lowerBoundComponents.chap;
+ tmpClone->setVerse (lowerBoundComponents.verse);
+ }
+ else tmpClone->Index(lowerBound);
- return (*lowerBound);
+ return (*tmpClone);
}
@@ -911,10 +1006,16 @@ VerseKey &VerseKey::LowerBound() const
VerseKey &VerseKey::UpperBound() const
{
- if (!upperBound)
- initBounds();
+ initBounds();
+ if (!isAutoNormalize()) {
+ tmpClone->testament = upperBoundComponents.test;
+ tmpClone->book = upperBoundComponents.book;
+ tmpClone->chapter = upperBoundComponents.chap;
+ tmpClone->setVerse (upperBoundComponents.verse);
+ }
+ else tmpClone->Index(upperBound);
- return (*upperBound);
+ return (*tmpClone);
}
@@ -924,33 +1025,36 @@ VerseKey &VerseKey::UpperBound() const
void VerseKey::ClearBounds()
{
- initBounds();
+ delete tmpClone;
+ tmpClone = 0;
+ boundSet = false;
}
void VerseKey::initBounds() const
{
- if (!upperBound) {
- upperBound = new VerseKey();
- upperBound->AutoNormalize(0);
- upperBound->Headings(1);
- }
- if (!lowerBound) {
- lowerBound = new VerseKey();
- lowerBound->AutoNormalize(0);
- lowerBound->Headings(1);
- }
-
- lowerBound->Testament(0);
- lowerBound->Book(0);
- lowerBound->Chapter(0);
- lowerBound->Verse(0);
+ if (!tmpClone) {
+ tmpClone = (VerseKey *)this->clone();
+ tmpClone->AutoNormalize(0);
+ tmpClone->Headings(1);
+ tmpClone->Testament((BMAX[1])?2:1);
+ tmpClone->Book(BMAX[(BMAX[1])?1:0]);
+ tmpClone->Chapter(tmpClone->getChapterMax());
+ tmpClone->Verse(tmpClone->getVerseMax());
+ upperBound = tmpClone->Index();
+ upperBoundComponents.test = tmpClone->getTestament();
+ upperBoundComponents.book = tmpClone->getBook();
+ upperBoundComponents.chap = tmpClone->getChapter();
+ upperBoundComponents.verse = tmpClone->getVerse();
+
+ lowerBound = 0;
+ lowerBoundComponents.test = 0;
+ lowerBoundComponents.book = 0;
+ lowerBoundComponents.chap = 0;
+ lowerBoundComponents.verse = 0;
- upperBound->Testament(2);
- upperBound->Book(BMAX[1]);
- upperBound->Chapter(books[1][BMAX[1]-1].chapmax);
- upperBound->Verse(books[1][BMAX[1]-1].versemax[upperBound->Chapter()-1]);
- boundSet = false;
+ }
+ else tmpClone->setLocale(getLocale());
}
@@ -975,7 +1079,7 @@ const char *VerseKey::getShortText() const {
else sprintf(buf, "[ Testament %d Heading ]", (int)testament);
}
else {
- sprintf(buf, "%s %d:%d", books[testament-1][book-1].prefAbbrev, chapter, verse);
+ sprintf(buf, "%s %d:%d", getBookAbbrev(), chapter, verse);
}
stdstr(&stext, buf);
return stext;
@@ -983,13 +1087,20 @@ const char *VerseKey::getShortText() const {
const char *VerseKey::getBookName() const {
- return books[testament-1][book-1].name;
+ return getPrivateLocale()->translate(refSys->getBook(((testament>1)?BMAX[0]:0)+book-1)->getLongName());
+}
+
+
+const char *VerseKey::getOSISBookName() const {
+ return refSys->getBook(((testament>1)?BMAX[0]:0)+book-1)->getOSISName();
}
const char *VerseKey::getBookAbbrev() const {
- return books[testament-1][book-1].prefAbbrev;
+ return refSys->getBook(((testament>1)?BMAX[0]:0)+book-1)->getPreferredAbbreviation();
}
+
+
/******************************************************************************
* VerseKey::setPosition(SW_POSITION) - Positions this key
*
@@ -1000,32 +1111,50 @@ const char *VerseKey::getBookAbbrev() const {
void VerseKey::setPosition(SW_POSITION p) {
switch (p) {
- case POS_TOP:
- testament = LowerBound().Testament();
- book = LowerBound().Book();
- chapter = LowerBound().Chapter();
- verse = LowerBound().Verse();
+ case POS_TOP: {
+ const VerseKey *lb = &LowerBound();
+ testament = (lb->Testament() || headings) ? lb->Testament() : 1;
+ book = (lb->Book() || headings) ? lb->Book() : 1;
+ chapter = (lb->Chapter() || headings) ? lb->Chapter() : 1;
+ verse = (lb->Verse() || headings) ? lb->Verse() : 1;
+ suffix = lb->getSuffix();
break;
- case POS_BOTTOM:
- testament = UpperBound().Testament();
- book = UpperBound().Book();
- chapter = UpperBound().Chapter();
- verse = UpperBound().Verse();
+ }
+ case POS_BOTTOM: {
+ const VerseKey *ub = &UpperBound();
+ testament = (ub->Testament() || headings) ? ub->Testament() : 1;
+ book = (ub->Book() || headings) ? ub->Book() : 1;
+ chapter = (ub->Chapter() || headings) ? ub->Chapter() : 1;
+ verse = (ub->Verse() || headings) ? ub->Verse() : 1;
+ suffix = ub->getSuffix();
break;
+ }
case POS_MAXVERSE:
Normalize();
- verse = books[testament-1][book-1].versemax[chapter-1];
+ verse = getVerseMax();
+ suffix = 0;
break;
case POS_MAXCHAPTER:
verse = 1;
+ suffix = 0;
Normalize();
- chapter = books[testament-1][book-1].chapmax;
+ chapter = getChapterMax();
break;
- }
+ }
Normalize(1);
Error(); // clear error from normalize
}
+int VerseKey::getChapterMax() const {
+ const VerseMgr::Book *b = refSys->getBook(((testament>1)?BMAX[0]:0)+book-1);
+ return (b) ? b->getChapterMax() : -1;
+}
+
+int VerseKey::getVerseMax() const {
+ const VerseMgr::Book *b = refSys->getBook(((testament>1)?BMAX[0]:0)+book-1);
+ return (b) ? b->getVerseMax(chapter) : -1;
+}
+
/******************************************************************************
* VerseKey::increment - Increments key a number of verses
@@ -1079,11 +1208,11 @@ void VerseKey::decrement(int step) {
void VerseKey::Normalize(char autocheck)
{
- error = 0;
if (((!autocheck) || (autonorm)) // only normalize if we were explicitely called or if autonorm is turned on
&&
((!headings) || ((verse) && (chapter)))) { // this is cheeze and temporary until deciding what actions should be taken; so headings should only be turned on when positioning with Index() or incrementors
+ error = 0;
while ((testament < 3) && (testament > 0)) {
@@ -1100,40 +1229,45 @@ void VerseKey::Normalize(char autocheck)
continue;
}
- if (chapter > books[testament-1][book-1].chapmax) {
- chapter -= books[testament-1][book-1].chapmax;
+ if (chapter > getChapterMax()) {
+ chapter -= getChapterMax();
book++;
continue;
}
- if (chapter < 1) {
- if (--book > 0) {
- chapter += books[testament-1][book-1].chapmax;
- }
- else {
- if (testament > 1) {
- chapter += books[0][BMAX[0]-1].chapmax;
- }
- }
- continue;
- }
+ if (chapter < 1) {
+ if (--book > 0) {
+ chapter += getChapterMax();
+ verse = getVerseMax();
+ }
+ else {
+ if (testament > 1) {
+ chapter += refSys->getBook(BMAX[0]-1)->getChapterMax();
+ verse = refSys->getBook(BMAX[0]-1)->getVerseMax(chapter);
+ }
+ }
+ continue;
+ }
- if (verse > books[testament-1][book-1].versemax[chapter-1]) { // -1 because e.g chapter 1 of Matthew is books[1][0].versemax[0]
- verse -= books[testament-1][book-1].versemax[chapter++ - 1];
+ if (verse > getVerseMax()) { // -1 because e.g chapter 1 of Matthew is books[1][0].versemax[0]
+ verse -= getVerseMax();
+ chapter++;
continue;
}
if (verse < 1) {
if (--chapter > 0) {
- verse += books[testament-1][book-1].versemax[chapter-1];
+ verse += getVerseMax();
}
else {
if (book > 1) {
- verse += books[testament-1][book-2].versemax[books[testament-1][book-2].chapmax-1];
+ const VerseMgr::Book *prevBook = refSys->getBook(((testament>1)?BMAX[0]:0)+book-2);
+ verse += prevBook->getVerseMax(prevBook->getChapterMax());
}
else {
if (testament > 1) {
- verse += books[0][BMAX[0]-1].versemax[books[0][BMAX[0]-1].chapmax-1];
+ const VerseMgr::Book *lastOTBook = refSys->getBook(BMAX[0]-1);
+ verse += lastOTBook->getVerseMax(lastOTBook->getChapterMax());
}
}
}
@@ -1143,11 +1277,11 @@ void VerseKey::Normalize(char autocheck)
break; // If we've made it this far (all failure checks continue) we're ok
}
- if (testament > 2) {
- testament = 2;
+ if (testament > (BMAX[1]?2:1)) {
+ testament = BMAX[1]?2:1;
book = BMAX[testament-1];
- chapter = books[testament-1][book-1].chapmax;
- verse = books[testament-1][book-1].versemax[chapter-1];
+ chapter = getChapterMax();
+ verse = getVerseMax();
error = KEYERR_OUTOFBOUNDS;
}
@@ -1161,11 +1295,11 @@ void VerseKey::Normalize(char autocheck)
// should we always perform bounds checks? Tried but seems to cause infinite recursion
if (_compare(UpperBound()) > 0) {
- setText(UpperBound(), false);
+ positionFrom(UpperBound());
error = KEYERR_OUTOFBOUNDS;
}
if (_compare(LowerBound()) < 0) {
- setText(LowerBound(), false);
+ positionFrom(LowerBound());
error = KEYERR_OUTOFBOUNDS;
}
}
@@ -1173,24 +1307,24 @@ void VerseKey::Normalize(char autocheck)
/******************************************************************************
- * VerseKey::Testament - Gets testament
+ * VerseKey::getTestament - Gets testament
*
* RET: value of testament
*/
-char VerseKey::Testament() const
+char VerseKey::getTestament() const
{
return testament;
}
/******************************************************************************
- * VerseKey::Book - Gets book
+ * VerseKey::getBook - Gets book
*
* RET: value of book
*/
-char VerseKey::Book() const
+char VerseKey::getBook() const
{
return book;
}
@@ -1202,7 +1336,7 @@ char VerseKey::Book() const
* RET: value of chapter
*/
-int VerseKey::Chapter() const
+int VerseKey::getChapter() const
{
return chapter;
}
@@ -1214,14 +1348,14 @@ int VerseKey::Chapter() const
* RET: value of verse
*/
-int VerseKey::Verse() const
+int VerseKey::getVerse() const
{
return verse;
}
/******************************************************************************
- * VerseKey::Testament - Sets/gets testament
+ * VerseKey::setTestament - Sets/gets testament
*
* ENT: itestament - value which to set testament
* [MAXPOS(char)] - only get
@@ -1230,64 +1364,68 @@ int VerseKey::Verse() const
* if changed -> previous value of testament
*/
-char VerseKey::Testament(char itestament)
+void VerseKey::setTestament(char itestament)
{
- char retval = testament;
-
if (itestament != MAXPOS(char)) {
testament = itestament;
Normalize(1);
}
- return retval;
}
/******************************************************************************
- * VerseKey::Book - Sets/gets book
+ * VerseKey::setBook - Sets/gets book
*
* ENT: ibook - value which to set book
- * [MAXPOS(char)] - only get
- *
- * RET: if unchanged -> value of book
- * if changed -> previous value of book
*/
-char VerseKey::Book(char ibook)
+void VerseKey::setBook(char ibook)
{
- char retval = book;
-
- Chapter(1);
- book = ibook;
+ verse = ibook ? 1 : 0;
+ chapter = ibook ? 1 : 0;
+ book = ibook;
Normalize(1);
-
- return retval;
}
+
/******************************************************************************
- * VerseKey::Chapter - Sets/gets chapter
- *
- * ENT: ichapter - value which to set chapter
- * [MAXPOS(int)] - only get
+ * VerseKey::setBookName - Sets/gets book by name
*
- * RET: if unchanged -> value of chapter
- * if changed -> previous value of chapter
+ * ENT: bname - book name/abbrev
*/
-int VerseKey::Chapter(int ichapter)
+void VerseKey::setBookName(const char *bname)
{
- int retval = chapter;
+ int bnum = getBookAbbrev(bname);
+ if (bnum > -1) {
+ if (bnum > BMAX[0]) {
+ bnum -= BMAX[0];
+ testament = 2;
+ }
+ else testament = 1;
+ setBook(bnum);
+ }
+ else error = KEYERR_OUTOFBOUNDS;
+}
+
+
+/******************************************************************************
+ * VerseKey::setChapter - Sets/gets chapter
+ *
+ * ENT: ichapter - value which to set chapter
+ */
- Verse(1);
+void VerseKey::setChapter(int ichapter)
+{
+ verse = ichapter ? 1 : 0;
chapter = ichapter;
Normalize(1);
-
- return retval;
}
/******************************************************************************
- * VerseKey::Verse - Sets/gets verse
+ * VerseKey::setVerse - Sets/gets verse
*
* ENT: iverse - value which to set verse
* [MAXPOS(int)] - only get
@@ -1296,37 +1434,36 @@ int VerseKey::Chapter(int ichapter)
* if changed -> previous value of verse
*/
-int VerseKey::Verse(int iverse)
+void VerseKey::setVerse(int iverse)
{
- int retval = verse;
-
+ setSuffix(0);
verse = iverse;
Normalize(1);
+}
- return retval;
+
+char VerseKey::getSuffix() const {
+ return suffix;
}
+void VerseKey::setSuffix(char suf) {
+ suffix = suf;
+}
/******************************************************************************
* VerseKey::AutoNormalize - Sets/gets flag that tells VerseKey to auto-
* matically normalize itself when modified
- *
- * ENT: iautonorm - value which to set autonorm
- * [MAXPOS(char)] - only get
- *
- * RET: if unchanged -> value of autonorm
- * if changed -> previous value of autonorm
*/
-char VerseKey::AutoNormalize(char iautonorm)
+bool VerseKey::isAutoNormalize() const
{
- char retval = autonorm;
+ return autonorm;
+}
- if (iautonorm != MAXPOS(char)) {
- autonorm = iautonorm;
- Normalize(1);
- }
- return retval;
+void VerseKey::setAutoNormalize(bool iautonorm)
+{
+ autonorm = iautonorm?1:0;
+ Normalize(1);
}
@@ -1392,34 +1529,27 @@ long VerseKey::Index() const
if (!testament) { // if we want module heading
offset = 0;
- verse = 0;
+ }
+ else if (!book) { // we want testament heading
+ offset = ((testament == 2) ? refSys->getNTStartOffset():0) + 1;
}
else {
- if (!book)
- chapter = 0;
- if (!chapter)
- verse = 0;
-
- offset = offsets[testament-1][0][book];
- offset = offsets[testament-1][1][(int)offset + chapter];
- if (!(offset|verse)) // if we have a testament but nothing else.
- offset = 1;
+ offset = refSys->getOffsetFromVerse((((testament>1)?BMAX[0]:0)+book-1), chapter, verse);
}
- return (offset + verse);
+ return offset;
}
/******************************************************************************
- * VerseKey::Index - Gets index based upon current verse
+ * VerseKey::TestamentIndex - Gets index based upon current verse
*
* RET: offset
*/
-long VerseKey::NewIndex() const
+long VerseKey::TestamentIndex() const
{
- static long otMaxIndex = 32300 - 8245; // total positions - new testament positions
-// static long otMaxIndex = offsets[0][1][(int)offsets[0][0][BMAX[0]] + books[0][BMAX[0]].chapmax];
- return ((testament-1) * otMaxIndex) + Index();
+ long offset = Index();
+ return (testament > 1) ? offset - refSys->getNTStartOffset() : offset;
}
@@ -1433,60 +1563,31 @@ long VerseKey::NewIndex() const
long VerseKey::Index(long iindex)
{
- long offset;
-
-// This is the dirty stuff --------------------------------------------
-
- if (!testament)
- testament = 1;
-
- if (iindex < 1) { // if (-) or module heading
- if (testament < 2) {
- if (iindex < 0) {
- testament = 0; // previously we changed 0 -> 1
- error = KEYERR_OUTOFBOUNDS;
- }
- else testament = 0; // we want module heading
- }
- else {
- testament--;
- iindex = (offsets[testament-1][1][offsize[testament-1][1]-1] + books[testament-1][BMAX[testament-1]-1].versemax[books[testament-1][BMAX[testament-1]-1].chapmax-1]) + iindex; // What a doozy! ((offset of last chapter + number of verses in the last chapter) + iindex)
- }
+ int b;
+ error = refSys->getVerseFromOffset(iindex, &b, &chapter, &verse);
+ book = (unsigned char)b;
+ testament = 1;
+ if (book > BMAX[0]) {
+ book -= BMAX[0];
+ testament = 2;
}
+ // special case for Module and Testament heading
+ if (book < 0) { testament = 0; book = 0; }
+ if (chapter < 0) { book = 0; chapter = 0; }
-// --------------------------------------------------------------------
-
-
- if (testament) {
- if ((!error) && (iindex)) {
- offset = findindex(offsets[testament-1][1], offsize[testament-1][1], iindex);
- verse = iindex - offsets[testament-1][1][offset];
- book = findindex(offsets[testament-1][0], offsize[testament-1][0], offset);
- chapter = offset - offsets[testament-1][0][VerseKey::book];
- verse = (chapter) ? verse : 0; // funny check. if we are index=1 (testmt header) all gets set to 0 exept verse. Don't know why. Fix if you figure out. Think its in the offsets table.
- if (verse) { // only check if -1 won't give negative
- if (verse > books[testament-1][book-1].versemax[chapter-1]) {
- if (testament > 1) {
- verse = books[testament-1][book-1].versemax[chapter-1];
- error = KEYERR_OUTOFBOUNDS;
- }
- else {
- testament++;
- Index(verse - books[testament-2][book-1].versemax[chapter-1]);
- }
- }
- }
- }
- }
- if (_compare(UpperBound()) > 0) {
- *this = UpperBound();
+ long i = Index();
+
+ initBounds();
+ if (i > upperBound) {
+ i = Index(upperBound);
error = KEYERR_OUTOFBOUNDS;
}
- if (_compare(LowerBound()) < 0) {
- *this = LowerBound();
+ if (i < lowerBound) {
+ i = Index(lowerBound);
error = KEYERR_OUTOFBOUNDS;
}
- return Index();
+
+ return i;
}
@@ -1524,37 +1625,23 @@ int VerseKey::compare(const SWKey &ikey)
int VerseKey::_compare(const VerseKey &ivkey)
{
- long keyval1 = 0;
- long keyval2 = 0;
+ unsigned long keyval1 = 0;
+ unsigned long keyval2 = 0;
- keyval1 += Testament() * 1000000000;
+ keyval1 += Testament() * 1000000000;
keyval2 += ivkey.Testament() * 1000000000;
- keyval1 += Book() * 1000000;
- keyval2 += ivkey.Book() * 1000000;
- keyval1 += Chapter() * 1000;
- keyval2 += ivkey.Chapter() * 1000;
- keyval1 += Verse();
- keyval2 += ivkey.Verse();
- keyval1 -= keyval2;
- keyval1 = (keyval1) ? ((keyval1 > 0) ? 1 : -1) /*keyval1/labs(keyval1)*/:0; // -1 | 0 | 1
+ keyval1 += Book() * 10000000;
+ keyval2 += ivkey.Book() * 10000000;
+ keyval1 += Chapter() * 10000;
+ keyval2 += ivkey.Chapter() * 10000;
+ keyval1 += Verse() * 50;
+ keyval2 += ivkey.Verse() * 50;
+ keyval1 += (int)getSuffix();
+ keyval2 += (int)ivkey.getSuffix();
+ keyval1 = (keyval1 != keyval2) ? ((keyval1 > keyval2) ? 1 : -1) : 0; // -1 | 0 | 1
return keyval1;
}
-const char *VerseKey::osisotbooks[] = {
- "Gen","Exod","Lev","Num","Deut","Josh","Judg","Ruth","1Sam","2Sam",
- "1Kgs","2Kgs","1Chr","2Chr","Ezra","Neh","Esth","Job","Ps",
- "Prov", // added this. Was not in OSIS spec
- "Eccl",
- "Song","Isa","Jer","Lam","Ezek","Dan","Hos","Joel","Amos","Obad",
- "Jonah","Mic","Nah","Hab","Zeph","Hag","Zech","Mal","Bar","PrAzar",
- "Bel","Sus","1Esd","2Esd","AddEsth","EpJer","Jdt","1Macc","2Macc","3Macc",
- "4Macc","PrMan","Ps151","Sir","Tob","Wis"};
-const char *VerseKey::osisntbooks[] = {
- "Matt","Mark","Luke","John","Acts","Rom","1Cor","2Cor","Gal","Eph",
- "Phil","Col","1Thess","2Thess","1Tim","2Tim","Titus","Phlm","Heb","Jas",
- "1Pet","2Pet","1John","2John","3John","Jude","Rev"};
-const char **VerseKey::osisbooks[] = { osisotbooks, osisntbooks };
-
const char *VerseKey::getOSISRef() const {
static char buf[5][254];
@@ -1564,53 +1651,50 @@ const char *VerseKey::getOSISRef() const {
loop = 0;
if (Verse())
- sprintf(buf[loop], "%s.%d.%d", osisbooks[Testament()-1][Book()-1], (int)Chapter(), (int)Verse());
+ sprintf(buf[loop], "%s.%d.%d", getOSISBookName(), (int)Chapter(), (int)Verse());
else if (Chapter())
- sprintf(buf[loop], "%s.%d", osisbooks[Testament()-1][Book()-1], (int)Chapter());
+ sprintf(buf[loop], "%s.%d", getOSISBookName(), (int)Chapter());
else if (Book())
- sprintf(buf[loop], "%s", osisbooks[Testament()-1][Book()-1]);
+ sprintf(buf[loop], "%s", getOSISBookName());
else buf[loop][0] = 0;
return buf[loop++];
}
-const int VerseKey::getOSISBookNum(const char *bookab) {
- int i;
- for (i=0; i < 39; i++)
- {
- if (!strncmp(bookab, osisotbooks[i], strlen(osisotbooks[i])))
- {
- //printf("VerseKey::getOSISBookNum %s is OT %d\n", bookab, i+1);
- return i+1;
- }
- }
- for (i=0; i < 27; i++)
- {
- if (!strncmp(bookab, osisntbooks[i], strlen(osisotbooks[i])))
- {
- //printf("VerseKey::getOSISBookNum %s is NT %d\n", bookab, i+1);
- return i+1;
- }
- }
- return -1;
-}
-
-
/******************************************************************************
* VerseKey::getRangeText - returns parsable range text for this key
*/
const char *VerseKey::getRangeText() const {
- if (isBoundSet()) {
- char buf[1023];
- sprintf(buf, "%s-%s", (const char *)LowerBound(), (const char *)UpperBound());
- stdstr(&rangeText, buf);
+ if (isBoundSet() && lowerBound != upperBound) {
+ SWBuf buf = (const char *)LowerBound();
+ buf += "-";
+ buf += (const char *)UpperBound();
+ stdstr(&rangeText, buf.c_str());
}
else stdstr(&rangeText, getText());
return rangeText;
}
+/******************************************************************************
+ * VerseKey::getOSISRefRangeText - returns parsable range text for this key
+ */
+
+const char *VerseKey::getOSISRefRangeText() const {
+ if (isBoundSet() && (lowerBound != upperBound)) {
+ SWBuf buf = LowerBound().getOSISRef();
+ buf += "-";
+ buf += UpperBound().getOSISRef();
+ stdstr(&rangeText, buf.c_str());
+ }
+ else stdstr(&rangeText, getOSISRef());
+ return rangeText;
+}
+
+
+// TODO: this is static so we have no context. We can only parse KJV v11n now
+// possibly add a const char *versification = KJV param?
const char *VerseKey::convertToOSIS(const char *inRef, const SWKey *lastKnownKey) {
static SWBuf outRef;
@@ -1620,12 +1704,13 @@ const char *VerseKey::convertToOSIS(const char *inRef, const SWKey *lastKnownKey
ListKey verses = defLanguage.ParseVerseList(inRef, (*lastKnownKey), true);
const char *startFrag = inRef;
for (int i = 0; i < verses.Count(); i++) {
- VerseKey *element = SWDYNAMIC_CAST(VerseKey, verses.GetElement(i));
- char buf[5120];
+ SWKey *element = verses.GetElement(i);
+// VerseKey *element = SWDYNAMIC_CAST(VerseKey, verses.GetElement(i));
+ SWBuf buf;
+ // TODO: This code really needs to not use fixed size arrays
char frag[800];
char preJunk[800];
char postJunk[800];
- memset(buf, 0, 5120);
memset(frag, 0, 800);
memset(preJunk, 0, 800);
memset(postJunk, 0, 800);
@@ -1633,32 +1718,26 @@ const char *VerseKey::convertToOSIS(const char *inRef, const SWKey *lastKnownKey
outRef += *startFrag;
startFrag++;
}
- if (element) {
- memmove(frag, startFrag, ((const char *)element->userData - startFrag) + 1);
- frag[((const char *)element->userData - startFrag) + 1] = 0;
- int j;
- for (j = strlen(frag)-1; j && (strchr(" {};,()[].", frag[j])); j--);
- if (frag[j+1])
- strcpy(postJunk, frag+j+1);
- frag[j+1]=0;
- startFrag += ((const char *)element->userData - startFrag) + 1;
- sprintf(buf, "<reference osisRef=\"%s-%s\">%s</reference>%s", element->LowerBound().getOSISRef(), element->UpperBound().getOSISRef(), frag, postJunk);
- }
- else {
- memmove(frag, startFrag, ((const char *)verses.GetElement(i)->userData - startFrag) + 1);
- frag[((const char *)verses.GetElement(i)->userData - startFrag) + 1] = 0;
- int j;
- for (j = strlen(frag)-1; j && (strchr(" {};,()[].", frag[j])); j--);
- if (frag[j+1])
- strcpy(postJunk, frag+j+1);
- frag[j+1]=0;
- startFrag += ((const char *)verses.GetElement(i)->userData - startFrag) + 1;
- sprintf(buf, "<reference osisRef=\"%s\">%s</reference>%s", VerseKey(*verses.GetElement(i)).getOSISRef(), frag, postJunk);
- }
- outRef+=buf;
+ memmove(frag, startFrag, ((const char *)element->userData - startFrag) + 1);
+ frag[((const char *)element->userData - startFrag) + 1] = 0;
+ int j;
+ for (j = strlen(frag)-1; j && (strchr(" {};,()[].", frag[j])); j--);
+ if (frag[j+1])
+ strcpy(postJunk, frag+j+1);
+ frag[j+1]=0;
+ startFrag += ((const char *)element->userData - startFrag) + 1;
+ buf = "<reference osisRef=\"";
+ buf += element->getOSISRefRangeText();
+ buf += "\">";
+ buf += frag;
+ buf += "</reference>";
+ buf += postJunk;
+
+ outRef += buf;
+
}
if (startFrag < (inRef + strlen(inRef)))
- outRef+=startFrag;
+ outRef += startFrag;
return outRef.c_str();
}
SWORD_NAMESPACE_END