Index: include/canon_synodal.h =================================================================== --- include/canon_synodal.h (revision 2571) +++ include/canon_synodal.h (working copy) @@ -285,7 +285,35 @@ 20, 29, 22, 11, 14, 17, 17, 13, 21, 11, 19, 17, 18, 20, 8, 21, 18, 24, 21, 15, 27, 21 }; +/* +"Lev.14.55:Lev.14.55-56" +"Ps.3.1:Ps.3.0" +"Ps.4.1:Ps.4.0" +"Ps.5.1:Ps.5.0" +"Ps.6.1:Ps.6.0" +"Ps.7.1:Ps.7.0" +"Ps.8.1:Ps.8.0" +"Ps.9.1:Ps.9.0" +"Ps.9.22:Ps.10.1" +"Ps.10.1:Ps.11.0-1" +"Ps.11.1:Ps.12.0" +*/ +unsigned char mappings_synodal[] = { + 3, 14, 55, 0, 14, 55, 56, + 23, 3, 1, 0, 3, 0, 0, + 23, 4, 1, 0, 4, 0, 0, + 23, 5, 1, 0, 5, 0, 0, + 23, 6, 1, 0, 6, 0, 0, + 23, 7, 1, 0, 7, 0, 0, + 23, 8, 1, 0, 8, 0, 0, + 23, 9, 1, 0, 9, 0, 0, + 23, 9, 22, 0, 10, 1, 0, + 23, 10, 1, 0, 11, 0, 1, + 23, 11, 1, 0, 12, 0, 0, + 0 +}; + SWORD_NAMESPACE_END Index: include/versemgr.h =================================================================== --- include/versemgr.h (revision 2571) +++ include/versemgr.h (working copy) @@ -65,7 +65,6 @@ int *versemax; }; - class SWDLLEXPORT VerseMgr : public SWCacher { @@ -141,11 +140,12 @@ int getBookNumberByOSISName(const char *bookName) const; const Book *getBook(int number) const; int getBookCount() const; - void loadFromSBook(const sbook *ot, const sbook *nt, int *chMax); + void loadFromSBook(const sbook *ot, const sbook *nt, int *chMax, const unsigned char *mappings=NULL); long getOffsetFromVerse(int book, int chapter, int verse) const; char getVerseFromOffset(long offset, int *book, int *chapter, int *verse) const; const int *getBMAX() const { return BMAX; }; long getNTStartOffset() const { return ntStartOffset; } + void translateVerse(const System *dstSys, const char **book, int *chapter, int *verse, int *verse_end) const; }; VerseMgr() { init(); } ~VerseMgr(); @@ -153,7 +153,7 @@ static void setSystemVerseMgr(VerseMgr *newVerseMgr); const StringList getVersificationSystems() const; const System *getVersificationSystem(const char *name) const; - void registerVersificationSystem(const char *name, const sbook *ot, const sbook *nt, int *chMax); + void registerVersificationSystem(const char *name, const sbook *ot, const sbook *nt, int *chMax, const unsigned char *mappings=NULL); void registerVersificationSystem(const char *name, const TreeKey *); }; Index: src/keys/versekey.cpp =================================================================== --- src/keys/versekey.cpp (revision 2571) +++ src/keys/versekey.cpp (working copy) @@ -119,20 +119,37 @@ */ 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()); - } + if (refSys == ikey.refSys) { + testament = ikey.Testament(); + book = ikey.Book(); + chapter = ikey.Chapter(); + verse = ikey.Verse(); + suffix = ikey.getSuffix(); + } + else { + // map verse between systems + // TODO if range is greater then chapter + // maybe negative and greater then chap-max numbers + if (refSys->getBookNumberByOSISName(ikey.getOSISBookName()) == -1) + // TODO set key to error or empty + return; + + const char* map_book = ikey.getOSISBookName(); + int map_chapter = ikey.Chapter(); + int map_verse = ikey.Verse(); + int map_range = map_verse; + + ikey.refSys->translateVerse(refSys, &map_book, &map_chapter, &map_verse, &map_range); + //printf("verse: %s.%i.%i-%i\n",map_book,map_chapter,map_verse,map_range); + + testament = ikey.Testament(); + book = refSys->getBookNumberByOSISName(map_book); + chapter = map_chapter; + // TODO howto position on headings? + if (map_verse < 1) map_verse = 1; + verse = map_verse; + suffix = ikey.getSuffix(); + } } Index: src/mgr/versemgr.cpp =================================================================== --- src/mgr/versemgr.cpp (revision 2571) +++ src/mgr/versemgr.cpp (working copy) @@ -60,7 +60,7 @@ systemVerseMgr->registerVersificationSystem("KJVA", otbooks_kjva, ntbooks, vm_kjva); systemVerseMgr->registerVersificationSystem("NRSV", otbooks, ntbooks, vm_nrsv); systemVerseMgr->registerVersificationSystem("NRSVA", otbooks_nrsva, ntbooks, vm_nrsva); - systemVerseMgr->registerVersificationSystem("Synodal", otbooks_synodal, ntbooks_synodal, vm_synodal); + systemVerseMgr->registerVersificationSystem("Synodal", otbooks_synodal, ntbooks_synodal, vm_synodal, mappings_synodal); systemVerseMgr->registerVersificationSystem("Vulg", otbooks_vulg, ntbooks_vulg, vm_vulg); systemVerseMgr->registerVersificationSystem("German", otbooks_german, ntbooks, vm_german); systemVerseMgr->registerVersificationSystem("Luther", otbooks_luther, ntbooks_luther, vm_luther); @@ -98,6 +98,14 @@ /** Array[chapmax] of maximum verses in chapters */ vector verseMax; vector offsetPrecomputed; + /** General mapping rule is that first verse of every chapter corresponds first + verse of another chapter in default intermediate canon(kjva), so mapping data + contains expections. Intermediate canon could not contain corresponding data. + + pointers on uchar[7]: 1 value - book id 1-based, ot+nt, 2-4 map to, 5-7 map + from (chap,verse from, verse to if greater then "verse from") + */ + vector mappings; Private() { verseMax.clear(); @@ -168,7 +176,7 @@ } -void VerseMgr::System::loadFromSBook(const sbook *ot, const sbook *nt, int *chMax) { +void VerseMgr::System::loadFromSBook(const sbook *ot, const sbook *nt, int *chMax, const unsigned char *mappings) { int chap = 0; int book = 0; long offset = 0; // module heading @@ -208,6 +216,13 @@ BMAX[1] = book; // TODO: build offset speed array + + // parse mappings + if (mappings != NULL) { + for (int i=0; mappings[i] != 0; i += 7) { + p->books[mappings[i]-1].p->mappings.push_back(mappings+i); + } + } } @@ -360,10 +375,10 @@ } -void VerseMgr::registerVersificationSystem(const char *name, const sbook *ot, const sbook *nt, int *chMax) { +void VerseMgr::registerVersificationSystem(const char *name, const sbook *ot, const sbook *nt, int *chMax, const unsigned char *mappings) { p->systems[name] = name; System &s = p->systems[name]; - s.loadFromSBook(ot, nt, chMax); + s.loadFromSBook(ot, nt, chMax, mappings); } @@ -379,5 +394,84 @@ return retVal; } +void VerseMgr::System::translateVerse(const System *dstSys, const char **book, int *chapter, int *verse, int *verse_end) const { + //printf("translate verse from %s to %s: %s.%i.%i-%i\n",getName(), dstSys->getName(), *book, *chapter, *verse, *verse_end); + if (this == dstSys) + return; + if (!strcmp(getName(),"KJVA") || !strcmp(getName(),"KJV")) { + if (!strcmp(dstSys->getName(),"KJVA") || !strcmp(dstSys->getName(),"KJV")) + return; + // reversed mapping + //printf("Perform reversed mapping.\n"); + const Book *b = dstSys->getBook(dstSys->getBookNumberByOSISName(*book)-1); + const unsigned char *appropriate = NULL; + for (int i=b->p->mappings.size()-1; i>=0; --i) { + if (b->p->mappings[i][4] == *chapter && b->p->mappings[i][5] <= *verse) { + const unsigned char *m = b->p->mappings[i]; + //printf("found mapping %i %i %i %i %i %i\n",m[1],m[2],m[3],m[4],m[5],m[6]); + if (m[6] >= *verse && m[5] <= *verse) { + // inside of any mapping range + (*chapter) = m[1]; + (*verse) = m[2]; + (*verse_end) = m[3]; + return; + } + if (appropriate == NULL) + appropriate = b->p->mappings[i]; + } + } + if (appropriate != NULL) { + const unsigned char *m = appropriate; + //printf("set appropriate: %i %i %i %i %i %i\n",m[1],m[2],m[3],m[4],m[5],m[6]); + (*chapter) = m[1]; + // shift verse + const int d = (m[3]-m[2]>0?m[3]:m[2])-(m[6]-m[5]>0?m[6]:m[5]); + if ((*verse) < (*verse_end)) + (*verse_end) += d; + else + (*verse_end) = (*verse) + d; + (*verse) += d; + return; + } + //printf("There is no mapping.\n"); + } + else if (strcmp(dstSys->getName(),"KJVA") && strcmp(dstSys->getName(),"KJV")) { + const System *kjva = getSystemVerseMgr()->getVersificationSystem("KJVA"); + translateVerse(kjva, book, chapter, verse, verse_end); + kjva->translateVerse(dstSys, book, chapter, verse, verse_end); + } + else { + // forward mapping + //printf("Perform forward mapping.\n"); + const Book *b = getBook(getBookNumberByOSISName(*book)-1); + for (int i=b->p->mappings.size()-1; i>=0; --i) { + if (b->p->mappings[i][1] < *chapter) { + //printf("There is no mapping for this chapter.\n"); + return; + } + if (b->p->mappings[i][1] == *chapter && b->p->mappings[i][2] <= *verse) { + const unsigned char *m = b->p->mappings[i]; + //printf("found mapping %i %i %i %i %i %i\n",m[1],m[2],m[3],m[4],m[5],m[6]); + if (m[3] >= *verse && m[2] <= *verse) { + (*chapter) = m[4]; + (*verse) = m[5]; + (*verse_end) = m[6]; + } + else { + (*chapter) = m[4]; + // shift verse + const int d = (m[6]-m[5]>0?m[6]:m[5])-(m[3]-m[2]>0?m[3]:m[2]); + if ((*verse) < (*verse_end)) + (*verse_end) += d; + else + (*verse_end) = (*verse) + d; + (*verse) += d; + } + return; + } + } + //printf("No mapping.\n"); + } +} SWORD_NAMESPACE_END