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.cpp286
1 files changed, 202 insertions, 84 deletions
diff --git a/src/keys/versekey.cpp b/src/keys/versekey.cpp
index 1d5adcb..b2f78e3 100644
--- a/src/keys/versekey.cpp
+++ b/src/keys/versekey.cpp
@@ -4,7 +4,6 @@
#include <swmacs.h>
#include <utilfuns.h>
-#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
@@ -20,10 +19,9 @@
#include <swlog.h>
#include <versekey.h>
#include <localemgr.h>
-extern "C" {
#include <roman.h>
-}
+SWORD_NAMESPACE_START
static const char *classes[] = {"VerseKey", "SWKey", "SWObject", 0};
SWClass VerseKey::classdef(classes);
@@ -55,6 +53,7 @@ void VerseKey::init() {
headings = 0; // default display headings option is false
upperBound = 0;
lowerBound = 0;
+ boundSet = false;
testament = 0;
book = 0;
chapter = 0;
@@ -94,7 +93,7 @@ VerseKey::VerseKey(const char *ikey) : SWKey(ikey)
}
-VerseKey::VerseKey(VerseKey const &k) : SWKey(k.keytext)
+VerseKey::VerseKey(VerseKey const &k) : SWKey(k)
{
init();
autonorm = k.autonorm;
@@ -103,8 +102,10 @@ VerseKey::VerseKey(VerseKey const &k) : SWKey(k.keytext)
book = k.Book();
chapter = k.Chapter();
verse = k.Verse();
- LowerBound(k.LowerBound());
- UpperBound(k.UpperBound());
+ if (k.isBoundSet()) {
+ LowerBound(k.LowerBound());
+ UpperBound(k.UpperBound());
+ }
}
@@ -169,8 +170,12 @@ void VerseKey::setLocale(const char *name) {
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;
@@ -181,7 +186,7 @@ void VerseKey::setBooks(const char *iBMAX, struct sbook **ibooks) {
void VerseKey::setBookAbbrevs(const struct abbrev *bookAbbrevs, unsigned int size) {
abbrevs = bookAbbrevs;
if (!size) {
- for (abbrevsCnt = 1; *abbrevs[abbrevsCnt].ab; abbrevsCnt++) {
+ 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);
@@ -193,7 +198,7 @@ void VerseKey::setBookAbbrevs(const struct abbrev *bookAbbrevs, unsigned int siz
for (int i = 0; i < BMAX[t]; i++) {
int bn = getBookAbbrev(books[t][i].name);
if ((bn-1)%39 != i) {
- SWLog::systemlog->LogError("Book: %s does not have a matching toupper abbrevs entry! book number returned was: %d", books[t][i].name, bn);
+ SWLog::systemlog->LogError("Book: %s does not have a matching toupper abbrevs entry! book number returned was: %d", books[t][i].name, bn);
}
}
}
@@ -232,36 +237,41 @@ char VerseKey::parse()
{
- testament = 1;
- book = 1;
+ testament = 2;
+ book = BMAX[1];
chapter = 1;
verse = 1;
+ int booklen = 0;
- error = 0;
+ int error = 0;
if (keytext) {
ListKey tmpListKey = VerseKey::ParseVerseList(keytext);
if (tmpListKey.Count()) {
SWKey::setText((const char *)tmpListKey);
- for (testament = 1; testament < 3; testament++) {
- for (book = 1; book <= BMAX[testament-1]; book++) {
- if (!strncmp(keytext, books[testament-1][book-1].name, strlen(books[testament-1][book-1].name)))
- break;
+ 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 (book <= BMAX[testament-1])
- break;
}
- if (testament < 3) {
- sscanf(&keytext[strlen(books[testament-1][book-1].name)], "%d:%d", &chapter, &verse);
+ if (booklen) {
+ sscanf(&keytext[booklen], "%d:%d", &chapter, &verse);
}
else error = 1;
- }
+ } else error = 1;
}
Normalize(1);
freshtext();
- return error;
+ return (this->error) ? this->error : (this->error = error);
}
@@ -306,35 +316,39 @@ void VerseKey::freshtext() const
int VerseKey::getBookAbbrev(const char *iabbr)
{
- int loop, diff, abLen, min, max, target, retVal = -1;
-
- char *abbr = 0;
-
- stdstr(&abbr, iabbr);
- strstrip(abbr);
- abLen = strlen(abbr);
- for (loop = 0; loop < abLen; loop++)
- abbr[loop] = SW_toupper(abbr[loop]);
-
- if (abLen) {
- min = 0;
-// max = abbrevsCnt - 1;
- max = abbrevsCnt;
- while(1) {
- target = min + ((max - min) / 2);
- diff = strncmp(abbr, abbrevs[target].ab, abLen);
- if ((!diff)||(target >= max)||(target <= min))
- break;
- if (diff > 0)
- min = target;
- else max = target;
- }
- for (; target > 0; target--) {
- if (strncmp(abbr, abbrevs[target-1].ab, abLen))
- break;
+ int loop, diff, abLen, min, max, target, retVal = -1;
+
+ char *abbr = 0;
+
+ for (int i = 0; i < 2; i++) {
+ stdstr(&abbr, iabbr);
+ strstrip(abbr);
+ if (!i)
+ toupperstr(abbr);
+ abLen = strlen(abbr);
+
+ if (abLen) {
+ min = 0;
+// max = abbrevsCnt - 1;
+ max = abbrevsCnt;
+ while(1) {
+ target = min + ((max - min) / 2);
+ diff = strncmp(abbr, abbrevs[target].ab, abLen);
+ if ((!diff)||(target >= max)||(target <= min))
+ break;
+ if (diff > 0)
+ min = target;
+ else max = target;
+ }
+ for (; target > 0; target--) {
+ if (strncmp(abbr, abbrevs[target-1].ab, abLen))
+ break;
+ }
+
+ retVal = (!diff) ? abbrevs[target].book : -1;
}
-
- retVal = (!diff) ? abbrevs[target].book : -1;
+ if (retVal > 0)
+ break;
}
delete [] abbr;
return retVal;
@@ -359,8 +373,8 @@ int VerseKey::getBookAbbrev(const char *iabbr)
ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool expandRange) {
SWKey textkey;
- char book[255];
- char number[255];
+ char book[2048];
+ char number[2048];
int tobook = 0;
int tonumber = 0;
int chap = -1, verse = -1;
@@ -372,13 +386,17 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
char comma = 0;
char dash = 0;
const char *orig = buf;
+ int q;
ListKey tmpListKey;
ListKey internalListKey;
SWKey tmpDefaultKey = defaultKey;
char lastPartial = 0;
+ bool inTerm = true;
+ int notAllDigits;
curkey.AutoNormalize(0);
tmpListKey << tmpDefaultKey;
+ tmpListKey.GetElement()->userData = (void *)buf;
while (*buf) {
switch (*buf) {
@@ -390,6 +408,21 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
*number = 0;
break;
+ case ' ':
+ inTerm = true;
+ while (true) {
+ if ((!*number) || (chap < 0))
+ break;
+ for (q = 1; ((buf[q]) && (buf[q] != ' ')); q++);
+ if (buf[q] == ':')
+ break;
+ inTerm = false;
+ break;
+ }
+ if (inTerm) {
+ book[tobook++] = ' ';
+ break;
+ }
case '-':
case ',': // on number new verse
case ';': // on number new chapter
@@ -421,26 +454,29 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
break;
}
- for (loop = strlen(book) - 1; loop+1; loop--) {
- if (book[loop] == ' ') {
+ for (loop = strlen(book) - 1; loop+1; loop--) {
+ if (book[loop] == ' ') {
if (isroman(&book[loop+1])) {
- if (verse == -1) {
- verse = chap;
+ if (verse == -1) {
+ verse = chap;
chap = from_rom(&book[loop+1]);
book[loop] = 0;
- }
- }
- break;
- }
- }
-
- if ((!stricmp(book, "V")) || (!stricmp(book, "VER"))) { // Verse abbrev
- if (verse == -1) {
- verse = chap;
- chap = VerseKey(tmpListKey).Chapter();
- *book = 0;
- }
- }
+ }
+ }
+ break;
+ }
+ }
+
+ if ((!stricmp(book, "V")) || (!stricmp(book, "VER"))) { // Verse abbrev
+ if (verse == -1) {
+ verse = chap;
+ chap = VerseKey(tmpListKey).Chapter();
+ *book = 0;
+ }
+ }
+ if ((!stricmp(book, "ch")) || (!stricmp(book, "chap"))) { // Verse abbrev
+ strcpy(book, VerseKey(tmpListKey).getBookName());
+ }
bookno = getBookAbbrev(book);
}
if (((bookno > -1) || (!*book)) && ((*book) || (chap >= 0) || (verse >= 0))) {
@@ -485,6 +521,7 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
newElement.LowerBound(curkey);
newElement.setPosition(TOP);
tmpListKey << newElement;
+ tmpListKey.GetElement()->userData = (void *)buf;
}
else {
if (!dash) { // if last separator was not a dash just add
@@ -498,8 +535,12 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
newElement.UpperBound(curkey);
newElement = TOP;
tmpListKey << newElement;
+ tmpListKey.GetElement()->userData = (void *)buf;
+ }
+ else {
+ tmpListKey << (const SWKey &)(const SWKey)(const char *)curkey;
+ tmpListKey.GetElement()->userData = (void *)buf;
}
- else tmpListKey << (const SWKey &)(const SWKey)(const char *)curkey;
}
else if (expandRange) {
VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.GetElement());
@@ -510,6 +551,7 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
curkey = MAXVERSE;
newElement->UpperBound(curkey);
*newElement = TOP;
+ tmpListKey.GetElement()->userData = (void *)buf;
}
}
}
@@ -527,11 +569,26 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
break;
case 10: // ignore these
case 13:
+ case '[':
+ case ']':
+ case '(':
+ case ')':
break;
case '.':
if (buf > orig) // ignore (break) if preceeding char is not a digit
- if (!isdigit(*(buf-1)))
+ for (notAllDigits = tobook; notAllDigits; notAllDigits--) {
+ if ((!isdigit(book[notAllDigits-1])) && (!strchr(" .", book[notAllDigits-1])))
+ break;
+ }
+ if (!notAllDigits)
break;
+
+ number[tonumber] = 0;
+ tonumber = 0;
+ if (*number)
+ chap = atoi(number);
+ *number = 0;
+ break;
default:
if (isdigit(*buf)) {
@@ -550,7 +607,7 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
}
}
if (chap == -1)
- book[tobook++] = SW_toupper(*buf);
+ book[tobook++] = *buf;
}
buf++;
}
@@ -582,15 +639,15 @@ 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])) {
- if (verse == -1) {
- verse = chap;
- chap = from_rom(&book[loop+1]);
- book[loop] = 0;
- }
- }
- break;
+ if (book[loop] == ' ') {
+ if (isroman(&book[loop+1])) {
+ if (verse == -1) {
+ verse = chap;
+ chap = from_rom(&book[loop+1]);
+ book[loop] = 0;
+ }
+ }
+ break;
}
}
@@ -602,6 +659,9 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
}
}
+ if ((!stricmp(book, "ch")) || (!stricmp(book, "chap"))) { // Verse abbrev
+ strcpy(book, VerseKey(tmpListKey).getBookName());
+ }
bookno = getBookAbbrev(book);
}
if (((bookno > -1) || (!*book)) && ((*book) || (chap >= 0) || (verse >= 0))) {
@@ -646,6 +706,7 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
newElement.LowerBound(curkey);
newElement = TOP;
tmpListKey << newElement;
+ tmpListKey.GetElement()->userData = (void *)buf;
}
else {
if (!dash) { // if last separator was not a dash just add
@@ -659,8 +720,12 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
newElement.UpperBound(curkey);
newElement = TOP;
tmpListKey << newElement;
+ tmpListKey.GetElement()->userData = (void *)buf;
+ }
+ else {
+ tmpListKey << (const SWKey &)(const SWKey)(const char *)curkey;
+ tmpListKey.GetElement()->userData = (void *)buf;
}
- else tmpListKey << (const SWKey &)(const SWKey)(const char *)curkey;
}
else if (expandRange) {
VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.GetElement());
@@ -671,6 +736,7 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e
curkey = MAXVERSE;
newElement->UpperBound(curkey);
*newElement = TOP;
+ tmpListKey.GetElement()->userData = (void *)buf;
}
}
}
@@ -696,7 +762,8 @@ VerseKey &VerseKey::LowerBound(const char *lb)
(*lowerBound) = lb;
lowerBound->Normalize();
-
+ lowerBound->setLocale( this->getLocale() );
+ boundSet = true;
return (*lowerBound);
}
@@ -715,6 +782,7 @@ VerseKey &VerseKey::UpperBound(const char *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);
@@ -736,7 +804,7 @@ VerseKey &VerseKey::UpperBound(const char *ub)
// -- end kludge
-
+ boundSet = true;
return (*upperBound);
}
@@ -799,6 +867,7 @@ void VerseKey::initBounds() const
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;
}
@@ -1403,3 +1472,52 @@ int VerseKey::_compare(const VerseKey &ivkey)
keyval1 = (keyval1) ? ((keyval1 > 0) ? 1 : -1) /*keyval1/labs(keyval1)*/:0; // -1 | 0 | 1
return keyval1;
}
+
+
+const char *VerseKey::getOSISRef() const {
+ static char buf[5][254];
+ static char loop = 0;
+
+ if (loop > 4)
+ loop = 0;
+
+ static char *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"};
+ static char *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"};
+ static char **osisbooks[] = { osisotbooks, osisntbooks };
+ if (Verse())
+ sprintf(buf[loop], "%s.%d.%d", osisbooks[Testament()-1][Book()-1], (int)Chapter(), (int)Verse());
+ else if (Chapter())
+ sprintf(buf[loop], "%s.%d", osisbooks[Testament()-1][Book()-1], (int)Chapter());
+ else if (Book())
+ sprintf(buf[loop], "%s", osisbooks[Testament()-1][Book()-1]);
+ else sprintf(buf[loop], "");
+ return buf[loop++];
+}
+
+
+/******************************************************************************
+ * 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);
+ }
+ else stdstr(&rangeText, getText());
+ return rangeText;
+}
+
+SWORD_NAMESPACE_END