From 1d0ff54794b5edea7cdf1d2d66710a0fa885bcc5 Mon Sep 17 00:00:00 2001 From: Teus Benschop Date: Sun, 28 Oct 2018 11:51:26 +0100 Subject: New upstream version 1.8.1 --- src/keys/treekeyidx.cpp | 75 +-- src/keys/versekey.cpp | 111 ++-- src/keys/versetreekey.cpp | 4 +- src/mgr/Makefile.am | 3 + src/mgr/curlftpt.cpp | 8 +- src/mgr/curlhttpt.cpp | 14 +- src/mgr/encfiltmgr.cpp | 21 +- src/mgr/filemgr.cpp | 55 +- src/mgr/ftplibftpt.cpp | 10 +- src/mgr/installmgr.cpp | 60 +- src/mgr/localemgr.cpp | 6 +- src/mgr/markupfiltmgr.cpp | 16 +- src/mgr/remotetrans.cpp | 77 ++- src/mgr/rtranspgdrive.cpp | 174 ++++++ src/mgr/stringmgr.cpp | 4 +- src/mgr/swconfig.cpp | 77 ++- src/mgr/swlocale.cpp | 24 +- src/mgr/swmgr.cpp | 380 ++++++++----- src/mgr/versificationmgr.cpp | 191 ++++++- src/modules/comments/Makefile.am | 1 + src/modules/comments/rawcom4/Makefile | 10 +- src/modules/comments/rawcom4/rawcom4.cpp | 4 +- src/modules/comments/zcom/zcom.cpp | 2 +- src/modules/comments/zcom4/Makefile | 5 + src/modules/comments/zcom4/Makefile.am | 2 + src/modules/comments/zcom4/zcom4.cpp | 220 ++++++++ src/modules/common/Makefile.am | 18 +- src/modules/common/bz2comprs.cpp | 57 +- src/modules/common/entriesblk.cpp | 6 +- src/modules/common/rawstr.cpp | 32 +- src/modules/common/rawstr4.cpp | 36 +- src/modules/common/rawverse.cpp | 4 +- src/modules/common/rawverse4.cpp | 6 +- src/modules/common/swcomprs.cpp | 3 +- src/modules/common/xzcomprs.cpp | 130 +++-- src/modules/common/zipcomprs.cpp | 34 +- src/modules/common/zstr.cpp | 42 +- src/modules/common/zverse.cpp | 19 +- src/modules/common/zverse4.cpp | 516 +++++++++++++++++ src/modules/filters/Makefile.am | 5 + src/modules/filters/gbfheadings.cpp | 8 +- src/modules/filters/gbfhtmlhref.cpp | 12 +- src/modules/filters/gbflatex.cpp | 198 +++++++ src/modules/filters/gbfmorph.cpp | 8 +- src/modules/filters/gbfplain.cpp | 6 +- src/modules/filters/gbfredletterwords.cpp | 7 +- src/modules/filters/gbfrtf.cpp | 6 +- src/modules/filters/gbfstrongs.cpp | 16 +- src/modules/filters/gbfthml.cpp | 13 +- src/modules/filters/gbfwordjs.cpp | 18 +- src/modules/filters/gbfxhtml.cpp | 12 +- src/modules/filters/greeklexattribs.cpp | 4 +- src/modules/filters/osisheadings.cpp | 11 +- src/modules/filters/osishtmlhref.cpp | 31 +- src/modules/filters/osislatex.cpp | 766 ++++++++++++++++++++++++++ src/modules/filters/osislemma.cpp | 12 +- src/modules/filters/osismorph.cpp | 7 +- src/modules/filters/osismorphsegmentation.cpp | 2 +- src/modules/filters/osisosis.cpp | 53 +- src/modules/filters/osisplain.cpp | 56 +- src/modules/filters/osisreferencelinks.cpp | 2 +- src/modules/filters/osisrtf.cpp | 21 +- src/modules/filters/osisscripref.cpp | 2 +- src/modules/filters/osisstrongs.cpp | 55 +- src/modules/filters/osiswebif.cpp | 14 +- src/modules/filters/osiswordjs.cpp | 11 +- src/modules/filters/osisxhtml.cpp | 238 +++++--- src/modules/filters/rtfhtml.cpp | 4 +- src/modules/filters/scsuutf8.cpp | 381 +++++++------ src/modules/filters/swbasicfilter.cpp | 20 +- src/modules/filters/teihtmlhref.cpp | 56 +- src/modules/filters/teilatex.cpp | 326 +++++++++++ src/modules/filters/teirtf.cpp | 30 +- src/modules/filters/teixhtml.cpp | 149 +++-- src/modules/filters/thmlgbf.cpp | 6 +- src/modules/filters/thmlheadings.cpp | 2 +- src/modules/filters/thmlhtml.cpp | 10 +- src/modules/filters/thmlhtmlhref.cpp | 39 +- src/modules/filters/thmllatex.cpp | 396 +++++++++++++ src/modules/filters/thmlplain.cpp | 10 +- src/modules/filters/thmlrtf.cpp | 37 +- src/modules/filters/thmlscripref.cpp | 2 +- src/modules/filters/thmlstrongs.cpp | 16 +- src/modules/filters/thmlwordjs.cpp | 18 +- src/modules/filters/thmlxhtml.cpp | 41 +- src/modules/filters/unicodertf.cpp | 2 +- src/modules/filters/utf16utf8.cpp | 2 +- src/modules/filters/utf8arabicpoints.cpp | 4 +- src/modules/filters/utf8greekaccents.cpp | 521 ++++++++++-------- src/modules/filters/utf8html.cpp | 2 +- src/modules/filters/utf8latin1.cpp | 2 +- src/modules/filters/utf8nfc.cpp | 2 +- src/modules/filters/utf8nfkd.cpp | 2 +- src/modules/filters/utf8scsu.cpp | 61 ++ src/modules/filters/utf8utf16.cpp | 2 +- src/modules/genbook/rawgenbook/rawgenbook.cpp | 6 +- src/modules/lexdict/rawld/rawld.cpp | 31 +- src/modules/lexdict/rawld4/rawld4.cpp | 35 +- src/modules/lexdict/swld.cpp | 6 +- src/modules/lexdict/zld/zld.cpp | 33 +- src/modules/swmodule.cpp | 218 +++++++- src/modules/texts/Makefile.am | 1 + src/modules/texts/rawtext4/Makefile | 10 +- src/modules/texts/rawtext4/rawtext4.cpp | 5 +- src/modules/texts/ztext4/Makefile | 5 + src/modules/texts/ztext4/Makefile.am | 2 + src/modules/texts/ztext4/ztext4.cpp | 223 ++++++++ src/utilfuns/ftplib.c | 20 +- src/utilfuns/roman.cpp | 4 +- src/utilfuns/swbuf.cpp | 63 +-- src/utilfuns/url.cpp | 8 +- src/utilfuns/utilstr.cpp | 193 +------ src/utilfuns/utilxml.cpp | 24 +- src/utilfuns/zlib/gzlib.c | 8 + src/utilfuns/zlib/gzread.c | 9 +- src/utilfuns/zlib/gzwrite.c | 11 +- src/utilfuns/zlib/untgz.c | 2 +- 117 files changed, 5396 insertions(+), 1715 deletions(-) create mode 100644 src/mgr/rtranspgdrive.cpp create mode 100644 src/modules/comments/zcom4/Makefile create mode 100644 src/modules/comments/zcom4/Makefile.am create mode 100644 src/modules/comments/zcom4/zcom4.cpp create mode 100644 src/modules/common/zverse4.cpp create mode 100644 src/modules/filters/gbflatex.cpp create mode 100644 src/modules/filters/osislatex.cpp create mode 100644 src/modules/filters/teilatex.cpp create mode 100644 src/modules/filters/thmllatex.cpp create mode 100644 src/modules/filters/utf8scsu.cpp create mode 100644 src/modules/texts/ztext4/Makefile create mode 100644 src/modules/texts/ztext4/Makefile.am create mode 100644 src/modules/texts/ztext4/ztext4.cpp (limited to 'src') diff --git a/src/keys/treekeyidx.cpp b/src/keys/treekeyidx.cpp index 5164277..5f245de 100644 --- a/src/keys/treekeyidx.cpp +++ b/src/keys/treekeyidx.cpp @@ -2,7 +2,7 @@ * * treekeyidx.cpp - * - * $Id: treekeyidx.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: treekeyidx.cpp 3524 2017-11-07 03:08:49Z scribe $ * * Copyright 2002-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -33,6 +33,7 @@ SWORD_NAMESPACE_START + static const char *classes[] = {"TreeKeyIdx", "TreeKey", "SWKey", "SWObject", 0}; SWClass TreeKeyIdx::classdef(classes); @@ -61,8 +62,10 @@ TreeKeyIdx::TreeKeyIdx(const char *idxPath, int fileMode) : currentNode() { buf.setFormatted("%s.dat", path); datfd = FileMgr::getSystemFileMgr()->open(buf, fileMode, true); - if (datfd <= 0) { - SWLog::getSystemLog()->logError("%d", errno); + if (!datfd || datfd->getFd() < 0) { + // couldn't find datafile but this might be fine if we're + // merely instantiating a remote InstallMgr SWMgr + SWLog::getSystemLog()->logDebug("Couldn't open file: %s. errno: %d", buf.c_str(), errno); error = errno; } else { @@ -106,7 +109,7 @@ void TreeKeyIdx::setUserData(const char *userData, int size) { delete currentNode.userData; if (!size) - size = strlen(userData) + 1; + size = (int)strlen(userData) + 1; currentNode.userData = new char [ size ]; memcpy(currentNode.userData, userData, size); @@ -204,7 +207,7 @@ void TreeKeyIdx::append() { while (lastSib.next > -1) { getTreeNodeFromIdxOffset(lastSib.next, &lastSib); } - __u32 idxOffset = idxfd->seek(0, SEEK_END); + __u32 idxOffset = (__u32)idxfd->seek(0, SEEK_END); lastSib.next = idxOffset; saveTreeNodeOffsets(&lastSib); __u32 parent = currentNode.parent; @@ -221,7 +224,7 @@ void TreeKeyIdx::appendChild() { append(); } else { - __u32 idxOffset = idxfd->seek(0, SEEK_END); + __u32 idxOffset = (__u32)idxfd->seek(0, SEEK_END); currentNode.firstChild = idxOffset; saveTreeNodeOffsets(¤tNode); __u32 parent = currentNode.offset; @@ -259,14 +262,15 @@ void TreeKeyIdx::remove() { getTreeNodeFromIdxOffset(currentNode.parent, &iterator); getTreeNodeFromIdxOffset(iterator.firstChild, &iterator); if (iterator.offset != target) { - while ((iterator.next != target) && (iterator.next > -1)) + while ((iterator.next != target) && (iterator.next > -1)) { getTreeNodeFromIdxOffset(iterator.next, &iterator); - if (iterator.next > -1) { - TreeNode prev; - getTreeNodeFromIdxOffset(iterator.offset, &prev); - prev.next = node.next; - saveTreeNodeOffsets(&prev); - getTreeNodeFromIdxOffset(prev.offset, ¤tNode); + } + if (iterator.next > -1) { + TreeNode prev; + getTreeNodeFromIdxOffset(iterator.offset, &prev); + prev.next = node.next; + saveTreeNodeOffsets(&prev); + getTreeNodeFromIdxOffset(prev.offset, ¤tNode); } } } @@ -304,7 +308,6 @@ signed char TreeKeyIdx::create(const char *ipath) { fd2 = FileMgr::getSystemFileMgr()->open(buf, FileMgr::CREAT|FileMgr::WRONLY, FileMgr::IREAD|FileMgr::IWRITE); fd2->getFd(); FileMgr::getSystemFileMgr()->close(fd2); - TreeKeyIdx newTree(path); TreeKeyIdx::TreeNode root; stdstr(&(root.name), ""); @@ -331,7 +334,7 @@ void TreeKeyIdx::getTreeNodeFromDatOffset(long ioffset, TreeNode *node) const { __s32 tmp; __u16 tmp2; - if (datfd > 0) { + if (datfd && datfd->getFd() >= 0) { datfd->seek(ioffset, SEEK_SET); @@ -384,22 +387,20 @@ char TreeKeyIdx::getTreeNodeFromIdxOffset(long ioffset, TreeNode *node) const { error = 77; // out of bounds but still position to 0; } - node->offset = ioffset; - if (idxfd > 0) { - if (idxfd->getFd() > 0) { - idxfd->seek(ioffset, SEEK_SET); + node->offset = (__s32)ioffset; + if (idxfd && idxfd->getFd() >= 0) { + idxfd->seek(ioffset, SEEK_SET); + if (idxfd->read(&offset, 4) == 4) { + offset = swordtoarch32(offset); + error = (error == 77) ? KEYERR_OUTOFBOUNDS : 0; + getTreeNodeFromDatOffset(offset, node); + } + else { + idxfd->seek(-4, SEEK_END); if (idxfd->read(&offset, 4) == 4) { offset = swordtoarch32(offset); - error = (error == 77) ? KEYERR_OUTOFBOUNDS : 0; getTreeNodeFromDatOffset(offset, node); } - else { - idxfd->seek(-4, SEEK_END); - if (idxfd->read(&offset, 4) == 4) { - offset = swordtoarch32(offset); - getTreeNodeFromDatOffset(offset, node); - } - } } } return error; @@ -422,11 +423,11 @@ void TreeKeyIdx::saveTreeNodeOffsets(TreeNode *node) { long datOffset = 0; __s32 tmp; - if (idxfd > 0) { + if (idxfd && idxfd->getFd() >= 0) { idxfd->seek(node->offset, SEEK_SET); if (idxfd->read(&tmp, 4) != 4) { datOffset = datfd->seek(0, SEEK_END); - tmp = archtosword32(datOffset); + tmp = (__s32)archtosword32(datOffset); idxfd->write(&tmp, 4); } else { @@ -434,13 +435,13 @@ void TreeKeyIdx::saveTreeNodeOffsets(TreeNode *node) { datfd->seek(datOffset, SEEK_SET); } - tmp = archtosword32(node->parent); + tmp = (__s32)archtosword32(node->parent); datfd->write(&tmp, 4); - tmp = archtosword32(node->next); + tmp = (__s32)archtosword32(node->next); datfd->write(&tmp, 4); - tmp = archtosword32(node->firstChild); + tmp = (__s32)archtosword32(node->firstChild); datfd->write(&tmp, 4); } } @@ -488,11 +489,11 @@ void TreeKeyIdx::copyFrom(const TreeKeyIdx &ikey) { void TreeKeyIdx::saveTreeNode(TreeNode *node) { long datOffset = 0; __s32 tmp; - if (idxfd > 0) { + if (idxfd && idxfd->getFd() >= 0) { idxfd->seek(node->offset, SEEK_SET); datOffset = datfd->seek(0, SEEK_END); - tmp = archtosword32(datOffset); + tmp = (__s32)archtosword32(datOffset); idxfd->write(&tmp, 4); saveTreeNodeOffsets(node); @@ -567,7 +568,7 @@ void TreeKeyIdx::setPosition(SW_POSITION p) { int TreeKeyIdx::_compare (const TreeKeyIdx & ikey) { - return (getOffset() - ikey.getOffset()); + return (int)(getOffset() - ikey.getOffset()); } @@ -587,7 +588,7 @@ void TreeKeyIdx::decrement(int steps) { void TreeKeyIdx::increment(int steps) { error = getTreeNodeFromIdxOffset(currentNode.offset + (4*steps), ¤tNode); if (error) { -// SWLog::getSystemLog()->logError("error: %d", error); + SWLog::getSystemLog(); // strange fix for android // ->logError("error: %d", error); } positionChanged(); @@ -611,7 +612,6 @@ void TreeKeyIdx::increment(int steps) { } - const char *TreeKeyIdx::getText() const { TreeNode parent; static SWBuf fullPath; @@ -655,6 +655,7 @@ void TreeKeyIdx::TreeNode::clear() { } + TreeKeyIdx::TreeNode::~TreeNode() { if (name) delete [] name; diff --git a/src/keys/versekey.cpp b/src/keys/versekey.cpp index 25af540..84aa6ff 100644 --- a/src/keys/versekey.cpp +++ b/src/keys/versekey.cpp @@ -3,7 +3,7 @@ * versekey.cpp - code for class 'VerseKey'- a standard Biblical * verse key * - * $Id: versekey.cpp 3281 2014-12-03 06:07:22Z greg.hellings $ + * $Id: versekey.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 1998-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -128,18 +128,55 @@ void VerseKey::setFromOther(const VerseKey &ikey) { chapter = ikey.getChapter(); verse = ikey.getVerse(); suffix = ikey.getSuffix(); - } - // TODO: versification mapping - // 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 - // Konstantin Maslyuk has submitted a patch) - // Asked Konstantin to try his patch out with his favorite - // SWORD frontend and report back how it goes. Need to follow up - else { - // For now, this is the best we can do - setText(ikey.getText()); - } + } + else { + // map verse between systems + const char* map_book = ikey.getOSISBookName(); + int map_chapter = ikey.getChapter(); + int map_verse = ikey.getVerse(); + 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); + + book = refSys->getBookNumberByOSISName(map_book); + + // check existence + if (book == -1) { + book = 1; + error = KEYERR_OUTOFBOUNDS; + } + else if (refSys->getBook(book-1)->getChapterMax() < map_chapter) { + map_chapter = refSys->getBook(book-1)->getChapterMax(); + map_verse = refSys->getBook(book-1)->getVerseMax(map_chapter); + error = KEYERR_OUTOFBOUNDS; + } + else if (map_chapter > 0 && refSys->getBook(book-1)->getVerseMax(map_chapter) < map_verse) { + map_verse = refSys->getBook(book-1)->getVerseMax(map_chapter); + error = KEYERR_OUTOFBOUNDS; + } + + // set values + if (book > BMAX[0]) + book -= BMAX[0], testament = 2; + else + testament = 1; + + //if (map_verse == 0) Headings(1); + + chapter = map_chapter; + verse = map_verse; + suffix = ikey.getSuffix(); + + if (map_verse < map_range) { + if (map_range > refSys->getBook(((testament>1)?BMAX[0]:0)+book-1)->getVerseMax(chapter)) + ++map_range; + verse = map_range; + setUpperBound(this); + verse = map_verse; + setLowerBound(this); + } + } } @@ -381,14 +418,14 @@ int VerseKey::getBookFromAbbrev(const char *iabbr) const if (!i) { if (hasUTF8Support) { //we have support for UTF-8 handling; we expect UTF-8 encoded locales - stringMgr->upperUTF8(abbr, strlen(abbr)*2); + stringMgr->upperUTF8(abbr, (unsigned int)(strlen(abbr)*2)); } else { stringMgr->upperLatin1(abbr); } } - abLen = strlen(abbr); + abLen = (int)strlen(abbr); if (abLen) { min = 0; @@ -446,7 +483,7 @@ void VerseKey::validateCurrentLocale() const { 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); + stringMgr->upperUTF8(abbr, (unsigned int)(strlen(abbr)*2)); } else { stringMgr->upperLatin1(abbr); @@ -560,6 +597,7 @@ ListKey VerseKey::parseVerseList(const char *buf, const char *defaultKey, bool e comma = 0; break; } + goto terminate_range; // otherwise drop down to next case case ' ': inTerm = true; @@ -593,6 +631,7 @@ ListKey VerseKey::parseVerseList(const char *buf, const char *defaultKey, bool e } case ',': // on number new verse case ';': // on number new chapter +terminate_range: number[tonumber] = 0; tonumber = 0; if (*number) { @@ -605,7 +644,7 @@ ListKey VerseKey::parseVerseList(const char *buf, const char *defaultKey, bool e tobook = 0; bookno = -1; if (*book) { - loop = strlen(book) - 1; + loop = (int)strlen(book) - 1; for (; loop+1; loop--) { if (book[loop] == ' ') book[loop] = 0; else break; } @@ -628,7 +667,7 @@ ListKey VerseKey::parseVerseList(const char *buf, const char *defaultKey, bool e break; } - for (loop = strlen(book) - 1; loop+1; loop--) { + for (loop = (int)strlen(book) - 1; loop+1; loop--) { if (book[loop] == ' ') { // "PS C" is ok, but "II C" is not ok if (isroman(&book[loop+1]) && !isroman(book,loop)) { @@ -643,14 +682,14 @@ ListKey VerseKey::parseVerseList(const char *buf, const char *defaultKey, bool e } // check for special inscriptio and subscriptio which are saved as book intro and chap 1 intro (for INTF) - for (loop = strlen(book) - 1; loop+1; loop--) { + for (loop = (int)strlen(book) - 1; loop+1; loop--) { if (book[loop] == ' ') { - if (!strnicmp(&book[loop+1], "inscriptio", strlen(&book[loop+1]))) { + if (!strnicmp(&book[loop+1], "inscriptio", (int)strlen(&book[loop+1]))) { book[loop] = 0; verse = 0; chap = 0; } - else if (!strnicmp(&book[loop+1], "subscriptio", strlen(&book[loop+1]))) { + else if (!strnicmp(&book[loop+1], "subscriptio", (int)strlen(&book[loop+1]))) { book[loop] = 0; verse = 0; chap = 1; @@ -876,7 +915,7 @@ ListKey VerseKey::parseVerseList(const char *buf, const char *defaultKey, bool e book[tobook] = 0; tobook = 0; if (*book) { - loop = strlen(book) - 1; + loop = (int)strlen(book) - 1; // strip trailing spaces for (; loop+1; loop--) { if (book[loop] == ' ') book[loop] = 0; else break; } @@ -905,7 +944,7 @@ ListKey VerseKey::parseVerseList(const char *buf, const char *defaultKey, bool e } // check for roman numeral chapter - for (loop = strlen(book) - 1; loop+1; loop--) { + for (loop = (int)strlen(book) - 1; loop+1; loop--) { if (book[loop] == ' ') { // "PS C" is ok, but "II C" is not ok if (isroman(&book[loop+1]) && !isroman(book,loop)) { @@ -919,19 +958,19 @@ ListKey VerseKey::parseVerseList(const char *buf, const char *defaultKey, bool e } } // check for special inscriptio and subscriptio which are saved as book intro and chap 1 intro (for INTF) - for (loop = strlen(book) - 1; loop+1; loop--) { + for (loop = (int)strlen(book) - 1; loop+1; loop--) { if (book[loop] == ' ') { - if (!strnicmp(&book[loop+1], "inscriptio", strlen(&book[loop+1]))) { + if (!strnicmp(&book[loop+1], "inscriptio", (int)strlen(&book[loop+1]))) { book[loop] = 0; verse = 0; chap = 0; suffix = 0; } - else if (!strnicmp(&book[loop+1], "subscriptio", strlen(&book[loop+1]))) { + else if (!strnicmp(&book[loop+1], "subscriptio", (int)strlen(&book[loop+1]))) { book[loop] = 0; verse = 0; chap = 1; - suffix = 0; + suffix = 0; } break; } @@ -1391,6 +1430,11 @@ void VerseKey::normalize(bool autocheck) } if (chapter < (intros?0:1)) { --book; + if (book < (intros?0:1)) { + if (--testament > 0) { + book += (BMAX[testament-1] + (intros?1:0)); + } + } chapter += (getChapterMax() + (intros?1:0)); continue; } @@ -1404,6 +1448,11 @@ void VerseKey::normalize(bool autocheck) if (verse < (intros?0:1)) { if (--chapter < (intros?0:1)) { --book; + if (book < (intros?0:1)) { + if (--testament > 0) { + book += (BMAX[testament-1] + (intros?1:0)); + } + } chapter += (getChapterMax() + (intros?1:0)); } verse += (getVerseMax() + (intros?1:0)); @@ -1756,7 +1805,7 @@ int VerseKey::_compare(const VerseKey &ivkey) keyval1 += (int)getSuffix(); keyval2 += (int)ivkey.getSuffix(); keyval1 = (keyval1 != keyval2) ? ((keyval1 > keyval2) ? 1 : -1) : 0; // -1 | 0 | 1 - return keyval1; + return (int)keyval1; } @@ -1831,14 +1880,14 @@ const char *VerseKey::convertToOSIS(const char *inRef, const SWKey *lastKnownKey memset(frag, 0, 800); memset(preJunk, 0, 800); memset(postJunk, 0, 800); - while ((*startFrag) && (strchr(" {};,()[].", *startFrag))) { + while ((*startFrag) && (strchr(" {}:;,()[].", *startFrag))) { outRef += *startFrag; startFrag++; } - memmove(frag, startFrag, ((const char *)element->userData - startFrag) + 1); + memmove(frag, startFrag, (size_t)((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--); + for (j = strlen(frag)-1; j && (strchr(" {}:;,()[].", frag[j])); j--); if (frag[j+1]) strcpy(postJunk, frag+j+1); frag[j+1]=0; diff --git a/src/keys/versetreekey.cpp b/src/keys/versetreekey.cpp index 571314f..09dd6b6 100644 --- a/src/keys/versetreekey.cpp +++ b/src/keys/versetreekey.cpp @@ -3,7 +3,7 @@ * versetreekey.cpp - code for class 'VerseTreeKey'- versekey using treekey * for data retrieval * - * $Id: versetreekey.cpp 2833 2013-06-29 06:40:28Z chrislit $ + * $Id: versetreekey.cpp 3455 2017-04-24 08:50:31Z scribe $ * * Copyright 2006-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -24,6 +24,7 @@ #include #include +#include SWORD_NAMESPACE_START @@ -92,6 +93,7 @@ int VerseTreeKey::getBookFromAbbrev(const char *iabbr) const { int bookno = VerseKey::getBookFromAbbrev(iabbr); if (bookno < 0) { + SWLog::getSystemLog(); // TODO fix for odd android bug /* vector::iterator it = find(books, iabbr); if (it == books.end()) { diff --git a/src/mgr/Makefile.am b/src/mgr/Makefile.am index 6acec3a..38f9cc4 100644 --- a/src/mgr/Makefile.am +++ b/src/mgr/Makefile.am @@ -15,6 +15,9 @@ FTP_SOURCES += $(mgrdir)/curlhttpt.cpp else FTP_SOURCES = $(mgrdir)/ftplibftpt.cpp endif +if WITHGAPI +FTP_SOURCES += $(mgrdir)/rtranspgdrive.cpp +endif libsword_la_SOURCES += $(FTP_SOURCES) libsword_la_SOURCES += $(mgrdir)/swconfig.cpp diff --git a/src/mgr/curlftpt.cpp b/src/mgr/curlftpt.cpp index 63eacb1..b287405 100644 --- a/src/mgr/curlftpt.cpp +++ b/src/mgr/curlftpt.cpp @@ -2,7 +2,7 @@ * * curlftpt.cpp - CURLFTPTransport * - * $Id: curlftpt.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: curlftpt.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 2004-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -63,12 +63,12 @@ namespace { return -1; /* failure, can't open file to write */ } if (out->destBuf) { - int s = out->destBuf->size(); + int s = (int)out->destBuf->size(); out->destBuf->size(s+(size*nmemb)); memcpy(out->destBuf->getRawData()+s, buffer, size*nmemb); - return nmemb; + return (int)nmemb; } - return fwrite(buffer, size, nmemb, out->stream); + return (int)fwrite(buffer, size, nmemb, out->stream); } diff --git a/src/mgr/curlhttpt.cpp b/src/mgr/curlhttpt.cpp index 5db0ee7..b9219a0 100644 --- a/src/mgr/curlhttpt.cpp +++ b/src/mgr/curlhttpt.cpp @@ -2,7 +2,7 @@ * * curlhttpt.cpp - CURLHTTPTransport * - * $Id: curlhttpt.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: curlhttpt.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2004-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -55,12 +55,12 @@ namespace { return -1; /* failure, can't open file to write */ } if (out->destBuf) { - int s = out->destBuf->size(); + int s = (int)out->destBuf->size(); out->destBuf->size(s+(size*nmemb)); memcpy(out->destBuf->getRawData()+s, buffer, size*nmemb); - return nmemb; + return (int)nmemb; } - return fwrite(buffer, size, nmemb, out->stream); + return (int)fwrite(buffer, size, nmemb, out->stream); } @@ -141,7 +141,9 @@ char CURLHTTPTransport::getURL(const char *destPath, const char *sourceURL, SWBu curl_easy_setopt(session, CURLOPT_CONNECTTIMEOUT, 45); /* Disable checking host certificate */ - curl_easy_setopt(session, CURLOPT_SSL_VERIFYPEER, false); + if (isUnverifiedPeerAllowed()) { + curl_easy_setopt(session, CURLOPT_SSL_VERIFYPEER, false); + } /* FTP connection settings */ @@ -215,7 +217,7 @@ vector CURLHTTPTransport::getDirList(const char *dirURL) { pBufRes = (char *)strchr(pBuf, '\"');//Find the end of the possible file name if (!pBufRes) break; - possibleNameLength = pBufRes - pBuf; + possibleNameLength = (int)(pBufRes - pBuf); possibleName.setFormatted("%.*s", possibleNameLength, pBuf); if (isalnum(possibleName[0])) { SWLog::getSystemLog()->logDebug("getDirListHTTP: Found a file: %s", possibleName.c_str()); diff --git a/src/mgr/encfiltmgr.cpp b/src/mgr/encfiltmgr.cpp index 24938bc..25ff415 100644 --- a/src/mgr/encfiltmgr.cpp +++ b/src/mgr/encfiltmgr.cpp @@ -4,7 +4,7 @@ * SWFilterMgr, used to transcode all module text to a * requested encoding * - * $Id: encfiltmgr.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: encfiltmgr.cpp 3083 2014-03-06 08:13:10Z chrislit $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -27,11 +27,17 @@ #include #include +#include #include #include #include #include + +#ifdef _ICU_ +#include +#endif + #include #include @@ -51,6 +57,7 @@ EncodingFilterMgr::EncodingFilterMgr(char enc) scsuutf8 = new SCSUUTF8(); latin1utf8 = new Latin1UTF8(); + utf16utf8 = new UTF16UTF8(); encoding = enc; @@ -59,6 +66,9 @@ EncodingFilterMgr::EncodingFilterMgr(char enc) case ENC_UTF16: targetenc = new UTF8UTF16(); break; case ENC_RTF: targetenc = new UnicodeRTF(); break; case ENC_HTML: targetenc = new UTF8HTML(); break; +#ifdef _ICU_ + case ENC_SCSU: targetenc = new UTF8SCSU(); break; +#endif default: // i.e. case ENC_UTF8 targetenc = NULL; } @@ -71,6 +81,7 @@ EncodingFilterMgr::EncodingFilterMgr(char enc) EncodingFilterMgr::~EncodingFilterMgr() { delete scsuutf8; delete latin1utf8; + delete utf16utf8; delete targetenc; } @@ -81,11 +92,14 @@ void EncodingFilterMgr::AddRawFilters(SWModule *module, ConfigEntMap §ion) { SWBuf encoding = ((entry = section.find("Encoding")) != section.end()) ? (*entry).second : (SWBuf)""; if (!encoding.length() || !stricmp(encoding.c_str(), "Latin-1")) { - module->addRawFilter(latin1utf8); + module->addRawFilter(latin1utf8); } else if (!stricmp(encoding.c_str(), "SCSU")) { module->addRawFilter(scsuutf8); } + else if (!stricmp(encoding.c_str(), "UTF-16")) { + module->addRawFilter(utf16utf8); + } } @@ -112,6 +126,9 @@ char EncodingFilterMgr::Encoding(char enc) { case ENC_UTF16: targetenc = new UTF8UTF16(); break; case ENC_RTF: targetenc = new UnicodeRTF(); break; case ENC_HTML: targetenc = new UTF8HTML(); break; +#ifdef _ICU_ + case ENC_SCSU: targetenc = new UTF8SCSU(); break; +#endif default: // i.e. case ENC_UTF8 targetenc = NULL; } diff --git a/src/mgr/filemgr.cpp b/src/mgr/filemgr.cpp index d801aaa..be4efcc 100644 --- a/src/mgr/filemgr.cpp +++ b/src/mgr/filemgr.cpp @@ -3,7 +3,7 @@ * filemgr.cpp - implementation of class FileMgr used for pooling file * handles * - * $Id: filemgr.cpp 2833 2013-06-29 06:40:28Z chrislit $ + * $Id: filemgr.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 1998-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -131,15 +132,6 @@ FileDesc::~FileDesc() { } -int FileDesc::getFd() { - if (fd == -77) - fd = parent->sysOpen(this); -// if ((fd < -1) && (fd != -77)) // kludge to hand ce -// return 777; - return fd; -} - - long FileDesc::seek(long offset, int whence) { return lseek(getFd(), offset, whence); } @@ -282,8 +274,8 @@ signed char FileMgr::trunc(FileDesc *file) { file->seek(0, SEEK_SET); while (size > 0) { - bytes = file->read(nibble, 32767); - bytes = (bytes < size)?bytes:size; + bytes = (int)file->read(nibble, 32767); + bytes = (bytes < size)?bytes:(int)size; if (write(fd, nibble, bytes) != bytes) { break; } size -= bytes; } @@ -296,7 +288,7 @@ signed char FileMgr::trunc(FileDesc *file) { // copy tmp file back (dumb, but must preserve file permissions) lseek(fd, 0, SEEK_SET); do { - bytes = read(fd, nibble, 32767); + bytes = (int)read(fd, nibble, 32767); file->write(nibble, bytes); } while (bytes == 32767); } @@ -316,7 +308,7 @@ signed char FileMgr::trunc(FileDesc *file) { signed char FileMgr::existsFile(const char *ipath, const char *ifileName) { - int len = strlen(ipath) + ((ifileName)?strlen(ifileName):0) + 3; + int len = (int)strlen(ipath) + ((ifileName)?strlen(ifileName):0) + 3; char *ch; char *path = new char [ len ]; strcpy(path, ipath); @@ -337,7 +329,7 @@ signed char FileMgr::existsFile(const char *ipath, const char *ifileName) signed char FileMgr::existsDir(const char *ipath, const char *idirName) { char *ch; - int len = strlen(ipath) + ((idirName)?strlen(idirName):0) + 1; + int len = (int)strlen(ipath) + ((idirName)?strlen(idirName):0) + 1; if (idirName) len += strlen(idirName); char *path = new char [ len ]; @@ -361,7 +353,7 @@ int FileMgr::createParent(const char *pName) { int retCode = 0; strcpy(buf, pName); - int end = strlen(buf) - 1; + int end = (int)strlen(buf) - 1; while (end) { if ((buf[end] == '/') || (buf[end] == '\\')) break; @@ -418,7 +410,7 @@ int FileMgr::copyFile(const char *sourceFile, const char *targetFile) { return -1; do { - len = read(sfd, buf, 4096); + len = (int)read(sfd, buf, 4096); if (write(dfd, buf, len) != len) break; } while(len == 4096); @@ -447,7 +439,7 @@ char FileMgr::getLine(FileDesc *fDesc, SWBuf &line) { while (more) { more = false; long index = fDesc->seek(0, SEEK_CUR); - len = fDesc->read(chunk, 254); + len = (int)fDesc->read(chunk, 254); // assert we have a readable file (not a directory) if (len < 1) @@ -509,23 +501,24 @@ char FileMgr::isDirectory(const char *path) { int FileMgr::copyDir(const char *srcDir, const char *destDir) { DIR *dir; struct dirent *ent; + int retVal = 0; if ((dir = opendir(srcDir))) { rewinddir(dir); - while ((ent = readdir(dir))) { + while ((ent = readdir(dir)) && !retVal) { if ((strcmp(ent->d_name, ".")) && (strcmp(ent->d_name, ".."))) { SWBuf srcPath = (SWBuf)srcDir + (SWBuf)"/" + ent->d_name; SWBuf destPath = (SWBuf)destDir + (SWBuf)"/" + ent->d_name; if (!isDirectory(srcPath.c_str())) { - copyFile(srcPath.c_str(), destPath.c_str()); + retVal = copyFile(srcPath.c_str(), destPath.c_str()); } else { - copyDir(srcPath.c_str(), destPath.c_str()); + retVal = copyDir(srcPath.c_str(), destPath.c_str()); } } } closedir(dir); } - return 0; + return retVal; } @@ -582,4 +575,22 @@ long FileMgr::resourceConsumption() { } +SWBuf FileMgr::getHomeDir() { + + // figure out 'home' directory for app data + SWBuf homeDir = getenv("HOME"); + if (!homeDir.length()) { + // silly windows + homeDir = getenv("APPDATA"); + } + if (homeDir.length()) { + if ((homeDir[homeDir.length()-1] != '\\') && (homeDir[homeDir.length()-1] != '/')) { + homeDir += "/"; + } + } + + return homeDir; +} + + SWORD_NAMESPACE_END diff --git a/src/mgr/ftplibftpt.cpp b/src/mgr/ftplibftpt.cpp index f1d1655..fae5964 100644 --- a/src/mgr/ftplibftpt.cpp +++ b/src/mgr/ftplibftpt.cpp @@ -2,7 +2,7 @@ * * ftplibftpt.cpp - FTPLibFTPTransport * - * $Id: ftplibftpt.cpp 2983 2013-09-15 16:22:32Z scribe $ + * $Id: ftplibftpt.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 2004-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -42,10 +42,10 @@ namespace { static int my_swbufwriter(netbuf *nControl, void *buffer, size_t size, void *swbuf) { SWBuf &output = *(SWBuf *)swbuf; - int s = output.size(); + int s = (int)output.size(); output.size(s+size); memcpy(output.getRawData()+s, buffer, size); - return size; + return (int)size; } #if defined(__GNUC__) @@ -56,9 +56,9 @@ namespace { static int my_fprogress(netbuf *nControl, int xfered, void *arg) { if (arg) { MyProgressData *pd = (MyProgressData *)arg; - SWLog::getSystemLog()->logDebug("FTPLibFTPTransport report progress: totalSize: %ld; xfered: %d\n", pd->totalSize, xfered); +//SWLog::getSystemLog()->logDebug("FTPLibFTPTransport report progress: totalSize: %ld; xfered: %d\n", pd->totalSize, xfered); if (pd->sr) { - pd->sr->statusUpdate(pd->totalSize, xfered); + pd->sr->update(pd->totalSize, xfered); } if (*(pd->term)) return 0; } diff --git a/src/mgr/installmgr.cpp b/src/mgr/installmgr.cpp index 1e83db5..fe1a674 100644 --- a/src/mgr/installmgr.cpp +++ b/src/mgr/installmgr.cpp @@ -2,7 +2,7 @@ * * installmgr.cpp - InstallMgr functions * - * $Id: installmgr.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: installmgr.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2002-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -59,7 +59,7 @@ SWORD_NAMESPACE_START namespace { static void removeTrailingSlash(SWBuf &buf) { - int len = buf.size(); + int len = (int)buf.size(); if ((buf[len-1] == '/') || (buf[len-1] == '\\')) buf.size(len-1); @@ -101,6 +101,8 @@ RemoteTransport *InstallMgr::createHTTPTransport(const char *host, StatusReporte InstallMgr::InstallMgr(const char *privatePath, StatusReporter *sr, SWBuf u, SWBuf p) { userDisclaimerConfirmed = false; + passive=true; + unverifiedPeerAllowed=true; statusReporter = sr; this->u = u; this->p = p; @@ -109,7 +111,7 @@ InstallMgr::InstallMgr(const char *privatePath, StatusReporter *sr, SWBuf u, SWB installConf = 0; stdstr(&(this->privatePath), privatePath); if (this->privatePath) { - int len = strlen(this->privatePath); + int len = (int)strlen(this->privatePath); if ((this->privatePath[len-1] == '/') || (this->privatePath[len-1] == '\\')) this->privatePath[len-1] = 0; @@ -145,12 +147,13 @@ void InstallMgr::readInstallConf() { clearSources(); setFTPPassive(stricmp((*installConf)["General"]["PassiveFTP"].c_str(), "false") != 0); + setUnverifiedPeerAllowed(stricmp((*installConf)["General"]["UnverifiedPeerAllowed"].c_str(), "false") != 0); - SectionMap::iterator confSection = installConf->Sections.find("Sources"); + SectionMap::iterator confSection = installConf->getSections().find("Sources"); ConfigEntMap::iterator sourceBegin; ConfigEntMap::iterator sourceEnd; - if (confSection != installConf->Sections.end()) { + if (confSection != installConf->getSections().end()) { sourceBegin = confSection->second.lower_bound("FTPSource"); sourceEnd = confSection->second.upper_bound("FTPSource"); @@ -204,8 +207,8 @@ void InstallMgr::readInstallConf() { } defaultMods.clear(); - confSection = installConf->Sections.find("General"); - if (confSection != installConf->Sections.end()) { + confSection = installConf->getSections().find("General"); + if (confSection != installConf->getSections().end()) { sourceBegin = confSection->second.lower_bound("DefaultMod"); sourceEnd = confSection->second.upper_bound("DefaultMod"); @@ -219,16 +222,17 @@ void InstallMgr::readInstallConf() { void InstallMgr::saveInstallConf() { - installConf->Sections["Sources"].clear(); + installConf->getSection("Sources").clear(); for (InstallSourceMap::iterator it = sources.begin(); it != sources.end(); ++it) { if (it->second) { - installConf->Sections["Sources"].insert(ConfigEntMap::value_type(it->second->type + "Source", it->second->getConfEnt().c_str())); + installConf->getSection("Sources").insert(ConfigEntMap::value_type(it->second->type + "Source", it->second->getConfEnt().c_str())); } } (*installConf)["General"]["PassiveFTP"] = (isFTPPassive()) ? "true" : "false"; + (*installConf)["General"]["UnverifiedPeerAllowed"] = (isUnverifiedPeerAllowed()) ? "true" : "false"; - installConf->Save(); + installConf->save(); } @@ -243,9 +247,9 @@ int InstallMgr::removeModule(SWMgr *manager, const char *moduleName) { // save our own copy, cuz when we remove the module from the SWMgr // it's likely we'll free the memory passed to us in moduleName SWBuf modName = moduleName; - module = manager->config->Sections.find(modName); + module = manager->config->getSections().find(modName); - if (module != manager->config->Sections.end()) { + if (module != manager->config->getSections().end()) { // to be sure all files are closed // this does not remove the .conf information from SWMgr manager->deleteModule(modName); @@ -285,7 +289,7 @@ int InstallMgr::removeModule(SWMgr *manager, const char *moduleName) { modFile += "/"; modFile += ent->d_name; SWConfig *config = new SWConfig(modFile.c_str()); - if (config->Sections.find(modName) != config->Sections.end()) { + if (config->getSections().find(modName) != config->getSections().end()) { delete config; FileMgr::removeFile(modFile.c_str()); } @@ -332,6 +336,8 @@ SWLog::getSystemLog()->logDebug("remoteCopy: %s, %s, %s, %c, %s", (is?is->source trans->setPasswd(p); } + trans->setUnverifiedPeerAllowed(unverifiedPeerAllowed); + SWBuf urlPrefix; if (is->type == "HTTP") { urlPrefix = (SWBuf) "http://"; @@ -361,6 +367,7 @@ SWLog::getSystemLog()->logDebug("remoteCopy: %s, %s, %s, %c, %s", (is?is->source SWBuf dir = (SWBuf)is->directory.c_str(); removeTrailingSlash(dir); dir += (SWBuf)"/" + src; //dont forget the final slash +SWLog::getSystemLog()->logDebug("remoteCopy: dirTransfer: %s", dir.c_str()); retVal = trans->copyDirectory(urlPrefix, dir, dest, suffix); @@ -393,6 +400,7 @@ SWLog::getSystemLog()->logDebug("remoteCopy: %s, %s, %s, %c, %s", (is?is->source int InstallMgr::installModule(SWMgr *destMgr, const char *fromLocation, const char *modName, InstallSource *is) { + int retVal = 0; SectionMap::iterator module, section; ConfigEntMap::iterator fileBegin; ConfigEntMap::iterator fileEnd; @@ -419,9 +427,9 @@ int InstallMgr::installModule(SWMgr *destMgr, const char *fromLocation, const ch SWMgr mgr(sourceDir.c_str()); - module = mgr.config->Sections.find(modName); + module = mgr.config->getSections().find(modName); - if (module != mgr.config->Sections.end()) { + if (module != mgr.config->getSections().end()) { entry = module->second.find("CipherKey"); if (entry != module->second.end()) @@ -449,14 +457,14 @@ int InstallMgr::installModule(SWMgr *destMgr, const char *fromLocation, const ch if (!aborted) { // DO THE INSTALL - while (fileBegin != fileEnd) { + while (fileBegin != fileEnd && !retVal) { SWBuf sourcePath = sourceDir; sourcePath += fileBegin->second.c_str(); SWBuf dest = destMgr->prefixPath; removeTrailingSlash(dest); dest += '/'; dest += fileBegin->second.c_str(); - FileMgr::copyFile(sourcePath.c_str(), dest.c_str()); + retVal = FileMgr::copyFile(sourcePath.c_str(), dest.c_str()); fileBegin++; } @@ -504,7 +512,7 @@ int InstallMgr::installModule(SWMgr *destMgr, const char *fromLocation, const ch } if (!aborted) { SWBuf destPath = (SWBuf)destMgr->prefixPath + relativePath; - FileMgr::copyDir(absolutePath.c_str(), destPath.c_str()); + retVal = FileMgr::copyDir(absolutePath.c_str(), destPath.c_str()); } if (is) { // delete tmp netCopied files // mgr->deleteModule(modName); @@ -516,17 +524,17 @@ int InstallMgr::installModule(SWMgr *destMgr, const char *fromLocation, const ch SWBuf confDir = sourceDir + "mods.d/"; if ((dir = opendir(confDir.c_str()))) { // find and copy .conf file rewinddir(dir); - while ((ent = readdir(dir))) { + while ((ent = readdir(dir)) && !retVal) { if ((strcmp(ent->d_name, ".")) && (strcmp(ent->d_name, ".."))) { modFile = confDir; modFile += ent->d_name; SWConfig *config = new SWConfig(modFile.c_str()); - if (config->Sections.find(modName) != config->Sections.end()) { + if (config->getSections().find(modName) != config->getSections().end()) { SWBuf targetFile = destMgr->configPath; //"./mods.d/"; removeTrailingSlash(targetFile); targetFile += "/"; targetFile += ent->d_name; - FileMgr::copyFile(modFile.c_str(), targetFile.c_str()); + retVal = FileMgr::copyFile(modFile.c_str(), targetFile.c_str()); if (cipher) { if (getCipherCode(modName, config)) { SWMgr newDest(destMgr->prefixPath); @@ -534,8 +542,8 @@ int InstallMgr::installModule(SWMgr *destMgr, const char *fromLocation, const ch aborted = true; } else { - config->Save(); - FileMgr::copyFile(modFile.c_str(), targetFile.c_str()); + config->save(); + retVal = FileMgr::copyFile(modFile.c_str(), targetFile.c_str()); } } } @@ -545,7 +553,7 @@ int InstallMgr::installModule(SWMgr *destMgr, const char *fromLocation, const ch closedir(dir); } } - return (aborted) ? -1 : 0; + return (aborted) ? -9 : retVal; } return 1; } @@ -660,8 +668,8 @@ int InstallMgr::refreshRemoteSourceConfiguration() { int errorCode = remoteCopy(&is, masterRepoList, masterRepoListPath.c_str(), false); if (!errorCode) { //sucessfully downloaded the repo list SWConfig masterList(masterRepoListPath); - SectionMap::iterator sections = masterList.Sections.find("Repos"); - if (sections != masterList.Sections.end()) { + SectionMap::iterator sections = masterList.getSections().find("Repos"); + if (sections != masterList.getSections().end()) { for (ConfigEntMap::iterator actions = sections->second.begin(); actions != sections->second.end(); actions++) { // Search through our current sources and see if we have a matching UID InstallSourceMap::iterator it; diff --git a/src/mgr/localemgr.cpp b/src/mgr/localemgr.cpp index 90d4716..ec19d11 100644 --- a/src/mgr/localemgr.cpp +++ b/src/mgr/localemgr.cpp @@ -3,7 +3,7 @@ * localemgr.cpp - implementation of class LocaleMgr used to interact with * registered locales for a SWORD installation * - * $Id: localemgr.cpp 3005 2014-01-09 04:06:11Z greg.hellings $ + * $Id: localemgr.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2000-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -85,7 +85,7 @@ LocaleMgr::LocaleMgr(const char *iConfigPath) { SWLog::getSystemLog()->logDebug("LOOKING UP LOCALE DIRECTORY..."); SWMgr::findConfig(&configType, &prefixPath, &configPath, &augPaths, &sysConf); if (sysConf) { - if ((entry = sysConf->Sections["Install"].find("LocalePath")) != sysConf->Sections["Install"].end()) { + if ((entry = sysConf->getSection("Install").find("LocalePath")) != sysConf->getSection("Install").end()) { configType = 9; // our own stdstr(&prefixPath, (char *)entry->second.c_str()); SWLog::getSystemLog()->logDebug("LocalePath provided in sysConfig."); @@ -101,7 +101,7 @@ LocaleMgr::LocaleMgr(const char *iConfigPath) { switch (configType) { case 2: int i; - for (i = strlen(configPath)-1; ((i) && (configPath[i] != '/') && (configPath[i] != '\\')); i--); + for (i = (int)strlen(configPath)-1; ((i) && (configPath[i] != '/') && (configPath[i] != '\\')); i--); configPath[i] = 0; path = configPath; path += "/"; diff --git a/src/mgr/markupfiltmgr.cpp b/src/mgr/markupfiltmgr.cpp index fb12583..94b1407 100644 --- a/src/mgr/markupfiltmgr.cpp +++ b/src/mgr/markupfiltmgr.cpp @@ -4,7 +4,7 @@ * used to transcode all module text to a requested * markup * - * $Id: markupfiltmgr.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: markupfiltmgr.cpp 3075 2014-03-05 02:27:33Z chrislit $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -49,7 +50,10 @@ #include #include #include - +#include +#include +#include + #include #include @@ -279,6 +283,14 @@ void MarkupFilterMgr::CreateFilters(char markup) { fromtei = new TEIRTF(); break; + case FMT_LATEX: + fromplain = NULL; + fromthml = new ThMLLaTeX(); + fromgbf = new GBFLaTeX(); + fromosis = new OSISLaTeX(); + fromtei = new TEILaTeX(); + break; + case FMT_OSIS: fromplain = NULL; fromthml = new ThMLOSIS(); diff --git a/src/mgr/remotetrans.cpp b/src/mgr/remotetrans.cpp index 03ad3e4..2d14d8f 100644 --- a/src/mgr/remotetrans.cpp +++ b/src/mgr/remotetrans.cpp @@ -1,8 +1,8 @@ -/***************************************************************************** +/***************************************************************************** * * remotetrans.cpp - * - * $Id: remotetrans.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: remotetrans.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2004-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -65,6 +65,8 @@ RemoteTransport::RemoteTransport(const char *host, StatusReporter *statusReporte u = "ftp"; p = "installmgr@user.com"; term = false; + passive = true; + unverifiedPeerAllowed = true; } @@ -74,13 +76,22 @@ RemoteTransport::~RemoteTransport() { // override this method in your real transport class char RemoteTransport::getURL(const char *destPath, const char *sourceURL, SWBuf *destBuf) { - char retVal = 0; + SWLog::getSystemLog()->logWarning("RemoteTransport::getURL called but unsupported"); + char retVal = -1; + return retVal; +} + +// override this method in your real transport class +char RemoteTransport::putURL(const char *destURL, const char *sourcePath, SWBuf *sourceBuf) { + SWLog::getSystemLog()->logWarning("RemoteTransport::putURL called but unsupported"); + char retVal = -1; return retVal; } vector RemoteTransport::getDirList(const char *dirURL) { + SWLog::getSystemLog()->logDebug("RemoteTransport::getDirList(%s)", dirURL); vector dirList; SWBuf dirBuf; @@ -100,12 +111,12 @@ vector RemoteTransport::getDirList(const char *dirURL) { else if ((*end != 10) && (*end != 13)) break; } - SWLog::getSystemLog()->logWarning("getDirList: parsing item %s(%d)\n", start, end-start); - int status = ftpparse(&item, start, end - start); + SWLog::getSystemLog()->logDebug("getDirList: parsing item %s(%d)\n", start, end-start); + int status = ftpparse(&item, start, (int)(end - start)); // in ftpparse.h, there is a warning that name is not necessarily null terminated SWBuf name; name.append(item.name, item.namelen); - SWLog::getSystemLog()->logWarning("getDirList: got item %s\n", name.c_str()); + SWLog::getSystemLog()->logDebug("getDirList: got item %s\n", name.c_str()); if (status && name != "." && name != "..") { struct DirEntry i; i.name = name; @@ -124,24 +135,45 @@ vector RemoteTransport::getDirList(const char *dirURL) { int RemoteTransport::copyDirectory(const char *urlPrefix, const char *dir, const char *dest, const char *suffix) { - unsigned int i; + SWLog::getSystemLog()->logDebug("RemoteTransport::copyDirectory"); int retVal = 0; - + SWBuf url = SWBuf(urlPrefix) + SWBuf(dir); removeTrailingSlash(url); url += '/'; - SWLog::getSystemLog()->logWarning("NetTransport: getting dir %s\n", url.c_str()); + SWLog::getSystemLog()->logDebug("NetTransport: getting dir %s\n", url.c_str()); vector dirList = getDirList(url.c_str()); if (!dirList.size()) { SWLog::getSystemLog()->logWarning("NetTransport: failed to read dir %s\n", url.c_str()); return -1; } - + + // append files in sub directories and calculate total download size + unsigned int i = 0; long totalBytes = 0; - for (i = 0; i < dirList.size(); i++) - totalBytes += dirList[i].size; + for (;;) { + if (i == dirList.size()) + break; + + struct DirEntry &e = dirList.at(i); + + if (e.isDirectory) { + SWBuf name(e.name); // &e will be invalidated after first insertion + vector sd = getDirList((url + name + '/').c_str()); + for (unsigned int ii = 0; ii < sd.size(); ii++) { + sd[ii].name = name + '/' + sd[ii].name; + dirList.push_back(sd[ii]); + } + dirList.erase(dirList.begin() + i); + } + else { + totalBytes += e.size; + i++; + } + } + long completedBytes = 0; for (i = 0; i < dirList.size(); i++) { struct DirEntry &dirEntry = dirList[i]; @@ -163,23 +195,12 @@ int RemoteTransport::copyDirectory(const char *urlPrefix, const char *dir, const SWBuf url = (SWBuf)urlPrefix + (SWBuf)dir; removeTrailingSlash(url); url += "/"; - url += dirEntry.name; //dont forget the final slash - if (!dirEntry.isDirectory) { - if (getURL(buffer.c_str(), url.c_str())) { - SWLog::getSystemLog()->logWarning("copyDirectory: failed to get file %s\n", url.c_str()); - return -2; - } - completedBytes += dirEntry.size; - } - else { - SWBuf subdir = (SWBuf)dir; - removeTrailingSlash(subdir); - subdir += (SWBuf)"/" + dirEntry.name; - if (copyDirectory(urlPrefix, subdir, buffer.c_str(), suffix)) { - SWLog::getSystemLog()->logWarning("copyDirectory: failed to get file %s\n", subdir.c_str()); - return -2; - } + url += dirEntry.name; + if (getURL(buffer.c_str(), url.c_str())) { + SWLog::getSystemLog()->logWarning("copyDirectory: failed to get file %s\n", url.c_str()); + return -2; } + completedBytes += dirEntry.size; } SWCATCH (...) {} if (term) { diff --git a/src/mgr/rtranspgdrive.cpp b/src/mgr/rtranspgdrive.cpp new file mode 100644 index 0000000..10931aa --- /dev/null +++ b/src/mgr/rtranspgdrive.cpp @@ -0,0 +1,174 @@ +/***************************************************************************** + * + * rtranspgdrive.cpp - RTransportGDrive + * + * $Id$ + * + * Copyright 2004-2013 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 + +#include + +#include + + +SWORD_NAMESPACE_START + +namespace { + + struct FtpFile { + const char *filename; + FILE *stream; + SWBuf *destBuf; + }; + + + // initialize/cleanup SYSTEMWIDE library with life of this static. + static class RTransportGDrive_init { + public: + RTransportGDrive_init() { + } + + ~RTransportGDrive_init() { + } + } _rTransportGDrive_init; + + + static int my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) { + struct FtpFile *out=(struct FtpFile *)stream; + if (out && !out->stream && !out->destBuf) { + /* open file for writing */ + out->stream=fopen(out->filename, "wb"); + if (!out->stream) + return -1; /* failure, can't open file to write */ + } + if (out->destBuf) { + int s = (int)out->destBuf->size(); + out->destBuf->size(s+(size*nmemb)); + memcpy(out->destBuf->getRawData()+s, buffer, size*nmemb); + return (int)nmemb; + } + return (int)fwrite(buffer, size, nmemb, out->stream); + } + + + struct MyProgressData { + StatusReporter *sr; + bool *term; + }; + + + static int my_fprogress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { + if (clientp) { + MyProgressData *pd = (MyProgressData *)clientp; + SWLog::getSystemLog()->logDebug("CURLFTPTransport report progress: totalSize: %ld; xfered: %ld\n", (long)dltotal, (long)dlnow); + if (pd->sr) { + if (dltotal < 0) dltotal = 0; + if (dlnow < 0) dlnow = 0; + if (dlnow > dltotal) dlnow = dltotal; + pd->sr->update(dltotal, dlnow); + } + if (*(pd->term)) return 1; + } + return 0; + } +} + + +RTransportGDrive::RTransportGDrive(const char *host, StatusReporter *sr) : RemoteTransport(host, sr) { + // session open +} + + +RTransportGDrive::~RTransportGDrive() { + // session cleanup +} + + +char RTransportGDrive::putURL(const char *destURL, const char *sourcePath, SWBuf *sourceBuf) { + return RemoteTransport::putURL(destURL, sourcePath, sourceBuf); +} +char RTransportGDrive::getURL(const char *destPath, const char *sourceURL, SWBuf *destBuf) { + signed char retVal = 0; + struct FtpFile ftpfile = {destPath, 0, destBuf}; +#if 0 + + if (session) { + + CURLcode res; + + struct MyProgressData pd; + pd.sr = statusReporter; + pd.term = &term; + + curl_easy_setopt(session, CURLOPT_URL, sourceURL); + + SWBuf credentials = u + ":" + p; + curl_easy_setopt(session, CURLOPT_USERPWD, credentials.c_str()); + curl_easy_setopt(session, CURLOPT_WRITEFUNCTION, my_fwrite); + if (!passive) + curl_easy_setopt(session, CURLOPT_FTPPORT, "-"); + curl_easy_setopt(session, CURLOPT_NOPROGRESS, 0); + curl_easy_setopt(session, CURLOPT_PROGRESSDATA, &pd); + curl_easy_setopt(session, CURLOPT_PROGRESSFUNCTION, my_fprogress); + curl_easy_setopt(session, CURLOPT_DEBUGFUNCTION, my_trace); + /* Set a pointer to our struct to pass to the callback */ + curl_easy_setopt(session, CURLOPT_FILE, &ftpfile); + + /* Switch on full protocol/debug output */ + curl_easy_setopt(session, CURLOPT_VERBOSE, true); + curl_easy_setopt(session, CURLOPT_CONNECTTIMEOUT, 45); + + /* FTP connection settings */ + +#if (LIBCURL_VERSION_MAJOR > 7) || \ + ((LIBCURL_VERSION_MAJOR == 7) && (LIBCURL_VERSION_MINOR > 10)) || \ + ((LIBCURL_VERSION_MAJOR == 7) && (LIBCURL_VERSION_MINOR == 10) && (LIBCURL_VERSION_PATCH >= 5)) +# define EPRT_AVAILABLE 1 +#endif + +#ifdef EPRT_AVAILABLE + curl_easy_setopt(session, CURLOPT_FTP_USE_EPRT, 0); + SWLog::getSystemLog()->logDebug("***** using CURLOPT_FTP_USE_EPRT\n"); +#endif + + + SWLog::getSystemLog()->logDebug("***** About to perform curl easy action. \n"); + SWLog::getSystemLog()->logDebug("***** destPath: %s \n", destPath); + SWLog::getSystemLog()->logDebug("***** sourceURL: %s \n", sourceURL); + res = curl_easy_perform(session); + SWLog::getSystemLog()->logDebug("***** Finished performing curl easy action. \n"); + + // it seems CURL tries to use this option data later for some reason, so we unset here + curl_easy_setopt(session, CURLOPT_PROGRESSDATA, (void*)NULL); + + if(CURLE_OK != res) { + retVal = -1; + } + } +#endif + + if (ftpfile.stream) + fclose(ftpfile.stream); /* close the local file */ + + return retVal; +} + + +SWORD_NAMESPACE_END + diff --git a/src/mgr/stringmgr.cpp b/src/mgr/stringmgr.cpp index 0390905..8538cd8 100644 --- a/src/mgr/stringmgr.cpp +++ b/src/mgr/stringmgr.cpp @@ -2,7 +2,7 @@ * * stringmgr.cpp - implementation of class StringMgr * - * $Id: stringmgr.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: stringmgr.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 2004-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -248,7 +248,7 @@ bool StringMgr::supportsUnicode() const { char *ICUStringMgr::upperUTF8(char *buf, unsigned int maxlen) const { char *ret = buf; - int max = (maxlen) ? maxlen : strlen(buf); + int max = (int)((maxlen) ? maxlen : strlen(buf)); UErrorCode err = U_ZERO_ERROR; diff --git a/src/mgr/swconfig.cpp b/src/mgr/swconfig.cpp index 748071c..1fcef2b 100644 --- a/src/mgr/swconfig.cpp +++ b/src/mgr/swconfig.cpp @@ -3,7 +3,7 @@ * swconfig.cpp - used for saving and retrieval of configuration * information * - * $Id: swconfig.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: swconfig.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 1998-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -29,14 +29,18 @@ SWORD_NAMESPACE_START +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif SWConfig::SWConfig() { } -SWConfig::SWConfig(const char * ifilename) { +SWConfig::SWConfig(const char *ifilename) { filename = ifilename; - Load(); + load(); } @@ -44,9 +48,13 @@ SWConfig::~SWConfig() { } -void SWConfig::Load() { +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif - if (!filename.size()) return; // assert we have a filename +void SWConfig::load() { + + if (!getFileName().size()) return; // assert we have a filename FileDesc *cfile; char *buf, *data; @@ -55,9 +63,9 @@ void SWConfig::Load() { SWBuf sectname; bool first = true; - Sections.erase(Sections.begin(), Sections.end()); + getSections().erase(getSections().begin(), getSections().end()); - cfile = FileMgr::getSystemFileMgr()->open(filename.c_str(), FileMgr::RDONLY); + cfile = FileMgr::getSystemFileMgr()->open(getFileName().c_str(), FileMgr::RDONLY); if (cfile->getFd() > 0) { bool goodLine = FileMgr::getLine(cfile, line); @@ -76,7 +84,7 @@ void SWConfig::Load() { strcpy(buf, line.c_str()); if (*strstrip(buf) == '[') { if (!first) - Sections.insert(SectionMap::value_type(sectname, cursect)); + getSections().insert(SectionMap::value_type(sectname, cursect)); else first = false; cursect.erase(cursect.begin(), cursect.end()); @@ -97,32 +105,32 @@ void SWConfig::Load() { goodLine = FileMgr::getLine(cfile, line); } if (!first) - Sections.insert(SectionMap::value_type(sectname, cursect)); + getSections().insert(SectionMap::value_type(sectname, cursect)); FileMgr::getSystemFileMgr()->close(cfile); } } -void SWConfig::Save() { +void SWConfig::save() const { - if (!filename.size()) return; // assert we have a filename + if (!getFileName().size()) return; // assert we have a filename FileDesc *cfile; SWBuf buf; - SectionMap::iterator sit; - ConfigEntMap::iterator entry; + SectionMap::const_iterator sit; + ConfigEntMap::const_iterator entry; SWBuf sectname; - cfile = FileMgr::getSystemFileMgr()->open(filename.c_str(), FileMgr::RDWR|FileMgr::CREAT|FileMgr::TRUNC); + cfile = FileMgr::getSystemFileMgr()->open(getFileName().c_str(), FileMgr::RDWR|FileMgr::CREAT|FileMgr::TRUNC); if (cfile->getFd() > 0) { - for (sit = Sections.begin(); sit != Sections.end(); sit++) { + for (sit = getSections().begin(); sit != getSections().end(); ++sit) { buf = "\n["; buf += (*sit).first.c_str(); buf += "]\n"; cfile->write(buf.c_str(), buf.length()); - for (entry = (*sit).second.begin(); entry != (*sit).second.end(); entry++) { + for (entry = (*sit).second.begin(); entry != (*sit).second.end(); ++entry) { buf = (*entry).first.c_str(); buf += "="; buf += (*entry).second.c_str(); @@ -142,32 +150,45 @@ void SWConfig::augment(SWConfig &addFrom) { SectionMap::iterator section; ConfigEntMap::iterator entry, start, end; - for (section = addFrom.Sections.begin(); section != addFrom.Sections.end(); section++) { - for (entry = (*section).second.begin(); entry != (*section).second.end(); entry++) { - start = Sections[section->first].lower_bound(entry->first); - end = Sections[section->first].upper_bound(entry->first); + for (section = addFrom.getSections().begin(); section != addFrom.getSections().end(); ++section) { + for (entry = (*section).second.begin(); entry != (*section).second.end(); ++entry) { + start = getSections()[section->first].lower_bound(entry->first); + end = getSections()[section->first].upper_bound(entry->first); if (start != end) { if (((++start) != end) - || ((++(addFrom.Sections[section->first].lower_bound(entry->first))) != addFrom.Sections[section->first].upper_bound(entry->first))) { - for (--start; start != end; start++) { + || ((++(addFrom.getSections()[section->first].lower_bound(entry->first))) != addFrom.getSections()[section->first].upper_bound(entry->first))) { + for (--start; start != end; ++start) { if (!strcmp(start->second.c_str(), entry->second.c_str())) break; } if (start == end) - Sections[(*section).first].insert(ConfigEntMap::value_type((*entry).first, (*entry).second)); + getSections()[(*section).first].insert(ConfigEntMap::value_type((*entry).first, (*entry).second)); } - else Sections[section->first][entry->first.c_str()] = entry->second.c_str(); + else getSections()[section->first][entry->first.c_str()] = entry->second.c_str(); } - else Sections[section->first][entry->first.c_str()] = entry->second.c_str(); + else getSections()[section->first][entry->first.c_str()] = entry->second.c_str(); } } } -ConfigEntMap & SWConfig::operator [] (const char *section) { - return Sections[section]; -} +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + +// TODO: use deprecated public 'Sections' property for now until we remove deprecation +// and store in private property +SectionMap &SWConfig::getSections() { return Sections; } + +// TODO: use deprecated public 'filename' property for now until we remove deprecation +// and store in private property + +SWBuf SWConfig::getFileName() const { return filename; } +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif SWORD_NAMESPACE_END diff --git a/src/mgr/swlocale.cpp b/src/mgr/swlocale.cpp index a007238..7aa9a0a 100644 --- a/src/mgr/swlocale.cpp +++ b/src/mgr/swlocale.cpp @@ -3,7 +3,7 @@ * swlocale.cpp - implementation of Class SWLocale used for retrieval * of locale lookups * - * $Id: swlocale.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: swlocale.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2000-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -69,16 +69,16 @@ SWLocale::SWLocale(const char *ifilename) { for (abbrevsCnt = 0; builtin_abbrevs[abbrevsCnt].osis[0]; abbrevsCnt++); } - confEntry = localeSource->Sections["Meta"].find("Name"); - if (confEntry != localeSource->Sections["Meta"].end()) + confEntry = localeSource->getSection("Meta").find("Name"); + if (confEntry != localeSource->getSection("Meta").end()) stdstr(&name, (*confEntry).second.c_str()); - confEntry = localeSource->Sections["Meta"].find("Description"); - if (confEntry != localeSource->Sections["Meta"].end()) + confEntry = localeSource->getSection("Meta").find("Description"); + if (confEntry != localeSource->getSection("Meta").end()) stdstr(&description, (*confEntry).second.c_str()); - confEntry = localeSource->Sections["Meta"].find("Encoding"); //Either empty (==Latin1) or UTF-8 - if (confEntry != localeSource->Sections["Meta"].end()) + confEntry = localeSource->getSection("Meta").find("Encoding"); //Either empty (==Latin1) or UTF-8 + if (confEntry != localeSource->getSection("Meta").end()) stdstr(&encoding, (*confEntry).second.c_str()); } @@ -110,8 +110,8 @@ const char *SWLocale::translate(const char *text) { if (entry == p->lookupTable.end()) { ConfigEntMap::iterator confEntry; - confEntry = localeSource->Sections["Text"].find(text); - if (confEntry == localeSource->Sections["Text"].end()) + confEntry = localeSource->getSection("Text").find(text); + if (confEntry == localeSource->getSection("Text").end()) p->lookupTable.insert(LookupMap::value_type(text, text)); else {//valid value found /* @@ -169,12 +169,12 @@ const struct abbrev *SWLocale::getBookAbbrevs(int *retSize) { for (int j = 0; builtin_abbrevs[j].osis[0]; j++) { p->mergedAbbrevs[builtin_abbrevs[j].ab] = builtin_abbrevs[j].osis; } - ConfigEntMap::iterator it = localeSource->Sections["Book Abbrevs"].begin(); - ConfigEntMap::iterator end = localeSource->Sections["Book Abbrevs"].end(); + ConfigEntMap::iterator it = localeSource->getSection("Book Abbrevs").begin(); + ConfigEntMap::iterator end = localeSource->getSection("Book Abbrevs").end(); for (; it != end; it++) { p->mergedAbbrevs[it->first.c_str()] = it->second.c_str(); } - int size = p->mergedAbbrevs.size(); + int size = (int)p->mergedAbbrevs.size(); bookAbbrevs = new struct abbrev[size + 1]; int i = 0; for (LookupMap::iterator it = p->mergedAbbrevs.begin(); it != p->mergedAbbrevs.end(); it++, i++) { diff --git a/src/mgr/swmgr.cpp b/src/mgr/swmgr.cpp index b41c411..a4413d0 100644 --- a/src/mgr/swmgr.cpp +++ b/src/mgr/swmgr.cpp @@ -2,7 +2,7 @@ * * swmgr.cpp - used to interact with an install base of sword modules * - * $Id: swmgr.cpp 3156 2014-04-17 03:50:37Z greg.hellings $ + * $Id: swmgr.cpp 3524 2017-11-07 03:08:49Z scribe $ * * Copyright 1998-2014 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -74,8 +74,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -93,7 +95,11 @@ #ifndef EXCLUDEZLIB #include "zipcomprs.h" +#endif +#ifndef EXCLUDEBZIP2 #include "bz2comprs.h" +#endif +#ifndef EXCLUDEXZ #include "xzcomprs.h" #endif @@ -126,6 +132,32 @@ const char *SWMgr::MODTYPE_LEXDICTS = "Lexicons / Dictionaries"; const char *SWMgr::MODTYPE_GENBOOKS = "Generic Books"; const char *SWMgr::MODTYPE_DAILYDEVOS = "Daily Devotional"; +namespace { + void setSystemLogLevel(SWConfig *sysConf, const char *logLevel = 0) { + SWBuf logLevelString = logLevel; + // kindof cheese. we should probably pass this in. + SWBuf logLocation = (sysConf ? "[SWORD] section of sword.conf" : "SWORD_LOGLEVEL"); + if (sysConf) { + ConfigEntMap::iterator entry; + if ((entry = sysConf->getSection("SWORD").find("LogLevel")) != sysConf->getSection("SWORD").end()) { + logLevelString = entry->second; + } + } + if (logLevelString.length()) { + int logLevel = logLevelString == "ERROR" ? SWLog::LOG_ERROR: + logLevelString == "WARN" ? SWLog::LOG_WARN: + logLevelString == "INFO" ? SWLog::LOG_INFO: + logLevelString == "TIMEDINFO" ? SWLog::LOG_TIMEDINFO: + logLevelString == "DEBUG" ? SWLog::LOG_DEBUG: + -1; + if (logLevel < 0) SWLog::getSystemLog()->logError("Invalid LogLevel found in %s: LogLevel: %s", logLocation.c_str(), logLevelString.c_str()); + else { + SWLog::getSystemLog()->setLogLevel(logLevel); + SWLog::getSystemLog()->logInformation("Setting log level from %s to %s", logLocation.c_str(), logLevelString.c_str()); + } + } + } +} void SWMgr::init() { SWOptionFilter *tmpFilter = 0; @@ -294,24 +326,11 @@ void SWMgr::init() { } -SWBuf SWMgr::getHomeDir() { - - // figure out 'home' directory for app data - SWBuf homeDir = getenv("HOME"); - if (!homeDir.length()) { - // silly windows - homeDir = getenv("APPDATA"); - } - if (homeDir.length()) { - if ((homeDir[homeDir.length()-1] != '\\') && (homeDir[homeDir.length()-1] != '/')) { - homeDir += "/"; - } - } - - return homeDir; -} - - +// TODO: because we're still calling deprecated virtual Load. Removed in 2.0 +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif void SWMgr::commonInit(SWConfig *iconfig, SWConfig *isysconfig, bool autoload, SWFilterMgr *filterMgr, bool multiMod) { init(); @@ -335,6 +354,9 @@ void SWMgr::commonInit(SWConfig *iconfig, SWConfig *isysconfig, bool autoload, S if (autoload) Load(); } +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif SWMgr::SWMgr(SWFilterMgr *filterMgr, bool multiMod) { @@ -347,6 +369,10 @@ SWMgr::SWMgr(SWConfig *iconfig, SWConfig *isysconfig, bool autoload, SWFilterMgr } +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif SWMgr::SWMgr(const char *iConfigPath, bool autoload, SWFilterMgr *filterMgr, bool multiMod, bool augmentHome) { init(); @@ -361,22 +387,23 @@ SWMgr::SWMgr(const char *iConfigPath, bool autoload, SWFilterMgr *filterMgr, boo this->augmentHome = augmentHome; path = iConfigPath; - int len = path.length(); + int len = (int)path.length(); if ((len < 1) || ((iConfigPath[len-1] != '\\') && (iConfigPath[len-1] != '/'))) path += "/"; + SWLog::getSystemLog()->logDebug("Checking at provided path: %s...", path.c_str()); if (FileMgr::existsFile(path.c_str(), "mods.conf")) { stdstr(&prefixPath, path.c_str()); path += "mods.conf"; stdstr(&configPath, path.c_str()); } - else { - if (FileMgr::existsDir(path.c_str(), "mods.d")) { - stdstr(&prefixPath, path.c_str()); - path += "mods.d"; - stdstr(&configPath, path.c_str()); - configType = 1; - } + else if (FileMgr::existsDir(path.c_str(), "mods.d")) { + SWLog::getSystemLog()->logDebug("Found mods.d/"); + stdstr(&prefixPath, path.c_str()); + path += "mods.d"; + stdstr(&configPath, path.c_str()); + configType = 1; } + else SWLog::getSystemLog()->logDebug("Config not found at provided path."); config = 0; sysConfig = 0; @@ -384,11 +411,14 @@ SWMgr::SWMgr(const char *iConfigPath, bool autoload, SWFilterMgr *filterMgr, boo if (autoload && configPath) Load(); } +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif SWMgr::~SWMgr() { - DeleteMods(); + deleteAllModules(); for (FilterList::iterator it = cleanupFilters.begin(); it != cleanupFilters.end(); it++) delete (*it); @@ -414,23 +444,33 @@ SWMgr::~SWMgr() { void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, std::list *augPaths, SWConfig **providedSysConf) { + static bool setLogLevel = false; SWBuf path; SWBuf sysConfPath; ConfigEntMap::iterator entry; ConfigEntMap::iterator lastEntry; + if (!setLogLevel) { + SWBuf envLogLevel = getenv("SWORD_LOGLEVEL"); + if (envLogLevel.length()) { + setSystemLogLevel(0, envLogLevel); + setLogLevel = true; + } + } + SWConfig *sysConf = 0; SWBuf sysConfDataPath = ""; *configType = 0; - SWBuf homeDir = getHomeDir(); + SWBuf homeDir = FileMgr::getSystemFileMgr()->getHomeDir(); // check for a sysConf passed in to us SWLog::getSystemLog()->logDebug("Checking for provided SWConfig(\"sword.conf\")..."); if (providedSysConf && *providedSysConf) { sysConf = *providedSysConf; SWLog::getSystemLog()->logDebug("found."); + if (!setLogLevel) { setSystemLogLevel(sysConf); setLogLevel = true; } } // if we haven't been given our datapath in a sysconf, we need to track it down @@ -441,9 +481,10 @@ void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, s SWLog::getSystemLog()->logDebug("Overriding any systemwide or ~/.sword/ sword.conf with one found in current directory."); sysConfPath = "./sword.conf"; sysConf = new SWConfig(sysConfPath); - if ((entry = sysConf->Sections["Install"].find("DataPath")) != sysConf->Sections["Install"].end()) { + if ((entry = sysConf->getSection("Install").find("DataPath")) != sysConf->getSection("Install").end()) { sysConfDataPath = (*entry).second; } + if (!setLogLevel) { setSystemLogLevel(sysConf); setLogLevel = true; } if (providedSysConf) { *providedSysConf = sysConf; } @@ -553,7 +594,8 @@ void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, s } if (sysConf) { - if ((entry = sysConf->Sections["Install"].find("DataPath")) != sysConf->Sections["Install"].end()) { + if (!setLogLevel) { setSystemLogLevel(sysConf); setLogLevel = true; } + if ((entry = sysConf->getSection("Install").find("DataPath")) != sysConf->getSection("Install").end()) { sysConfDataPath = (*entry).second; } if (sysConfDataPath.size()) { @@ -586,10 +628,11 @@ void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, s // do some extra processing of sysConf if we have one if (sysConf) { + if (!setLogLevel) { setSystemLogLevel(sysConf); setLogLevel = true; } if (augPaths) { augPaths->clear(); - entry = sysConf->Sections["Install"].lower_bound("AugmentPath"); - lastEntry = sysConf->Sections["Install"].upper_bound("AugmentPath"); + entry = sysConf->getSection("Install").lower_bound("AugmentPath"); + lastEntry = sysConf->getSection("Install").upper_bound("AugmentPath"); for (;entry != lastEntry; entry++) { path = entry->second; if ((entry->second.c_str()[strlen(entry->second.c_str())-1] != '\\') && (entry->second.c_str()[strlen(entry->second.c_str())-1] != '/')) @@ -638,7 +681,7 @@ void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, s SWLog::getSystemLog()->logDebug("Checking $HOME/Library/Application Support/Sword/..."); - SWBuf pathCheck = getHomeDir(); + SWBuf pathCheck = FileMgr::getSystemFileMgr()->getHomeDir(); if (pathCheck.length()) { SWLog::getSystemLog()->logDebug("found (%s).", pathCheck.c_str()); path = pathCheck; @@ -756,8 +799,8 @@ void SWMgr::augmentModules(const char *ipath, bool multiMod) { // fix config's Section names to rename modules which are available more than once // find out which sections are in both config objects // inserting all configs first is not good because that overwrites old keys and new modules would share the same config - for (SectionMap::iterator it = config->Sections.begin(); it != config->Sections.end();) { - if (saveConfig->Sections.find( (*it).first ) != saveConfig->Sections.end()) { //if the new section is already present rename it + for (SectionMap::iterator it = config->getSections().begin(); it != config->getSections().end();) { + if (saveConfig->getSections().find((*it).first) != saveConfig->getSections().end()) { //if the new section is already present rename it ConfigEntMap entMap((*it).second); SWBuf name; @@ -765,17 +808,17 @@ void SWMgr::augmentModules(const char *ipath, bool multiMod) { do { //module name already used? name.setFormatted("%s_%d", (*it).first.c_str(), i); i++; - } while (config->Sections.find(name) != config->Sections.end()); + } while (config->getSections().find(name) != config->getSections().end()); - config->Sections.insert(SectionMap::value_type(name, entMap) ); + config->getSections().insert(SectionMap::value_type(name, entMap) ); SectionMap::iterator toErase = it++; - config->Sections.erase(toErase); + config->getSections().erase(toErase); } else ++it; } } - CreateMods(multiMod); + createAllModules(multiMod); stdstr(&prefixPath, savePrefixPath); delete []savePrefixPath; @@ -791,13 +834,13 @@ void SWMgr::augmentModules(const char *ipath, bool multiMod) { /*********************************************************************** - * SWMgr::Load - loads actual modules + * SWMgr::load - loads actual modules * * RET: status - 0 = ok; -1 no config found; 1 = no modules installed * */ -signed char SWMgr::Load() { +signed char SWMgr::load() { signed char ret = 0; if (!config) { // If we weren't passed a config object at construction, find a config file @@ -819,9 +862,9 @@ signed char SWMgr::Load() { SectionMap::iterator Sectloop, Sectend; ConfigEntMap::iterator Entryloop, Entryend; - DeleteMods(); + deleteAllModules(); - for (Sectloop = config->Sections.lower_bound("Globals"), Sectend = config->Sections.upper_bound("Globals"); Sectloop != Sectend; Sectloop++) { // scan thru all 'Globals' sections + for (Sectloop = config->getSections().lower_bound("Globals"), Sectend = config->getSections().upper_bound("Globals"); Sectloop != Sectend; Sectloop++) { // scan thru all 'Globals' sections for (Entryloop = (*Sectloop).second.lower_bound("AutoInstall"), Entryend = (*Sectloop).second.upper_bound("AutoInstall"); Entryloop != Entryend; Entryloop++) // scan thru all AutoInstall entries InstallScan((*Entryloop).second.c_str()); // Scan AutoInstall entry directory for new modules and install } @@ -830,16 +873,16 @@ signed char SWMgr::Load() { config = myconfig = 0; loadConfigDir(configPath); } - else config->Load(); + else config->load(); - CreateMods(mgrModeMultiMod); + createAllModules(mgrModeMultiMod); for (std::list::iterator pathIt = augPaths.begin(); pathIt != augPaths.end(); pathIt++) { augmentModules(pathIt->c_str(), mgrModeMultiMod); } if (augmentHome) { // augment config with ~/.sword/mods.d if it exists --------------------- - SWBuf homeDir = getHomeDir(); + SWBuf homeDir = FileMgr::getSystemFileMgr()->getHomeDir(); if (homeDir.length() && configType != 2) { // 2 = user only SWBuf path = homeDir; path += ".sword/"; @@ -850,7 +893,7 @@ signed char SWMgr::Load() { } } // ------------------------------------------------------------------------- - if (!Modules.size()) // config exists, but no modules + if (!getModules().size()) // config exists, but no modules ret = 1; } @@ -912,11 +955,15 @@ SWModule *SWMgr::createModule(const char *name, const char *driver, ConfigEntMap else markup = FMT_GBF; - if (!stricmp(encoding.c_str(), "SCSU")) - enc = ENC_SCSU; - else if (!stricmp(encoding.c_str(), "UTF-8")) { + if (!stricmp(encoding.c_str(), "UTF-8")) { enc = ENC_UTF8; } + else if (!stricmp(encoding.c_str(), "SCSU")) { + enc = ENC_SCSU; + } + else if (!stricmp(encoding.c_str(), "UTF-16")) { + enc = ENC_UTF16; + } else enc = ENC_LATIN1; if ((entry = section.find("Direction")) == section.end()) { @@ -932,7 +979,7 @@ SWModule *SWMgr::createModule(const char *name, const char *driver, ConfigEntMap direction = DIRECTION_LTR; } - if ((!stricmp(driver, "zText")) || (!stricmp(driver, "zCom"))) { + if ((!stricmp(driver, "zText")) || (!stricmp(driver, "zCom")) || (!stricmp(driver, "zText4")) || (!stricmp(driver, "zCom4"))) { SWCompress *compress = 0; int blockType = CHAPTERBLOCKS; misc1 = ((entry = section.find("BlockType")) != section.end()) ? (*entry).second : (SWBuf)"CHAPTER"; @@ -948,10 +995,14 @@ SWModule *SWMgr::createModule(const char *name, const char *driver, ConfigEntMap if (!stricmp(misc1.c_str(), "ZIP")) compress = new ZipCompress(); else - if (!stricmp(misc1.c_str(), "BZIP2_UNSUPPORTED")) +#endif +#ifndef EXCLUDEBZIP2 + if (!stricmp(misc1.c_str(), "BZIP2")) compress = new Bzip2Compress(); else - if (!stricmp(misc1.c_str(), "XZ_UNSUPPORTED")) +#endif +#ifndef EXCLUDEXZ + if (!stricmp(misc1.c_str(), "XZ")) compress = new XzCompress(); else #endif @@ -961,7 +1012,12 @@ SWModule *SWMgr::createModule(const char *name, const char *driver, ConfigEntMap if (compress) { if (!stricmp(driver, "zText")) newmod = new zText(datapath.c_str(), name, description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str(), versification); - else newmod = new zCom(datapath.c_str(), name, description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str(), versification); + else if (!stricmp(driver, "zText4")) + newmod = new zText4(datapath.c_str(), name, description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str(), versification); + else if (!stricmp(driver, "zCom4")) + newmod = new zCom4(datapath.c_str(), name, description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str(), versification); + else + newmod = new zCom(datapath.c_str(), name, description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str(), versification); } } @@ -1024,6 +1080,16 @@ SWModule *SWMgr::createModule(const char *name, const char *driver, ConfigEntMap if (!stricmp(misc1.c_str(), "ZIP")) compress = new ZipCompress(); else +#endif +#ifndef EXCLUDEBZIP2 + if (!stricmp(misc1.c_str(), "BZIP2")) + compress = new Bzip2Compress(); + else +#endif +#ifndef EXCLUDEXZ + if (!stricmp(misc1.c_str(), "XZ")) + compress = new XzCompress(); + else #endif if (!stricmp(misc1.c_str(), "LZSS")) compress = new LZSSCompress(); @@ -1042,7 +1108,7 @@ SWModule *SWMgr::createModule(const char *name, const char *driver, ConfigEntMap if (pos == 1) { SWBuf &dp = section["AbsoluteDataPath"]; - for (int i = dp.length() - 1; i; i--) { + for (int i = (int)dp.length() - 1; i; i--) { if (dp[i] == '/') { dp.setSize(i); break; @@ -1071,7 +1137,10 @@ SWModule *SWMgr::createModule(const char *name, const char *driver, ConfigEntMap } -void SWMgr::AddGlobalOptions(SWModule *module, ConfigEntMap §ion, ConfigEntMap::iterator start, ConfigEntMap::iterator end) { +void SWMgr::addGlobalOptionFilters(SWModule *module, ConfigEntMap §ion) { + + ConfigEntMap::iterator start = section.lower_bound("GlobalOptionFilter"); + ConfigEntMap::iterator end = section.upper_bound("GlobalOptionFilter"); for (;start != end; ++start) { OptionFilterMap::iterator it; @@ -1120,8 +1189,7 @@ void SWMgr::AddGlobalOptions(SWModule *module, ConfigEntMap §ion, ConfigEntM } -char SWMgr::filterText(const char *filterName, SWBuf &text, const SWKey *key, const SWModule *module) -{ +char SWMgr::filterText(const char *filterName, SWBuf &text, const SWKey *key, const SWModule *module) { char retVal = -1; // why didn't we use find here? for (OptionFilterMap::iterator it = optionFilters.begin(); it != optionFilters.end(); it++) { @@ -1144,8 +1212,11 @@ char SWMgr::filterText(const char *filterName, SWBuf &text, const SWKey *key, co } -void SWMgr::AddLocalOptions(SWModule *module, ConfigEntMap §ion, ConfigEntMap::iterator start, ConfigEntMap::iterator end) -{ +void SWMgr::addLocalOptionFilters(SWModule *module, ConfigEntMap §ion) { + + ConfigEntMap::iterator start = section.lower_bound("LocalOptionFilter"); + ConfigEntMap::iterator end = section.upper_bound("LocalOptionFilter"); + for (;start != end; start++) { OptionFilterMap::iterator it; it = optionFilters.find((*start).second); @@ -1160,8 +1231,11 @@ void SWMgr::AddLocalOptions(SWModule *module, ConfigEntMap §ion, ConfigEntMa // manually specified StripFilters for special cases, like Papyri marks and such -void SWMgr::AddStripFilters(SWModule *module, ConfigEntMap §ion, ConfigEntMap::iterator start, ConfigEntMap::iterator end) -{ +void SWMgr::addLocalStripFilters(SWModule *module, ConfigEntMap §ion) { + + ConfigEntMap::iterator start = section.lower_bound("LocalStripFilter"); + ConfigEntMap::iterator end = section.upper_bound("LocalStripFilter"); + for (;start != end; start++) { OptionFilterMap::iterator it; it = optionFilters.find((*start).second); @@ -1172,7 +1246,7 @@ void SWMgr::AddStripFilters(SWModule *module, ConfigEntMap §ion, ConfigEntMa } -void SWMgr::AddRawFilters(SWModule *module, ConfigEntMap §ion) { +void SWMgr::addRawFilters(SWModule *module, ConfigEntMap §ion) { SWBuf sourceformat, cipherKey; ConfigEntMap::iterator entry; @@ -1189,13 +1263,13 @@ void SWMgr::AddRawFilters(SWModule *module, ConfigEntMap §ion) { } -void SWMgr::AddEncodingFilters(SWModule *module, ConfigEntMap §ion) { +void SWMgr::addEncodingFilters(SWModule *module, ConfigEntMap §ion) { if (filterMgr) filterMgr->AddEncodingFilters(module, section); } -void SWMgr::AddRenderFilters(SWModule *module, ConfigEntMap §ion) { +void SWMgr::addRenderFilters(SWModule *module, ConfigEntMap §ion) { SWBuf sourceformat; ConfigEntMap::iterator entry; @@ -1221,7 +1295,7 @@ void SWMgr::AddRenderFilters(SWModule *module, ConfigEntMap §ion) { } -void SWMgr::AddStripFilters(SWModule *module, ConfigEntMap §ion) +void SWMgr::addStripFilters(SWModule *module, ConfigEntMap §ion) { SWBuf sourceformat; ConfigEntMap::iterator entry; @@ -1254,81 +1328,6 @@ void SWMgr::AddStripFilters(SWModule *module, ConfigEntMap §ion) } -void SWMgr::CreateMods(bool multiMod) { - SectionMap::iterator it; - ConfigEntMap::iterator start; - ConfigEntMap::iterator end; - ConfigEntMap::iterator entry; - SWModule *newmod; - SWBuf driver, misc1; - for (it = config->Sections.begin(); it != config->Sections.end(); it++) { - ConfigEntMap §ion = (*it).second; - newmod = 0; - - driver = ((entry = section.find("ModDrv")) != section.end()) ? (*entry).second : (SWBuf)""; - if (driver.length()) { - newmod = createModule((*it).first, driver, section); - if (newmod) { - // Filters to add for this module and globally announce as an option to the user - // e.g. translit, strongs, redletterwords, etc, so users can turn these on and off globally - start = section.lower_bound("GlobalOptionFilter"); - end = section.upper_bound("GlobalOptionFilter"); - AddGlobalOptions(newmod, section, start, end); - - // Only add the option to the module, don't announce it's availability - // These are useful for like: filters that parse special entryAttribs in a text - // or whatever you might want to happen on entry lookup - start = section.lower_bound("LocalOptionFilter"); - end = section.upper_bound("LocalOptionFilter"); - AddLocalOptions(newmod, section, start, end); - - //STRIP FILTERS - - // add all basic ones for for the modtype - AddStripFilters(newmod, section); - - // Any special processing for this module when searching: - // e.g. for papyri, removed all [](). notation - start = section.lower_bound("LocalStripFilter"); - end = section.upper_bound("LocalStripFilter"); - AddStripFilters(newmod, section, start, end); - - AddRawFilters(newmod, section); - AddRenderFilters(newmod, section); - AddEncodingFilters(newmod, section); - - SWModule *oldmod = Modules[newmod->getName()]; - if (oldmod) { - delete oldmod; - } - - Modules[newmod->getName()] = newmod; - } - } - } -} - - -void SWMgr::DeleteMods() { - - ModMap::iterator it; - - for (it = Modules.begin(); it != Modules.end(); it++) - delete (*it).second; - - Modules.clear(); -} - - -void SWMgr::deleteModule(const char *modName) { - ModMap::iterator it = Modules.find(modName); - if (it != Modules.end()) { - delete (*it).second; - Modules.erase(it); - } -} - - void SWMgr::InstallScan(const char *dirname) { DIR *dir; @@ -1361,8 +1360,8 @@ void SWMgr::InstallScan(const char *dirname) // mods.conf else { if (!conffd) { - conffd = FileMgr::getSystemFileMgr()->open(config->filename.c_str(), FileMgr::WRONLY|FileMgr::APPEND); - if (conffd > 0) + conffd = FileMgr::getSystemFileMgr()->open(config->getFileName().c_str(), FileMgr::WRONLY|FileMgr::APPEND); + if (conffd && conffd->getFd() >= 0) conffd->seek(0L, SEEK_END); else { FileMgr::getSystemFileMgr()->close(conffd); @@ -1455,6 +1454,91 @@ StringList SWMgr::getGlobalOptionValues(const char *option) return options; } +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + +// TODO: use deprecated public 'Modules' property for now until we remove deprecation +// and store in private property +// also old deprecated virtuals so client overrides still are called + +void SWMgr::createAllModules(bool multiMod) { + SectionMap::iterator it; + ConfigEntMap::iterator entry; + SWModule *newmod; + SWBuf driver, misc1; + for (it = config->getSections().begin(); it != config->getSections().end(); it++) { + ConfigEntMap §ion = (*it).second; + newmod = 0; + + driver = ((entry = section.find("ModDrv")) != section.end()) ? (*entry).second : (SWBuf)""; + if (driver.length()) { + newmod = createModule((*it).first, driver, section); + if (newmod) { + // Filters to add for this module and globally announce as an option to the user + // e.g. translit, strongs, redletterwords, etc, so users can turn these on and off globally + // TODO: addGlobalOptionFilters(newmod, section); + AddGlobalOptions(newmod, section, section.lower_bound("GlobalOptionFilter"), section.upper_bound("GlobalOptionFilter")); + + // Only add the option to the module, don't announce it's availability + // These are useful for like: filters that parse special entryAttribs in a text + // or whatever you might want to happen on entry lookup + // TODO: addLocalOptionFilters(newmod, section); + AddLocalOptions(newmod, section, section.lower_bound("LocalOptionFilter"), section.upper_bound("LocalOptionFilter")); + + //STRIP FILTERS + + // add all basic strip filters for for the modtype + // TODO: addStripFilters(newmod, section); + AddStripFilters(newmod, section); + + // Any module-specific processing specified in module config + // as entries LocalStripFilter= + // e.g. for papyri, removed all [](). notation + // TODO: addLocalStripFilters(newmod, section); + AddStripFilters(newmod, section, section.lower_bound("LocalStripFilter"), section.upper_bound("LocalStripFilter")); + + // TODO: addRawFilters(newmod, section); + AddRawFilters(newmod, section); + // TODO: addRenderFilters(newmod, section); + AddRenderFilters(newmod, section); + // TODO: addEncodingFilters(newmod, section); + AddEncodingFilters(newmod, section); + + // place our module in module container, removing first if one + // already exists by our same name + SWModule *oldmod = getModule(newmod->getName()); + if (oldmod) { + delete oldmod; + } + + Modules[newmod->getName()] = newmod; + } + } + } +} + + +void SWMgr::deleteAllModules() { + + ModMap::iterator it; + + for (it = getModules().begin(); it != getModules().end(); ++it) { + delete (*it).second; + } + + Modules.clear(); +} + + +void SWMgr::deleteModule(const char *modName) { + ModMap::iterator it = Modules.find(modName); + if (it != Modules.end()) { + delete (*it).second; + Modules.erase(it); + } +} signed char SWMgr::setCipherKey(const char *modName, const char *key) { FilterMap::iterator it; @@ -1481,5 +1565,13 @@ signed char SWMgr::setCipherKey(const char *modName, const char *key) { } +ModMap &SWMgr::getModules() { return Modules; } + +SWBuf SWMgr::getHomeDir() { return FileMgr::getSystemFileMgr()->getHomeDir(); } + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + SWORD_NAMESPACE_END diff --git a/src/mgr/versificationmgr.cpp b/src/mgr/versificationmgr.cpp index 7972488..027889f 100644 --- a/src/mgr/versificationmgr.cpp +++ b/src/mgr/versificationmgr.cpp @@ -3,7 +3,7 @@ * versificationmgr.cpp - implementation of class VersificationMgr used * for managing versification systems * - * $Id: versificationmgr.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: versificationmgr.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2008-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -45,6 +45,9 @@ #include // Catholic2 v11n system (16 chapter Esther) #include // General LXX v11n system (includes GNT, as used in Orthodox Bibles) #include // Orthodox v11n system as used in Orthodox Bibles +#include // French v11n system as used by Segond Bibles and its derivatives +#include // French v11n system +#include // French v11n system based on John Darby's French translation using std::vector; using std::map; @@ -62,17 +65,20 @@ VersificationMgr *VersificationMgr::getSystemVersificationMgr() { systemVersificationMgr->registerVersificationSystem("Leningrad", otbooks_leningrad, ntbooks_null, vm_leningrad); systemVersificationMgr->registerVersificationSystem("MT", otbooks_mt, ntbooks_null, vm_mt); systemVersificationMgr->registerVersificationSystem("KJVA", otbooks_kjva, ntbooks, vm_kjva); - systemVersificationMgr->registerVersificationSystem("NRSV", otbooks, ntbooks, vm_nrsv); + systemVersificationMgr->registerVersificationSystem("NRSV", otbooks, ntbooks, vm_nrsv, mappings_nrsv); systemVersificationMgr->registerVersificationSystem("NRSVA", otbooks_nrsva, ntbooks, vm_nrsva); - systemVersificationMgr->registerVersificationSystem("Synodal", otbooks_synodal, ntbooks_synodal, vm_synodal); + systemVersificationMgr->registerVersificationSystem("Synodal", otbooks_synodal, ntbooks_synodal, vm_synodal, mappings_synodal); systemVersificationMgr->registerVersificationSystem("SynodalProt", otbooks_synodalProt, ntbooks_synodal, vm_synodalProt); - systemVersificationMgr->registerVersificationSystem("Vulg", otbooks_vulg, ntbooks_vulg, vm_vulg); + systemVersificationMgr->registerVersificationSystem("Vulg", otbooks_vulg, ntbooks_vulg, vm_vulg, mappings_vulg); systemVersificationMgr->registerVersificationSystem("German", otbooks_german, ntbooks, vm_german); systemVersificationMgr->registerVersificationSystem("Luther", otbooks_luther, ntbooks_luther, vm_luther); systemVersificationMgr->registerVersificationSystem("Catholic", otbooks_catholic, ntbooks, vm_catholic); systemVersificationMgr->registerVersificationSystem("Catholic2", otbooks_catholic2, ntbooks, vm_catholic2); systemVersificationMgr->registerVersificationSystem("LXX", otbooks_lxx, ntbooks, vm_lxx); systemVersificationMgr->registerVersificationSystem("Orthodox", otbooks_orthodox, ntbooks, vm_orthodox); + systemVersificationMgr->registerVersificationSystem("Calvin", otbooks, ntbooks, vm_calvin, mappings_calvin); + systemVersificationMgr->registerVersificationSystem("DarbyFr", otbooks, ntbooks, vm_darbyfr, mappings_darbyfr); + systemVersificationMgr->registerVersificationSystem("Segond", otbooks, ntbooks, vm_segond, mappings_segond); } return systemVersificationMgr; } @@ -83,6 +89,19 @@ public: /** Array[chapmax] of maximum verses in chapters */ vector books; map osisLookup; + /** 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") + + TODO what if book name in one v11n differs from cannon + special section in mapping for book transformation + */ + typedef vector mapping; + vector mappings; + vector mappingsExtraBooks; Private() { } @@ -115,7 +134,8 @@ public: } VersificationMgr::Book::Private &operator =(const VersificationMgr::Book::Private &other) { verseMax.clear(); - verseMax = other.verseMax; + int s = (int)other.verseMax.size(); + if (s) verseMax = other.verseMax; offsetPrecomputed = other.offsetPrecomputed; return *this; } @@ -179,7 +199,7 @@ int VersificationMgr::System::getBookNumberByOSISName(const char *bookName) cons } -void VersificationMgr::System::loadFromSBook(const sbook *ot, const sbook *nt, int *chMax) { +void VersificationMgr::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 @@ -188,7 +208,7 @@ void VersificationMgr::System::loadFromSBook(const sbook *ot, const sbook *nt, i p->books.push_back(Book(ot->name, ot->osis, ot->prefAbbrev, ot->chapmax)); offset++; // book heading Book &b = p->books[p->books.size()-1]; - p->osisLookup[b.getOSISName()] = p->books.size(); + p->osisLookup[b.getOSISName()] = (int)p->books.size(); for (int i = 0; i < ot->chapmax; i++) { b.p->verseMax.push_back(chMax[chap]); offset++; // chapter heading @@ -206,7 +226,7 @@ void VersificationMgr::System::loadFromSBook(const sbook *ot, const sbook *nt, i p->books.push_back(Book(nt->name, nt->osis, nt->prefAbbrev, nt->chapmax)); offset++; // book heading Book &b = p->books[p->books.size()-1]; - p->osisLookup[b.getOSISName()] = p->books.size(); + p->osisLookup[b.getOSISName()] = (int)p->books.size(); for (int i = 0; i < nt->chapmax; i++) { b.p->verseMax.push_back(chMax[chap]); offset++; // chapter heading @@ -219,6 +239,23 @@ void VersificationMgr::System::loadFromSBook(const sbook *ot, const sbook *nt, i BMAX[1] = book; // TODO: build offset speed array + + // parse mappings + if (mappings != NULL) { + const unsigned char *m=mappings; + for (; *m != 0; m += strlen((const char*)m)+1) { + p->mappingsExtraBooks.push_back((const char*)m); + } + p->mappings.resize(p->books.size()+p->mappingsExtraBooks.size()); + + for (++m; *m != 0; m += 7) { + p->mappings[m[0]-1].push_back(m); + if (*m > p->books.size()) { + p->mappings[m[7]-1].push_back(m); + m += 1; + } + } + } } @@ -255,7 +292,7 @@ int VersificationMgr::Book::getVerseMax(int chapter) const { int VersificationMgr::System::getBookCount() const { - return (p ? p->books.size() : 0); + return (int)(p ? p->books.size() : 0); } @@ -372,10 +409,10 @@ const VersificationMgr::System *VersificationMgr::getVersificationSystem(const c } -void VersificationMgr::registerVersificationSystem(const char *name, const sbook *ot, const sbook *nt, int *chMax) { +void VersificationMgr::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); } @@ -391,6 +428,138 @@ const StringList VersificationMgr::getVersificationSystems() const { return retVal; } +void VersificationMgr::System::translateVerse(const System *dstSys, const char **book, int *chapter, int *verse, int *verse_end) const { + SWLog::getSystemLog()->logDebug("translate verse from %s to %s: %s.%i.%i-%i\n",getName(), dstSys->getName(), *book, *chapter, *verse, *verse_end); + + if (!strcmp(getName(),"KJVA") || !strcmp(getName(),"KJV")) { + if (!strcmp(dstSys->getName(),"KJVA") || !strcmp(dstSys->getName(),"KJV")) + return; + // reversed mapping + SWLog::getSystemLog()->logDebug("Perform reversed mapping.\n"); + int b = dstSys->getBookNumberByOSISName(*book)-1; + + SWLog::getSystemLog()->logDebug("\tgetBookNumberByOSISName %i %s.\n", b, *book); + + if (b < 0) { + SWLog::getSystemLog()->logDebug("\tmappingsExtraBooks.size() %i.\n", dstSys->p->mappingsExtraBooks.size()); + for (int i=0; i<(int)dstSys->p->mappingsExtraBooks.size(); ++i) { + SWLog::getSystemLog()->logDebug("\t%s %s.\n", *book, dstSys->p->mappingsExtraBooks[i]); + if (!strcmp(*book, dstSys->p->mappingsExtraBooks[i])) { + b = (int)p->books.size()+i-2; + break; + } + } + } + + SWLog::getSystemLog()->logDebug("\tb %i.\n", b); + + if (b >= (int)dstSys->p->mappings.size() || b < 0) { + SWLog::getSystemLog()->logDebug("no modification"); + return; + } + + const unsigned char *a = NULL; + + // reversed mapping should use forward search for item + for (unsigned int i=0; ip->mappings[b].size(); ++i) { + const unsigned char *m = dstSys->p->mappings[b][i]; + if (m[4] == *chapter && m[5] <= *verse) { + SWLog::getSystemLog()->logDebug("found mapping %i %i %i %i %i %i\n",m[1],m[2],m[3],m[4],m[5],m[6]); + if (m[5] == *verse || (m[6] >= *verse && m[5] <= *verse)) { + // inside of any mapping range + *chapter = m[1]; + *verse = m[2]; + *verse_end = m[3]; + if (*m >= dstSys->p->books.size()) { + SWLog::getSystemLog()->logWarning("map to extra books, possible bug source\n"); + *book = dstSys->getBook(m[7]-1)->getOSISName(); + } + return; + } + // destination mapping can have duplicate items, use the last (by using <=) + if (a == NULL || (a[5]>a[6]?a[5]:a[6]) <= (m[5]>m[6]?m[5]:m[6])) + a = m; + } + } + if (a != NULL) { + SWLog::getSystemLog()->logDebug("set appropriate: %i %i %i %i %i %i\n",a[1],a[2],a[3],a[4],a[5],a[6]); + (*chapter) = a[1]; + // shift verse + const int d = (a[3]>a[2]?a[3]:a[2])-(a[6]>a[5]?a[6]:a[5]); + if (*verse < *verse_end) + *verse_end += d; + else + *verse_end = (*verse) + d; + *verse += d; + if (*a > dstSys->p->books.size()) { + SWLog::getSystemLog()->logDebug("appropriate: %i %i %i %i %i %i %i %i\n",a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]); + SWLog::getSystemLog()->logDebug("book: %s\n", dstSys->getBook(a[7]-1)->getOSISName()); + *book = dstSys->getBook(a[7]-1)->getOSISName(); + } + return; + } + SWLog::getSystemLog()->logDebug("There is no mapping.\n"); + } + else if (strcmp(dstSys->getName(),"KJVA") && strcmp(dstSys->getName(),"KJV")) { + const System *kjva = getSystemVersificationMgr()->getVersificationSystem("KJVA"); + const int src_verse = *verse; + + translateVerse(kjva, book, chapter, verse, verse_end); + + int interm_verse = *verse, interm_range = *verse_end, interm_chapter = *chapter; + const char *interm_book = *book; + + kjva->translateVerse(dstSys, book, chapter, verse, verse_end); + + // contraction->expansion fix + if (verse < verse_end && !(interm_verse < interm_range)) { + kjva->translateVerse(this, &interm_book, &interm_chapter, &interm_verse, &interm_range); + if (interm_verse < interm_range) { + *verse += src_verse - interm_verse; + if (*verse > *verse_end) + *verse = *verse_end; + else + *verse_end = *verse; + } + } + } + else { + SWLog::getSystemLog()->logDebug("Perform forward mapping.\n"); + const int b = getBookNumberByOSISName(*book)-1; + if (b >= (int)p->mappings.size()) + return; + // forward mapping should use reversed search for item + for (int i = (int)p->mappings[b].size()-1; i>=0; --i) { + const unsigned char *m = p->mappings[b][i]; + if (m[1] < *chapter) { + SWLog::getSystemLog()->logWarning("There is no mapping for this chapter.\n"); + return; + } + if (m[1] == *chapter && m[2] <= *verse) { + SWLog::getSystemLog()->logDebug("found mapping %i %i %i %i %i %i\n",m[1],m[2],m[3],m[4],m[5],m[6]); + if (m[2] == *verse || (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]?m[6]:m[5])-(m[3]>m[2]?m[3]:m[2]); + if (*verse < *verse_end) + *verse_end += d; + else + *verse_end = (*verse) + d; + *verse += d; + } + if (*m > p->books.size()) + *book = p->mappingsExtraBooks[m[0]-p->books.size()-1]; + return; + } + } + SWLog::getSystemLog()->logDebug("No mapping.\n"); + } +} SWORD_NAMESPACE_END diff --git a/src/modules/comments/Makefile.am b/src/modules/comments/Makefile.am index 7139cf8..8ca9fc9 100644 --- a/src/modules/comments/Makefile.am +++ b/src/modules/comments/Makefile.am @@ -6,4 +6,5 @@ include ../src/modules/comments/rawcom/Makefile.am include ../src/modules/comments/rawcom4/Makefile.am include ../src/modules/comments/rawfiles/Makefile.am include ../src/modules/comments/zcom/Makefile.am +include ../src/modules/comments/zcom4/Makefile.am include ../src/modules/comments/hrefcom/Makefile.am diff --git a/src/modules/comments/rawcom4/Makefile b/src/modules/comments/rawcom4/Makefile index a08e07e..35d6648 100644 --- a/src/modules/comments/rawcom4/Makefile +++ b/src/modules/comments/rawcom4/Makefile @@ -1,5 +1,5 @@ - -root := ../../../.. - -all: - make -C ${root} + +root := ../../../.. + +all: + make -C ${root} diff --git a/src/modules/comments/rawcom4/rawcom4.cpp b/src/modules/comments/rawcom4/rawcom4.cpp index 7cfc603..f432712 100644 --- a/src/modules/comments/rawcom4/rawcom4.cpp +++ b/src/modules/comments/rawcom4/rawcom4.cpp @@ -4,7 +4,7 @@ * commentary files: * ot and nt using indexs ??.bks ??.cps ??.vss * - * $Id: rawcom4.cpp 2833 2013-06-29 06:40:28Z chrislit $ + * $Id: rawcom4.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 2007-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -72,7 +72,7 @@ SWBuf &RawCom4::getRawEntryBuf() const { VerseKey *key = &getVerseKey(); findOffset(key->getTestament(), key->getTestamentIndex(), &start, &size); - entrySize = size; // support getEntrySize call + entrySize = (int)size; // support getEntrySize call entryBuf = ""; readText(key->getTestament(), start, size, entryBuf); diff --git a/src/modules/comments/zcom/zcom.cpp b/src/modules/comments/zcom/zcom.cpp index 839baf5..b6d18b2 100644 --- a/src/modules/comments/zcom/zcom.cpp +++ b/src/modules/comments/zcom/zcom.cpp @@ -3,7 +3,7 @@ * zcom.cpp - code for class 'zCom'- a module that reads raw commentary * files * - * $Id: zcom.cpp 3156 2014-04-17 03:50:37Z greg.hellings $ + * $Id: zcom.cpp 3073 2014-03-05 00:27:52Z scribe $ * * Copyright 1996-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society diff --git a/src/modules/comments/zcom4/Makefile b/src/modules/comments/zcom4/Makefile new file mode 100644 index 0000000..35d6648 --- /dev/null +++ b/src/modules/comments/zcom4/Makefile @@ -0,0 +1,5 @@ + +root := ../../../.. + +all: + make -C ${root} diff --git a/src/modules/comments/zcom4/Makefile.am b/src/modules/comments/zcom4/Makefile.am new file mode 100644 index 0000000..6ae887f --- /dev/null +++ b/src/modules/comments/zcom4/Makefile.am @@ -0,0 +1,2 @@ +zcom4dir = $(top_srcdir)/src/modules/comments/zcom4 +libsword_la_SOURCES += $(zcom4dir)/zcom4.cpp diff --git a/src/modules/comments/zcom4/zcom4.cpp b/src/modules/comments/zcom4/zcom4.cpp new file mode 100644 index 0000000..534582a --- /dev/null +++ b/src/modules/comments/zcom4/zcom4.cpp @@ -0,0 +1,220 @@ +/****************************************************************************** + * + * zcom4.cpp - code for class 'zCom4'- a module that reads compressed + * commentary files + * + * $Id: zcom4.cpp 3141 2014-03-19 01:24:04Z chrislit $ + * + * Copyright 1996-2014 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 +#include +#include + +#include +#include +#include +#include +#include + +SWORD_NAMESPACE_START + +/****************************************************************************** + * zCom4 Constructor - Initializes data for instance of zCom4 + * + * ENT: ipath - path to data files + * iname - Internal name for module + * idesc - Name to display to user for module + * iblockType - verse, chapter, book, etc. of index chunks + * icomp - Compressor object + * idisp - Display object to use for displaying + */ + +zCom4::zCom4(const char *ipath, const char *iname, const char *idesc, int iblockType, SWCompress *icomp, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char *ilang, const char *versification) : zVerse4(ipath, -1, iblockType, icomp), SWCom(iname, idesc, idisp, enc, dir, mark, ilang, versification)/*, SWCompress()*/ +{ + blockType = iblockType; + lastWriteKey = 0; +} + +/****************************************************************************** + * zCom4 Destructor - Cleans up instance of zCom4 + */ + +zCom4::~zCom4() { + flushCache(); + + if (lastWriteKey) + delete lastWriteKey; +} + + +bool zCom4::isWritable() const { + return ((idxfp[0]->getFd() > 0) && ((idxfp[0]->mode & FileMgr::RDWR) == FileMgr::RDWR)); +} + + +/****************************************************************************** + * zCom4::getRawEntry - Returns the current verse buffer + * + * RET: buffer with verse + */ + +SWBuf &zCom4::getRawEntryBuf() const { + long start = 0; + unsigned long size = 0; + unsigned long buffnum = 0; + VerseKey &key = getVerseKey(); + + findOffset(key.getTestament(), key.getTestamentIndex(), &start, &size, &buffnum); + entrySize = size; // support getEntrySize call + + entryBuf = ""; + + zReadText(key.getTestament(), start, size, buffnum, entryBuf); + rawFilter(entryBuf, &key); + +// if (!isUnicode()) + prepText(entryBuf); + + return entryBuf; +} + + +bool zCom4::sameBlock(VerseKey *k1, VerseKey *k2) { + if (k1->getTestament() != k2->getTestament()) + return false; + + switch (blockType) { + case VERSEBLOCKS: + if (k1->getVerse() != k2->getVerse()) + return false; + case CHAPTERBLOCKS: + if (k1->getChapter() != k2->getChapter()) + return false; + case BOOKBLOCKS: + if (k1->getBook() != k2->getBook()) + return false; + } + return true; +} + +void zCom4::setEntry(const char *inbuf, long len) { + VerseKey *key = &getVerseKey(); + + // see if we've jumped across blocks since last write + if (lastWriteKey) { + if (!sameBlock(lastWriteKey, key)) { + flushCache(); + } + delete lastWriteKey; + } + + doSetText(key->getTestament(), key->getTestamentIndex(), inbuf, len); + + lastWriteKey = (VerseKey *)key->clone(); // must delete +} + + +void zCom4::linkEntry(const SWKey *inkey) { + VerseKey *destkey = &getVerseKey(); + const VerseKey *srckey = &getVerseKey(inkey); + + doLinkEntry(destkey->getTestament(), destkey->getTestamentIndex(), srckey->getTestamentIndex()); + + if (inkey != srckey) // free our key if we created a VerseKey + delete srckey; +} + +/****************************************************************************** + * zCom4::deleteEntry - deletes this entry + * + * RET: *this + */ + +void zCom4::deleteEntry() { + + VerseKey *key = &getVerseKey(); + doSetText(key->getTestament(), key->getTestamentIndex(), ""); +} + + +/****************************************************************************** + * zCom4::increment - Increments module key a number of entries + * + * ENT: increment - Number of entries to jump forward + * + * RET: *this + */ + +void zCom4::increment(int steps) { + long start; + unsigned long size; + unsigned long buffnum; + VerseKey *tmpkey = &getVerseKey(); + + findOffset(tmpkey->getTestament(), tmpkey->getTestamentIndex(), &start, &size, &buffnum); + + SWKey lastgood = *tmpkey; + while (steps) { + long laststart = start; + unsigned long lastsize = size; + SWKey lasttry = *tmpkey; + (steps > 0) ? ++(*key) : --(*key); + tmpkey = &getVerseKey(); + + if ((error = key->popError())) { + *key = lastgood; + break; + } + long index = tmpkey->getTestamentIndex(); + findOffset(tmpkey->getTestament(), index, &start, &size, &buffnum); + if ( + (((laststart != start) || (lastsize != size)) // we're a different entry +// && (start > 0) + && (size)) // and we actually have a size + ||(!skipConsecutiveLinks)) { // or we don't want to skip consecutive links + steps += (steps < 0) ? 1 : -1; + lastgood = *tmpkey; + } + } + error = (error) ? KEYERR_OUTOFBOUNDS : 0; +} + +bool zCom4::isLinked(const SWKey *k1, const SWKey *k2) const { + long start1, start2; + unsigned long size1, size2; + unsigned long buffnum1, buffnum2; + VerseKey *vk1 = &getVerseKey(k1); + VerseKey *vk2 = &getVerseKey(k2); + if (vk1->getTestament() != vk2->getTestament()) return false; + + findOffset(vk1->getTestament(), vk1->getTestamentIndex(), &start1, &size1, &buffnum1); + findOffset(vk2->getTestament(), vk2->getTestamentIndex(), &start2, &size2, &buffnum2); + return start1 == start2 && buffnum1 == buffnum2; +} + +bool zCom4::hasEntry(const SWKey *k) const { + long start; + unsigned long size; + unsigned long buffnum; + VerseKey *vk = &getVerseKey(k); + + findOffset(vk->getTestament(), vk->getTestamentIndex(), &start, &size, &buffnum); + return size; +} + +SWORD_NAMESPACE_END diff --git a/src/modules/common/Makefile.am b/src/modules/common/Makefile.am index 90a3f98..0bca03e 100644 --- a/src/modules/common/Makefile.am +++ b/src/modules/common/Makefile.am @@ -6,18 +6,22 @@ libsword_la_SOURCES += $(commondir)/swcomprs.cpp libsword_la_SOURCES += $(commondir)/lzsscomprs.cpp if HAVE_LIBZ -SWZLIB = $(commondir)/zipcomprs.cpp -SWZLIB += $(commondir)/bz2comprs.cpp -SWZLIB += $(commondir)/xzcomprs.cpp -else -SWZLIB = +libsword_la_SOURCES += $(commondir)/zipcomprs.cpp endif -libsword_la_SOURCES += $(SWZLIB) + +if HAVE_BZIP2 +libsword_la_SOURCES += $(commondir)/bz2comprs.cpp +endif + +if HAVE_XZ +libsword_la_SOURCES += $(commondir)/xzcomprs.cpp +endif + libsword_la_SOURCES += $(commondir)/rawverse.cpp libsword_la_SOURCES += $(commondir)/rawverse4.cpp libsword_la_SOURCES += $(commondir)/swcipher.cpp libsword_la_SOURCES += $(commondir)/zverse.cpp +libsword_la_SOURCES += $(commondir)/zverse4.cpp libsword_la_SOURCES += $(commondir)/zstr.cpp libsword_la_SOURCES += $(commondir)/entriesblk.cpp libsword_la_SOURCES += $(commondir)/sapphire.cpp - diff --git a/src/modules/common/bz2comprs.cpp b/src/modules/common/bz2comprs.cpp index 7863e98..6b9374e 100644 --- a/src/modules/common/bz2comprs.cpp +++ b/src/modules/common/bz2comprs.cpp @@ -3,7 +3,7 @@ * bz2comprs.cpp - Bzip2Compress, a driver class that provides bzip2 * compression (Burrows–Wheeler with Huffman coding) * - * $Id: bz2comprs.cpp 3156 2014-04-17 03:50:37Z greg.hellings $ + * $Id: bz2comprs.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2000-2014 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -26,7 +26,7 @@ #include #include #include -#include +#include SWORD_NAMESPACE_START @@ -36,6 +36,7 @@ SWORD_NAMESPACE_START */ Bzip2Compress::Bzip2Compress() : SWCompress() { + level = 9; } @@ -59,20 +60,6 @@ Bzip2Compress::~Bzip2Compress() { void Bzip2Compress::Encode(void) { -/* -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least 0.1% larger than - sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the - compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ direct = 0; // set direction needed by parent [Get|Send]Chars() // get buffer @@ -91,12 +78,12 @@ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, } - zlen = (long) (len*1.001)+15; + zlen = (long) (len*1.01)+600; char *zbuf = new char[zlen+1]; if (len) { //printf("Doing compress\n"); - if (compress((Bytef*)zbuf, &zlen, (const Bytef*)buf, len) != Z_OK) + if (BZ2_bzBuffToBuffCompress(zbuf, (unsigned int*)&zlen, buf, (unsigned int)len, level, 0, 0) != BZ_OK) { printf("ERROR in compression\n"); } @@ -123,23 +110,7 @@ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, void Bzip2Compress::Decode(void) { -/* -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. -*/ + direct = 1; // set direction needed by parent [Get|Send]Chars() // get buffer char chunk[1024]; @@ -147,7 +118,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, char *chunkbuf = zbuf; int chunklen; unsigned long zlen = 0; - while((chunklen = GetChars(chunk, 1023))) { + while((chunklen = (int)GetChars(chunk, 1023))) { memcpy(chunkbuf, chunk, chunklen); zlen += chunklen; if (chunklen < 1023) @@ -158,16 +129,16 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, //printf("Decoding complength{%ld} uncomp{%ld}\n", zlen, blen); if (zlen) { - unsigned long blen = zlen*20; // trust compression is less than 1000% + unsigned int blen = (unsigned int)(zlen*20); // trust compression is less than 1000% char *buf = new char[blen]; //printf("Doing decompress {%s}\n", zbuf); slen = 0; - switch (uncompress((Bytef*)buf, &blen, (Bytef*)zbuf, zlen)){ - case Z_OK: SendChars(buf, blen); slen = blen; break; - case Z_MEM_ERROR: fprintf(stderr, "ERROR: not enough memory during decompression.\n"); break; - case Z_BUF_ERROR: fprintf(stderr, "ERROR: not enough room in the out buffer during decompression.\n"); break; - case Z_DATA_ERROR: fprintf(stderr, "ERROR: corrupt data during decompression.\n"); break; - default: fprintf(stderr, "ERROR: an unknown error occured during decompression.\n"); break; + switch (BZ2_bzBuffToBuffDecompress(buf, &blen, zbuf, (unsigned int)zlen, 0, 0)){ + case BZ_OK: SendChars(buf, blen); slen = blen; break; + case BZ_MEM_ERROR: fprintf(stderr, "ERROR: not enough memory during decompression.\n"); break; + case BZ_OUTBUFF_FULL: fprintf(stderr, "ERROR: not enough room in the out buffer during decompression.\n"); break; + case BZ_DATA_ERROR: fprintf(stderr, "ERROR: corrupt data during decompression.\n"); break; + default: fprintf(stderr, "ERROR: an unknown error occurred during decompression.\n"); break; } delete [] buf; } diff --git a/src/modules/common/entriesblk.cpp b/src/modules/common/entriesblk.cpp index 4872d28..85b7e0d 100644 --- a/src/modules/common/entriesblk.cpp +++ b/src/modules/common/entriesblk.cpp @@ -2,7 +2,7 @@ * * entriesblk.cpp - EntriesBlock facilitates compressed lex/dict modules * - * $Id: entriesblk.cpp 2833 2013-06-29 06:40:28Z chrislit $ + * $Id: entriesblk.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -84,8 +84,8 @@ void EntriesBlock::getMetaEntry(int index, unsigned long *offset, unsigned long void EntriesBlock::setMetaEntry(int index, unsigned long offset, unsigned long size) { - __u32 rawOffset = archtosword32(offset); - __u32 rawSize = archtosword32(size); + __u32 rawOffset = (__u32)archtosword32(offset); + __u32 rawSize = (__u32)archtosword32(size); if (index >= getCount()) // assert index < count return; diff --git a/src/modules/common/rawstr.cpp b/src/modules/common/rawstr.cpp index 12371ab..7f5015f 100644 --- a/src/modules/common/rawstr.cpp +++ b/src/modules/common/rawstr.cpp @@ -5,7 +5,7 @@ * and provides lookup and parsing functions based on * class StrKey * - * $Id: rawstr.cpp 3181 2014-04-17 04:27:57Z greg.hellings $ + * $Id: rawstr.cpp 3524 2017-11-07 03:08:49Z scribe $ * * Copyright 1998-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -74,8 +74,10 @@ RawStr::RawStr(const char *ipath, int fileMode, bool caseSensitive) : caseSensit buf.setFormatted("%s.dat", path); datfd = FileMgr::getSystemFileMgr()->open(buf, fileMode, true); - if (datfd < 0) { - SWLog::getSystemLog()->logError("%d", errno); + if (!datfd || datfd->getFd() < 0) { + // couldn't find datafile but this might be fine if we're + // merely instantiating a remote InstallMgr SWMgr + SWLog::getSystemLog()->logDebug("Couldn't open file: %s. errno: %d", buf.c_str(), errno); } instance++; @@ -111,7 +113,7 @@ void RawStr::getIDXBufDat(long ioffset, char **buf) const { int size; char ch; - if (datfd > 0) { + if (datfd && datfd->getFd() >= 0) { datfd->seek(ioffset, SEEK_SET); for (size = 0; datfd->read(&ch, 1) == 1; size++) { if ((ch == '\\') || (ch == 10) || (ch == 13)) @@ -145,7 +147,7 @@ void RawStr::getIDXBuf(long ioffset, char **buf) const { __u32 offset; - if (idxfd > 0) { + if (idxfd && idxfd->getFd() >= 0) { idxfd->seek(ioffset, SEEK_SET); idxfd->read(&offset, 4); @@ -183,9 +185,9 @@ signed char RawStr::findOffset(const char *ikey, __u32 *start, __u16 *size, long headoff = 0; stdstr(&key, ikey, 3); - if (!caseSensitive) toupperstr_utf8(key, strlen(key)*3); + if (!caseSensitive) toupperstr_utf8(key, (unsigned int)(strlen(key)*3)); - int keylen = strlen(key); + int keylen = (int)strlen(key); bool substr = false; trybuf = maxbuf = 0; @@ -243,7 +245,7 @@ signed char RawStr::findOffset(const char *ikey, __u32 *start, __u16 *size, long idxfd->read(&tmpStart, 4); idxfd->read(&tmpSize, 2); if (idxoff) - *idxoff = tryoff; + *idxoff = (__u32)tryoff; *start = swordtoarch32(tmpStart); *size = swordtoarch16(tmpSize); @@ -262,17 +264,17 @@ signed char RawStr::findOffset(const char *ikey, __u32 *start, __u16 *size, long if (bad) { if(!awayFromSubstrCheck) retval = -1; - *start = laststart; + *start = (__u32)laststart; *size = lastsize; tryoff = lasttry; if (idxoff) - *idxoff = tryoff; + *idxoff = (__u32)tryoff; break; } idxfd->read(&tmpStart, 4); idxfd->read(&tmpSize, 2); if (idxoff) - *idxoff = tryoff; + *idxoff = (__u32)tryoff; *start = swordtoarch32(tmpStart); *size = swordtoarch16(tmpSize); @@ -346,7 +348,7 @@ void RawStr::readText(__u32 istart, __u16 *isize, char **idxbuf, SWBuf &buf) con while (true); // while we're resolving links if (idxbuflocal) { - int localsize = strlen(idxbuflocal); + int localsize = (int)strlen(idxbuflocal); localsize = (localsize < (*isize - 1)) ? localsize : (*isize - 1); strncpy(*idxbuf, idxbuflocal, localsize); (*idxbuf)[localsize] = 0; @@ -381,7 +383,7 @@ void RawStr::doSetText(const char *ikey, const char *buf, long len) char errorStatus = findOffset(ikey, &start, &size, 0, &idxoff); stdstr(&key, ikey, 2); - if (!caseSensitive) toupperstr_utf8(key, strlen(key)*2); + if (!caseSensitive) toupperstr_utf8(key, (unsigned int)(strlen(key)*2)); len = (len < 0) ? strlen(buf) : len; @@ -424,7 +426,7 @@ void RawStr::doSetText(const char *ikey, const char *buf, long len) while (true); // while we're resolving links } - endoff = idxfd->seek(0, SEEK_END); + endoff = (__u32)idxfd->seek(0, SEEK_END); shiftSize = endoff - idxoff; @@ -440,7 +442,7 @@ void RawStr::doSetText(const char *ikey, const char *buf, long len) memcpy(outbuf + size, buf, len); size = outsize = size + (len); - start = outstart = datfd->seek(0, SEEK_END); + start = outstart = (__u32)datfd->seek(0, SEEK_END); outstart = archtosword32(start); outsize = archtosword16(size); diff --git a/src/modules/common/rawstr4.cpp b/src/modules/common/rawstr4.cpp index c88e70d..0b54c00 100644 --- a/src/modules/common/rawstr4.cpp +++ b/src/modules/common/rawstr4.cpp @@ -5,7 +5,7 @@ * and provides lookup and parsing functions based on * class StrKey * - * $Id: rawstr4.cpp 3181 2014-04-17 04:27:57Z greg.hellings $ + * $Id: rawstr4.cpp 3524 2017-11-07 03:08:49Z scribe $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -74,8 +74,10 @@ RawStr4::RawStr4(const char *ipath, int fileMode, bool caseSensitive) : caseSens buf.setFormatted("%s.dat", path); datfd = FileMgr::getSystemFileMgr()->open(buf, fileMode, true); - if (datfd < 0) { - SWLog::getSystemLog()->logError("%d", errno); + if (!datfd || datfd->getFd() < 0) { + // couldn't find datafile but this might be fine if we're + // merely instantiating a remote InstallMgr SWMgr + SWLog::getSystemLog()->logDebug("Couldn't open file: %s. errno: %d", buf.c_str(), errno); } instance++; @@ -111,7 +113,7 @@ void RawStr4::getIDXBufDat(long ioffset, char **buf) const { int size; char ch; - if (datfd > 0) { + if ((unsigned long)datfd > 0) { datfd->seek(ioffset, SEEK_SET); for (size = 0; datfd->read(&ch, 1) == 1; size++) { if ((ch == '\\') || (ch == 10) || (ch == 13)) @@ -145,7 +147,7 @@ void RawStr4::getIDXBuf(long ioffset, char **buf) const { __u32 offset; - if (idxfd > 0) { + if ((unsigned long)idxfd > 0) { idxfd->seek(ioffset, SEEK_SET); idxfd->read(&offset, 4); @@ -193,9 +195,9 @@ signed char RawStr4::findOffset(const char *ikey, __u32 *start, __u32 *size, lon headoff = 0; stdstr(&key, ikey, 3); - if (!caseSensitive) toupperstr_utf8(key, strlen(key)*3); + if (!caseSensitive) toupperstr_utf8(key, (unsigned int)(strlen(key)*3)); - int keylen = strlen(key); + int keylen = (int)strlen(key); bool substr = false; trybuf = maxbuf = 0; @@ -252,7 +254,7 @@ signed char RawStr4::findOffset(const char *ikey, __u32 *start, __u32 *size, lon idxfd->read(&tmpStart, 4); idxfd->read(&tmpSize, 4); if (idxoff) - *idxoff = tryoff; + *idxoff = (__u32)tryoff; *start = swordtoarch32(tmpStart); *size = swordtoarch32(tmpSize); @@ -271,17 +273,17 @@ signed char RawStr4::findOffset(const char *ikey, __u32 *start, __u32 *size, lon if (bad) { if(!awayFromSubstrCheck) retval = -1; - *start = laststart; - *size = lastsize; + *start = (__u32)laststart; + *size = (__u32)lastsize; tryoff = lasttry; if (idxoff) - *idxoff = tryoff; + *idxoff = (__u32)tryoff; break; } idxfd->read(&tmpStart, 4); idxfd->read(&tmpSize, 4); if (idxoff) - *idxoff = tryoff; + *idxoff = (__u32)tryoff; *start = swordtoarch32(tmpStart); *size = swordtoarch32(tmpSize); @@ -355,7 +357,7 @@ void RawStr4::readText(__u32 istart, __u32 *isize, char **idxbuf, SWBuf &buf) co while (true); // while we're resolving links if (idxbuflocal) { - unsigned int localsize = strlen(idxbuflocal); + unsigned int localsize = (unsigned int)strlen(idxbuflocal); localsize = (localsize < (*isize - 1)) ? localsize : (*isize - 1); strncpy(*idxbuf, idxbuflocal, localsize); (*idxbuf)[localsize] = 0; @@ -389,7 +391,7 @@ void RawStr4::doSetText(const char *ikey, const char *buf, long len) { char errorStatus = findOffset(ikey, &start, &size, 0, &idxoff); stdstr(&key, ikey, 3); - if (!caseSensitive) toupperstr_utf8(key, strlen(key)*3); + if (!caseSensitive) toupperstr_utf8(key, (unsigned int)(strlen(key)*3)); len = (len < 0) ? strlen(buf) : len; getIDXBufDat(start, &dbKey); @@ -432,7 +434,7 @@ void RawStr4::doSetText(const char *ikey, const char *buf, long len) { while (true); // while we're resolving links } - endoff = idxfd->seek(0, SEEK_END); + endoff = (__u32)idxfd->seek(0, SEEK_END); shiftSize = endoff - idxoff; @@ -446,9 +448,9 @@ void RawStr4::doSetText(const char *ikey, const char *buf, long len) { sprintf(outbuf, "%s%c%c", key, 13, 10); size = strlen(outbuf); memcpy(outbuf + size, buf, len); - size = outsize = size + len; + size = outsize = size + (__u32)len; - start = outstart = datfd->seek(0, SEEK_END); + start = outstart = (__u32)datfd->seek(0, SEEK_END); outstart = archtosword32(start); outsize = archtosword32(size); diff --git a/src/modules/common/rawverse.cpp b/src/modules/common/rawverse.cpp index 34fba10..a4e8008 100644 --- a/src/modules/common/rawverse.cpp +++ b/src/modules/common/rawverse.cpp @@ -5,7 +5,7 @@ * and provides lookup and parsing functions based on * class VerseKey * - * $Id: rawverse.cpp 3181 2014-04-17 04:27:57Z greg.hellings $ + * $Id: rawverse.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 1997-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -186,7 +186,7 @@ void RawVerse::doSetText(char testmt, long idxoff, const char *buf, long len) size = (len < 0) ? strlen(buf) : len; - start = textfp[testmt-1]->seek(0, SEEK_END); + start = (__s32)textfp[testmt-1]->seek(0, SEEK_END); idxfp[testmt-1]->seek(idxoff, SEEK_SET); if (size) { diff --git a/src/modules/common/rawverse4.cpp b/src/modules/common/rawverse4.cpp index 100ef6b..92775b7 100644 --- a/src/modules/common/rawverse4.cpp +++ b/src/modules/common/rawverse4.cpp @@ -6,7 +6,7 @@ * and provides lookup and parsing functions based on * class VerseKey * - * $Id: rawverse4.cpp 3182 2014-04-17 04:28:36Z greg.hellings $ + * $Id: rawverse4.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 2007-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -185,9 +185,9 @@ void RawVerse4::doSetText(char testmt, long idxoff, const char *buf, long len) if (!testmt) testmt = ((idxfp[1]) ? 1:2); - size = (len < 0) ? strlen(buf) : len; + size = (__u32)((len < 0) ? strlen(buf) : len); - start = textfp[testmt-1]->seek(0, SEEK_END); + start = (__u32)textfp[testmt-1]->seek(0, SEEK_END); idxfp[testmt-1]->seek(idxoff, SEEK_SET); if (size) { diff --git a/src/modules/common/swcomprs.cpp b/src/modules/common/swcomprs.cpp index a9ac72e..ef7e27f 100644 --- a/src/modules/common/swcomprs.cpp +++ b/src/modules/common/swcomprs.cpp @@ -2,7 +2,7 @@ * * swcomprs.cpp - a driver class that provides compression utilities * - * $Id: swcomprs.cpp 3175 2014-04-17 04:21:31Z greg.hellings $ + * $Id: swcomprs.cpp 3121 2014-03-13 09:44:43Z chrislit $ * * Copyright 1996-2014 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -35,6 +35,7 @@ SWORD_NAMESPACE_START SWCompress::SWCompress() { buf = zbuf = 0; + level = 6; Init(); } diff --git a/src/modules/common/xzcomprs.cpp b/src/modules/common/xzcomprs.cpp index 513e170..d29057d 100644 --- a/src/modules/common/xzcomprs.cpp +++ b/src/modules/common/xzcomprs.cpp @@ -3,7 +3,7 @@ * xzcomprs.cpp - XzCompress, a driver class that provides xz (LZMA2) * compression * - * $Id: xzcomprs.cpp 3156 2014-04-17 03:50:37Z greg.hellings $ + * $Id: xzcomprs.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2000-2014 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -21,12 +21,13 @@ * */ - #include #include #include #include -#include + +#define LZMA_API_STATIC +#include SWORD_NAMESPACE_START @@ -36,6 +37,24 @@ SWORD_NAMESPACE_START */ XzCompress::XzCompress() : SWCompress() { + level = 3; + + // start with the estimated memory usage for our preset + memlimit = lzma_easy_decoder_memusage(level | LZMA_PRESET_EXTREME); + + // and round up to a power of 2-- + // bit twiddle hack to determine next greatest power of 2 from: + // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 + memlimit--; + memlimit |= memlimit >> 1; + memlimit |= memlimit >> 2; + memlimit |= memlimit >> 4; + memlimit |= memlimit >> 8; + memlimit |= memlimit >> 16; + memlimit++; + + // double that for safety's sake + memlimit <<= 1; } @@ -59,20 +78,6 @@ XzCompress::~XzCompress() { void XzCompress::Encode(void) { -/* -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least 0.1% larger than - sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the - compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ direct = 0; // set direction needed by parent [Get|Send]Chars() // get buffer @@ -90,18 +95,22 @@ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, chunkbuf = buf+len; } - - zlen = (long) (len*1.001)+15; + zlen = (long)lzma_stream_buffer_bound(len); char *zbuf = new char[zlen+1]; + size_t zpos = 0; + if (len) { //printf("Doing compress\n"); - if (compress((Bytef*)zbuf, &zlen, (const Bytef*)buf, len) != Z_OK) - { - printf("ERROR in compression\n"); - } - else { - SendChars(zbuf, zlen); + switch (lzma_easy_buffer_encode(level | LZMA_PRESET_EXTREME, LZMA_CHECK_CRC64, NULL, (const uint8_t*)buf, (size_t)len, (uint8_t*)zbuf, &zpos, (size_t)zlen)) { + case LZMA_OK: SendChars(zbuf, zpos); break; + case LZMA_BUF_ERROR: fprintf(stderr, "ERROR: not enough room in the out buffer during compression.\n"); break; + case LZMA_UNSUPPORTED_CHECK: fprintf(stderr, "ERROR: unsupported_check error encountered during decompression.\n"); break; + case LZMA_OPTIONS_ERROR: fprintf(stderr, "ERROR: options error encountered during decompression.\n"); break; + case LZMA_MEM_ERROR: fprintf(stderr, "ERROR: not enough memory during compression.\n"); break; + case LZMA_DATA_ERROR: fprintf(stderr, "ERROR: corrupt data during compression.\n"); break; + case LZMA_PROG_ERROR: fprintf(stderr, "ERROR: program error encountered during decompression.\n"); break; + default: fprintf(stderr, "ERROR: an unknown error occurred during compression.\n"); break; } } else @@ -123,23 +132,7 @@ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, void XzCompress::Decode(void) { -/* -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. -*/ + direct = 1; // set direction needed by parent [Get|Send]Chars() // get buffer char chunk[1024]; @@ -158,16 +151,25 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, //printf("Decoding complength{%ld} uncomp{%ld}\n", zlen, blen); if (zlen) { - unsigned long blen = zlen*20; // trust compression is less than 1000% + unsigned long blen = zlen*20; // trust compression is less than 2000% char *buf = new char[blen]; //printf("Doing decompress {%s}\n", zbuf); slen = 0; - switch (uncompress((Bytef*)buf, &blen, (Bytef*)zbuf, zlen)){ - case Z_OK: SendChars(buf, blen); slen = blen; break; - case Z_MEM_ERROR: fprintf(stderr, "ERROR: not enough memory during decompression.\n"); break; - case Z_BUF_ERROR: fprintf(stderr, "ERROR: not enough room in the out buffer during decompression.\n"); break; - case Z_DATA_ERROR: fprintf(stderr, "ERROR: corrupt data during decompression.\n"); break; - default: fprintf(stderr, "ERROR: an unknown error occured during decompression.\n"); break; + size_t zpos = 0; + size_t bpos = 0; + + switch (lzma_stream_buffer_decode((uint64_t *)&memlimit, 0, NULL, (const uint8_t*)zbuf, &zpos, (size_t)zlen, (uint8_t*)buf, &bpos, (size_t)&blen)){ + case LZMA_OK: SendChars(buf, bpos); slen = bpos; break; + case LZMA_FORMAT_ERROR: fprintf(stderr, "ERROR: format error encountered during decompression.\n"); break; + case LZMA_OPTIONS_ERROR: fprintf(stderr, "ERROR: options error encountered during decompression.\n"); break; + case LZMA_DATA_ERROR: fprintf(stderr, "ERROR: corrupt data during decompression.\n"); break; + case LZMA_NO_CHECK: fprintf(stderr, "ERROR: no_check error encountered during decompression.\n"); break; + case LZMA_UNSUPPORTED_CHECK: fprintf(stderr, "ERROR: unsupported_check error encountered during decompression.\n"); break; + case LZMA_MEMLIMIT_ERROR: fprintf(stderr, "ERROR: memlimit error encountered during decompression.\n"); break; + case LZMA_MEM_ERROR: fprintf(stderr, "ERROR: not enough memory during decompression.\n"); break; + case LZMA_BUF_ERROR: fprintf(stderr, "ERROR: not enough room in the out buffer during decompression.\n"); break; + case LZMA_PROG_ERROR: fprintf(stderr, "ERROR: program error encountered during decompression.\n"); break; + default: fprintf(stderr, "ERROR: an unknown error occurred during decompression.\n"); break; } delete [] buf; } @@ -178,4 +180,34 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, free (zbuf); } + +/****************************************************************************** + * XzCompress::SetLevel - This function sets the compression level of the + * compressor. + */ + +void XzCompress::setLevel(int l) { + level = l; + + // having changed the compression level, we need to adjust our memlimit accordingly, + // as in the constructor: + + // start with the estimated memory usage for our preset + memlimit = lzma_easy_decoder_memusage(level | LZMA_PRESET_EXTREME); + + // and round up to a power of 2-- + // bit twiddle hack to determine next greatest power of 2 from: + // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 + memlimit--; + memlimit |= memlimit >> 1; + memlimit |= memlimit >> 2; + memlimit |= memlimit >> 4; + memlimit |= memlimit >> 8; + memlimit |= memlimit >> 16; + memlimit++; + + // double that for safety's sake + memlimit <<= 1; +}; + SWORD_NAMESPACE_END diff --git a/src/modules/common/zipcomprs.cpp b/src/modules/common/zipcomprs.cpp index 28471d8..557239e 100644 --- a/src/modules/common/zipcomprs.cpp +++ b/src/modules/common/zipcomprs.cpp @@ -3,7 +3,7 @@ * zipcomprs.cpp - ZipCompress, a driver class that provides zlib * compression * - * $Id: zipcomprs.cpp 3175 2014-04-17 04:21:31Z greg.hellings $ + * $Id: zipcomprs.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2000-2014 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -38,6 +38,7 @@ SWORD_NAMESPACE_START ZipCompress::ZipCompress() : SWCompress() { // fprintf(stderr, "init compress\n"); + level = Z_DEFAULT_COMPRESSION; } @@ -62,18 +63,20 @@ ZipCompress::~ZipCompress() { void ZipCompress::Encode(void) { /* -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least 0.1% larger than - sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); + + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. */ direct = 0; // set direction needed by parent [Get|Send]Chars() @@ -98,7 +101,7 @@ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, if (len) { //printf("Doing compress\n"); - if (compress((Bytef*)zbuf, &zlen, (const Bytef*)buf, len) != Z_OK) + if (compress2((Bytef*)zbuf, &zlen, (const Bytef*)buf, len, level) != Z_OK) { printf("ERROR in compression\n"); } @@ -142,6 +145,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted. */ + direct = 1; // set direction needed by parent [Get|Send]Chars() // get buffer char chunk[1024]; @@ -149,7 +153,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, char *chunkbuf = zbuf; int chunklen; unsigned long zlen = 0; - while((chunklen = GetChars(chunk, 1023))) { + while((chunklen = (int)GetChars(chunk, 1023))) { memcpy(chunkbuf, chunk, chunklen); zlen += chunklen; if (chunklen < 1023) @@ -169,7 +173,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, case Z_MEM_ERROR: fprintf(stderr, "ERROR: not enough memory during decompression.\n"); break; case Z_BUF_ERROR: fprintf(stderr, "ERROR: not enough room in the out buffer during decompression.\n"); break; case Z_DATA_ERROR: fprintf(stderr, "ERROR: corrupt data during decompression.\n"); break; - default: fprintf(stderr, "ERROR: an unknown error occured during decompression.\n"); break; + default: fprintf(stderr, "ERROR: an unknown error occurred during decompression.\n"); break; } delete [] buf; } diff --git a/src/modules/common/zstr.cpp b/src/modules/common/zstr.cpp index a745502..0b4f0f6 100644 --- a/src/modules/common/zstr.cpp +++ b/src/modules/common/zstr.cpp @@ -4,7 +4,7 @@ * files and provides lookup and parsing functions based on * class StrKey * - * $Id: zstr.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: zstr.cpp 3524 2017-11-07 03:08:49Z scribe $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -83,8 +83,10 @@ zStr::zStr(const char *ipath, int fileMode, long blockCount, SWCompress *icomp, buf.setFormatted("%s.zdt", path); zdtfd = FileMgr::getSystemFileMgr()->open(buf, fileMode, true); - if (datfd <= 0) { - SWLog::getSystemLog()->logError("%d", errno); + if (!zdtfd || zdtfd->getFd() < 0) { + // couldn't find datafile but this might be fine if we're + // merely instantiating a remote InstallMgr SWMgr + SWLog::getSystemLog()->logDebug("Couldn't open file: %s. errno: %d", buf.c_str(), errno); } cacheBlock = 0; @@ -133,7 +135,7 @@ void zStr::getKeyFromDatOffset(long ioffset, char **buf) const { int size; char ch; - if (datfd > 0) { + if (datfd && datfd->getFd() >= 0) { datfd->seek(ioffset, SEEK_SET); for (size = 0; datfd->read(&ch, 1) == 1; size++) { if ((ch == '\\') || (ch == 10) || (ch == 13)) @@ -167,7 +169,7 @@ void zStr::getKeyFromIdxOffset(long ioffset, char **buf) const { __u32 offset; - if (idxfd > 0) { + if (idxfd && idxfd->getFd() >= 0) { idxfd->seek(ioffset, SEEK_SET); idxfd->read(&offset, 4); offset = swordtoarch32(offset); @@ -198,19 +200,19 @@ signed char zStr::findKeyIndex(const char *ikey, long *idxoff, long away) const bool awayFromSubstrCheck = false; if (idxfd->getFd() >= 0) { - tailoff = maxoff = idxfd->seek(0, SEEK_END) - IDXENTRYSIZE; + tailoff = maxoff = (__s32)idxfd->seek(0, SEEK_END) - IDXENTRYSIZE; if (*ikey) { headoff = 0; stdstr(&key, ikey, 3); - if (!caseSensitive) toupperstr_utf8(key, strlen(key)*3); + if (!caseSensitive) toupperstr_utf8(key, (unsigned int)(strlen(key)*3)); - int keylen = strlen(key); + int keylen = (int)strlen(key); bool substr = false; getKeyFromIdxOffset(maxoff, &maxbuf); while (headoff < tailoff) { - tryoff = (lastoff == -1) ? headoff + (((((tailoff / IDXENTRYSIZE) - (headoff / IDXENTRYSIZE))) / 2) * IDXENTRYSIZE) : lastoff; + tryoff = ((__s32)lastoff == -1) ? headoff + (((((tailoff / IDXENTRYSIZE) - (headoff / IDXENTRYSIZE))) / 2) * IDXENTRYSIZE) : (__s32)lastoff; lastoff = -1; getKeyFromIdxOffset(tryoff, &trybuf); @@ -295,7 +297,7 @@ signed char zStr::findKeyIndex(const char *ikey, long *idxoff, long away) const *idxoff = tryoff; - if (((laststart != start) || (lastsize != size)) && (start >= 0) && (size)) + if (((laststart != start) || (lastsize != size)) && size) away += (away < 0) ? 1 : -1; } @@ -366,7 +368,7 @@ void zStr::getText(long offset, char **idxbuf, char **buf) const { while (true); // while we're resolving links if (idxbuflocal) { - __u32 localsize = strlen(idxbuflocal); + __u32 localsize = (__u32)strlen(idxbuflocal); localsize = (localsize < (size - 1)) ? localsize : (size - 1); strncpy(*idxbuf, idxbuflocal, localsize); (*idxbuf)[localsize] = 0; @@ -416,7 +418,7 @@ void zStr::getCompressedText(long block, long entry, char **buf) const { cacheBlock = new EntriesBlock(rawBuf, len); cacheBlockIndex = block; } - size = cacheBlock->getEntrySize(entry); + size = (__u32)cacheBlock->getEntrySize(entry); *buf = (*buf) ? (char *)realloc(*buf, size*2 + 1) : (char *)malloc(size*2 + 1); strcpy(*buf, cacheBlock->getEntry(entry)); } @@ -448,7 +450,7 @@ void zStr::setText(const char *ikey, const char *buf, long len) { len = (len < 0) ? strlen(buf) : len; stdstr(&key, ikey, 3); - if (!caseSensitive) toupperstr_utf8(key, strlen(key)*3); + if (!caseSensitive) toupperstr_utf8(key, (unsigned int)(strlen(key)*3)); char notFound = findKeyIndex(ikey, &idxoff, 0); if (!notFound) { @@ -497,9 +499,9 @@ void zStr::setText(const char *ikey, const char *buf, long len) { } } - endoff = idxfd->seek(0, SEEK_END); + endoff = (__s32)idxfd->seek(0, SEEK_END); - shiftSize = endoff - idxoff; + shiftSize = endoff - (__s32)idxoff; if (shiftSize > 0) { idxBytes = new char [ shiftSize ]; @@ -509,7 +511,7 @@ void zStr::setText(const char *ikey, const char *buf, long len) { outbuf = new char [ len + strlen(key) + 5 ]; sprintf(outbuf, "%s%c%c", key, 13, 10); - size = strlen(outbuf); + size = (__u32)strlen(outbuf); if (len > 0) { // NOT a link if (!cacheBlock) { flushCache(); @@ -523,7 +525,7 @@ void zStr::setText(const char *ikey, const char *buf, long len) { } __u32 entry = cacheBlock->addEntry(buf); cacheDirty = true; - outstart = archtosword32(cacheBlockIndex); + outstart = (__u32)archtosword32(cacheBlockIndex); outsize = archtosword32(entry); memcpy (outbuf + size, &outstart, sizeof(__u32)); memcpy (outbuf + size + sizeof(__u32), &outsize, sizeof(__u32)); @@ -534,7 +536,7 @@ void zStr::setText(const char *ikey, const char *buf, long len) { size += len; } - start = datfd->seek(0, SEEK_END); + start = (__u32)datfd->seek(0, SEEK_END); outstart = archtosword32(start); outsize = archtosword32(size); @@ -609,7 +611,7 @@ void zStr::flushCache() const { unsigned long zdtSize = zdtfd->seek(0, SEEK_END); if ((cacheBlockIndex * ZDXENTRYSIZE) > (zdxSize - ZDXENTRYSIZE)) { // New Block - start = zdtSize; + start = (__u32)zdtSize; } else { zdxfd->seek(cacheBlockIndex * ZDXENTRYSIZE, SEEK_SET); @@ -624,7 +626,7 @@ void zStr::flushCache() const { size = outsize; } else { // middle and bigger-- we have serious problems, for now let's put it at the end = lots of wasted space - start = zdtSize; + start = (__u32)zdtSize; } } diff --git a/src/modules/common/zverse.cpp b/src/modules/common/zverse.cpp index cd63eca..e975a81 100644 --- a/src/modules/common/zverse.cpp +++ b/src/modules/common/zverse.cpp @@ -5,7 +5,7 @@ * and provides lookup and parsing functions based on * class VerseKey for compressed modules * - * $Id: zverse.cpp 3166 2014-04-17 04:08:45Z greg.hellings $ + * $Id: zverse.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 1996-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -67,7 +67,6 @@ zVerse::zVerse(const char *ipath, int fileMode, int blockType, SWCompress *icomp SWBuf buf; - nl = '\n'; path = 0; cacheBufIdx = -1; cacheTestament = 0; @@ -273,7 +272,7 @@ void zVerse::zReadText(char testmt, long start, unsigned short size, unsigned lo compressor->Buf(0, &len); cacheBuf = (char *)calloc(len + 1, 1); memcpy(cacheBuf, compressor->Buf(), len); - cacheBufSize = strlen(cacheBuf); // TODO: can we just use len? + cacheBufSize = (int)strlen(cacheBuf); // TODO: can we just use len? cacheTestament = testmt; cacheBufIdx = ulBuffNum; } @@ -315,12 +314,12 @@ void zVerse::doSetText(char testmt, long idxoff, const char *buf, long len) { __u32 start; __u16 size; - __u32 outBufIdx = cacheBufIdx; + __u32 outBufIdx = (__u32)cacheBufIdx; idxoff *= 10; size = len; - start = strlen(cacheBuf); + start = (__u32)strlen(cacheBuf); if (!size) start = outBufIdx = 0; @@ -344,9 +343,9 @@ void zVerse::flushCache() const { __u32 size, outsize; __u32 zsize, outzsize; - idxoff = cacheBufIdx * 12; + idxoff = (__u32)cacheBufIdx * 12; if (cacheBuf) { - size = outsize = zsize = outzsize = strlen(cacheBuf); + size = outsize = zsize = outzsize = (__u32)strlen(cacheBuf); if (size) { // if (compressor) { // delete compressor; @@ -355,16 +354,16 @@ void zVerse::flushCache() const { compressor->Buf(cacheBuf); unsigned long tmpSize; compressor->zBuf(&tmpSize); - outzsize = zsize = tmpSize; + outzsize = zsize = (__u32)tmpSize; SWBuf buf; buf.setSize(zsize + 5); memcpy(buf.getRawData(), compressor->zBuf(&tmpSize), tmpSize); - outzsize = zsize = tmpSize; + outzsize = zsize = (__u32)tmpSize; buf.setSize(zsize); rawZFilter(buf, 1); // 1 = encipher - start = outstart = textfp[cacheTestament-1]->seek(0, SEEK_END); + start = outstart = (__u32)textfp[cacheTestament-1]->seek(0, SEEK_END); outstart = archtosword32(start); outsize = archtosword32(size); diff --git a/src/modules/common/zverse4.cpp b/src/modules/common/zverse4.cpp new file mode 100644 index 0000000..ff10b2d --- /dev/null +++ b/src/modules/common/zverse4.cpp @@ -0,0 +1,516 @@ +/****************************************************************************** + * + * zverse4.cpp - code for class 'zVerse4'- a module that reads raw text + * files: ot and nt using indexs ??.bks ??.cps ??.vss + * and provides lookup and parsing functions based on + * class VerseKey for compressed modules + * + * $Id: zverse4.cpp 3439 2016-10-23 08:32:02Z scribe $ + * + * Copyright 1996-2014 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +SWORD_NAMESPACE_START + +/****************************************************************************** + * zVerse4 Statics + */ + +int zVerse4::instance = 0; + +const char zVerse4::uniqueIndexID[] = {'X', 'r', 'v', 'c', 'b'}; + +/****************************************************************************** + * zVerse4 Constructor - Initializes data for instance of zVerse4 + * + * ENT: ipath - path of the directory where data and index files are located. + * be sure to include the trailing separator (e.g. '/' or '\') + * (e.g. 'modules/texts/rawtext/webster/') + * fileMode - open mode for the files (FileMgr::RDONLY, etc.) + * blockType - verse, chapter, book, etc. + */ + +zVerse4::zVerse4(const char *ipath, int fileMode, int blockType, SWCompress *icomp) +{ + // this line, instead of just defaulting, to keep FileMgr out of header + if (fileMode == -1) fileMode = FileMgr::RDONLY; + + SWBuf buf; + + path = 0; + cacheBufIdx = -1; + cacheTestament = 0; + cacheBuf = 0; + dirtyCache = false; + stdstr(&path, ipath); + + if ((path[strlen(path)-1] == '/') || (path[strlen(path)-1] == '\\')) + path[strlen(path)-1] = 0; + + compressor = (icomp) ? icomp : new SWCompress(); + + if (fileMode == -1) { // try read/write if possible + fileMode = FileMgr::RDWR; + } + + buf.setFormatted("%s/ot.%czs", path, uniqueIndexID[blockType]); + idxfp[0] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true); + + buf.setFormatted("%s/nt.%czs", path, uniqueIndexID[blockType]); + idxfp[1] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true); + + buf.setFormatted("%s/ot.%czz", path, uniqueIndexID[blockType]); + textfp[0] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true); + + buf.setFormatted("%s/nt.%czz", path, uniqueIndexID[blockType]); + textfp[1] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true); + + buf.setFormatted("%s/ot.%czv", path, uniqueIndexID[blockType]); + compfp[0] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true); + + buf.setFormatted("%s/nt.%czv", path, uniqueIndexID[blockType]); + compfp[1] = FileMgr::getSystemFileMgr()->open(buf, fileMode, true); + + instance++; +} + + +/****************************************************************************** + * zVerse4 Destructor - Cleans up instance of zVerse4 + */ + +zVerse4::~zVerse4() +{ + int loop1; + + if (cacheBuf) { + flushCache(); + free(cacheBuf); + } + + if (path) + delete [] path; + + if (compressor) + delete compressor; + + --instance; + + for (loop1 = 0; loop1 < 2; loop1++) { + FileMgr::getSystemFileMgr()->close(idxfp[loop1]); + FileMgr::getSystemFileMgr()->close(textfp[loop1]); + FileMgr::getSystemFileMgr()->close(compfp[loop1]); + } +} + + +/****************************************************************************** + * zVerse4::findoffset - Finds the offset of the key verse from the indexes + * + * + * + * ENT: testmt - testament to find (0 - Bible/module introduction) + * book - book to find (0 - testament introduction) + * chapter - chapter to find (0 - book introduction) + * verse - verse to find (0 - chapter introduction) + * start - address to store the starting offset + * size - address to store the size of the entry + */ + +void zVerse4::findOffset(char testmt, long idxoff, long *start, unsigned long *size, unsigned long *buffnum) const +{ + __u32 ulBuffNum = 0; // buffer number + __u32 ulVerseStart = 0; // verse offset within buffer + __u32 usVerseSize = 0; // verse size + // set start to offset in + // set size to + // set + *start = *size = *buffnum = 0; + //fprintf(stderr, "Finding offset %ld\n", idxoff); + idxoff *= 12; // TODO: Is this the correct size? (throughout) + if (!testmt) { + testmt = ((idxfp[0]) ? 1:2); + } + + // assert we have and valid file descriptor + if (compfp[testmt-1]->getFd() < 1) + return; + + long newOffset = compfp[testmt-1]->seek(idxoff, SEEK_SET); + if (newOffset == idxoff) { + if (compfp[testmt-1]->read(&ulBuffNum, 4) != 4) { + fprintf(stderr, "Error reading ulBuffNum\n"); + return; + } + } + else return; + + if (compfp[testmt-1]->read(&ulVerseStart, 4) < 4) + { + fprintf(stderr, "Error reading ulVerseStart\n"); + return; + } + if (compfp[testmt-1]->read(&usVerseSize, 4) < 4) + { + fprintf(stderr, "Error reading usVerseSize\n"); + return; + } + + *buffnum = swordtoarch32(ulBuffNum); + *start = swordtoarch32(ulVerseStart); + *size = swordtoarch32(usVerseSize); + +} + + +/****************************************************************************** + * zVerse4::zreadtext - gets text at a given offset + * + * ENT: testmt - testament file to search in (0 - Old; 1 - New) + * start - starting offset where the text is located in the file + * size - size of text entry + 1 (null) + * buf - buffer to store text + * + */ + +void zVerse4::zReadText(char testmt, long start, unsigned long size, unsigned long ulBuffNum, SWBuf &inBuf) const { + __u32 ulCompOffset = 0; // compressed buffer start + __u32 ulCompSize = 0; // buffer size compressed + __u32 ulUnCompSize = 0; // buffer size uncompressed + + if (!testmt) { + testmt = ((idxfp[0]) ? 1:2); + } + + // assert we have and valid file descriptor + if (compfp[testmt-1]->getFd() < 1) + return; + + if (size && + !(((long) ulBuffNum == cacheBufIdx) && (testmt == cacheTestament) && (cacheBuf))) { + //fprintf(stderr, "Got buffer number{%ld} versestart{%ld} versesize{%d}\n", ulBuffNum, ulVerseStart, usVerseSize); + + if (idxfp[testmt-1]->seek(ulBuffNum*12, SEEK_SET)!=(long) ulBuffNum*12) + { + fprintf(stderr, "Error seeking compressed file index\n"); + return; + } + if (idxfp[testmt-1]->read(&ulCompOffset, 4)<4) + { + fprintf(stderr, "Error reading ulCompOffset\n"); + return; + } + if (idxfp[testmt-1]->read(&ulCompSize, 4)<4) + { + fprintf(stderr, "Error reading ulCompSize\n"); + return; + } + if (idxfp[testmt-1]->read(&ulUnCompSize, 4)<4) + { + fprintf(stderr, "Error reading ulUnCompSize\n"); + return; + } + + ulCompOffset = swordtoarch32(ulCompOffset); + ulCompSize = swordtoarch32(ulCompSize); + ulUnCompSize = swordtoarch32(ulUnCompSize); + + if (textfp[testmt-1]->seek(ulCompOffset, SEEK_SET)!=(long)ulCompOffset) + { + fprintf(stderr, "Error: could not seek to right place in compressed text\n"); + return; + } + SWBuf pcCompText; + pcCompText.setSize(ulCompSize+5); + + if (textfp[testmt-1]->read(pcCompText.getRawData(), ulCompSize)<(long)ulCompSize) { + fprintf(stderr, "Error reading compressed text\n"); + return; + } + pcCompText.setSize(ulCompSize); + rawZFilter(pcCompText, 0); // 0 = decipher + + unsigned long bufSize = ulCompSize; + compressor->zBuf(&bufSize, pcCompText.getRawData()); + + if (cacheBuf) { + flushCache(); + free(cacheBuf); + } + + unsigned long len = 0; + compressor->Buf(0, &len); + cacheBuf = (char *)calloc(len + 1, 1); + memcpy(cacheBuf, compressor->Buf(), len); + cacheBufSize = (int)strlen(cacheBuf); // TODO: can we just use len? + cacheTestament = testmt; + cacheBufIdx = ulBuffNum; + } + + inBuf = ""; + if ((size > 0) && cacheBuf && ((unsigned)start < cacheBufSize)) { + inBuf.setFillByte(0); + inBuf.setSize(size+1); + strncpy(inBuf.getRawData(), &(cacheBuf[start]), size); + inBuf.setSize(strlen(inBuf.c_str())); + } +} + + +/****************************************************************************** + * zVerse4::settext - Sets text for current offset + * + * ENT: testmt - testament to find (0 - Bible/module introduction) + * idxoff - offset into .vss + * buf - buffer to store + * len - length of buffer (0 - null terminated) + */ + +void zVerse4::doSetText(char testmt, long idxoff, const char *buf, long len) { + + len = (len < 0) ? strlen(buf) : len; + if (!testmt) + testmt = ((idxfp[0]) ? 1:2); + if ((!dirtyCache) || (cacheBufIdx < 0)) { + cacheBufIdx = idxfp[testmt-1]->seek(0, SEEK_END) / 12; + cacheTestament = testmt; + if (cacheBuf) + free(cacheBuf); + cacheBuf = (char *)calloc(len + 1, 1); + } + else cacheBuf = (char *)((cacheBuf)?realloc(cacheBuf, strlen(cacheBuf)+(len + 1)):calloc((len + 1), 1)); + + dirtyCache = true; + + __u32 start; + __u32 size; + __u32 outBufIdx = (__u32)cacheBufIdx; + + idxoff *= 12; + size = (__u32)len; + + start = (__u32)strlen(cacheBuf); + + if (!size) + start = outBufIdx = 0; + + outBufIdx = archtosword32(outBufIdx); + start = archtosword32(start); + size = archtosword32(size); + + compfp[testmt-1]->seek(idxoff, SEEK_SET); + compfp[testmt-1]->write(&outBufIdx, 4); + compfp[testmt-1]->write(&start, 4); + compfp[testmt-1]->write(&size, 4); + strcat(cacheBuf, buf); +} + + +void zVerse4::flushCache() const { + if (dirtyCache) { + __u32 idxoff; + __u32 start, outstart; + __u32 size, outsize; + __u32 zsize, outzsize; + + idxoff = (__u32)cacheBufIdx * 12; + if (cacheBuf) { + size = outsize = zsize = outzsize = (__u32)strlen(cacheBuf); + if (size) { + compressor->Buf(cacheBuf); + unsigned long tmpSize; + compressor->zBuf(&tmpSize); + outzsize = zsize = (__u32)tmpSize; + + SWBuf buf; + buf.setSize(zsize + 5); + memcpy(buf.getRawData(), compressor->zBuf(&tmpSize), tmpSize); + outzsize = zsize = (__u32)tmpSize; + buf.setSize(zsize); + rawZFilter(buf, 1); // 1 = encipher + + start = outstart = (__u32)textfp[cacheTestament-1]->seek(0, SEEK_END); + + outstart = archtosword32(start); + outsize = archtosword32(size); + outzsize = archtosword32(zsize); + + textfp[cacheTestament-1]->write(buf, zsize); + + idxfp[cacheTestament-1]->seek(idxoff, SEEK_SET); + idxfp[cacheTestament-1]->write(&outstart, 4); + idxfp[cacheTestament-1]->write(&outzsize, 4); + idxfp[cacheTestament-1]->write(&outsize, 4); + } + free(cacheBuf); + cacheBuf = 0; + } + dirtyCache = false; + } +} + +/****************************************************************************** + * RawVerse::linkentry - links one entry to another + * + * ENT: testmt - testament to find (0 - Bible/module introduction) + * destidxoff - dest offset into .vss + * srcidxoff - source offset into .vss + */ + +void zVerse4::doLinkEntry(char testmt, long destidxoff, long srcidxoff) { + __s32 bufidx; + __s32 start; + __u32 size; + + destidxoff *= 12; + srcidxoff *= 12; + + if (!testmt) + testmt = ((idxfp[1]) ? 1:2); + + // get source + compfp[testmt-1]->seek(srcidxoff, SEEK_SET); + compfp[testmt-1]->read(&bufidx, 4); + compfp[testmt-1]->read(&start, 4); + compfp[testmt-1]->read(&size, 4); + + // write dest + compfp[testmt-1]->seek(destidxoff, SEEK_SET); + compfp[testmt-1]->write(&bufidx, 4); + compfp[testmt-1]->write(&start, 4); + compfp[testmt-1]->write(&size, 4); +} + + +/****************************************************************************** + * RawVerse::CreateModule - Creates new module files + * + * ENT: path - directory to store module files + * RET: error status + */ + +char zVerse4::createModule(const char *ipath, int blockBound, const char *v11n) +{ + char *path = 0; + char *buf = new char [ strlen (ipath) + 20 ]; + char retVal = 0; + FileDesc *fd, *fd2; + __s32 offset = 0; + __s32 size = 0; + VerseKey vk; + + stdstr(&path, ipath); + + if ((path[strlen(path)-1] == '/') || (path[strlen(path)-1] == '\\')) + path[strlen(path)-1] = 0; + + sprintf(buf, "%s/ot.%czs", path, uniqueIndexID[blockBound]); + FileMgr::removeFile(buf); + fd = FileMgr::getSystemFileMgr()->open(buf, FileMgr::CREAT|FileMgr::WRONLY, FileMgr::IREAD|FileMgr::IWRITE); + if (fd->getFd() < 1) goto erroropen1; + FileMgr::getSystemFileMgr()->close(fd); + + sprintf(buf, "%s/nt.%czs", path, uniqueIndexID[blockBound]); + FileMgr::removeFile(buf); + fd = FileMgr::getSystemFileMgr()->open(buf, FileMgr::CREAT|FileMgr::WRONLY, FileMgr::IREAD|FileMgr::IWRITE); + if (fd->getFd() < 1) goto erroropen1; + FileMgr::getSystemFileMgr()->close(fd); + + sprintf(buf, "%s/ot.%czz", path, uniqueIndexID[blockBound]); + FileMgr::removeFile(buf); + fd = FileMgr::getSystemFileMgr()->open(buf, FileMgr::CREAT|FileMgr::WRONLY, FileMgr::IREAD|FileMgr::IWRITE); + if (fd->getFd() < 1) goto erroropen1; + FileMgr::getSystemFileMgr()->close(fd); + + sprintf(buf, "%s/nt.%czz", path, uniqueIndexID[blockBound]); + FileMgr::removeFile(buf); + fd = FileMgr::getSystemFileMgr()->open(buf, FileMgr::CREAT|FileMgr::WRONLY, FileMgr::IREAD|FileMgr::IWRITE); + if (fd->getFd() < 1) goto erroropen1; + FileMgr::getSystemFileMgr()->close(fd); + + sprintf(buf, "%s/ot.%czv", path, uniqueIndexID[blockBound]); + FileMgr::removeFile(buf); + fd = FileMgr::getSystemFileMgr()->open(buf, FileMgr::CREAT|FileMgr::WRONLY, FileMgr::IREAD|FileMgr::IWRITE); + if (fd->getFd() < 1) goto erroropen1; + + sprintf(buf, "%s/nt.%czv", path, uniqueIndexID[blockBound]); + FileMgr::removeFile(buf); + fd2 = FileMgr::getSystemFileMgr()->open(buf, FileMgr::CREAT|FileMgr::WRONLY, FileMgr::IREAD|FileMgr::IWRITE); + if (fd2->getFd() < 1) goto erroropen2; + + vk.setVersificationSystem(v11n); + vk.setIntros(true); + + offset = archtosword32(offset); + size = archtosword32(size); + + for (vk = TOP; !vk.popError(); vk++) { + if (vk.getTestament() < 2) { + if (fd->write(&offset, 4) != 4) goto writefailure; //compBufIdxOffset + if (fd->write(&offset, 4) != 4) goto writefailure; + if (fd->write(&size, 4) != 4) goto writefailure; + } + else { + if (fd2->write(&offset, 4) != 4) goto writefailure; //compBufIdxOffset + if (fd2->write(&offset, 4) != 4) goto writefailure; + if (fd2->write(&size, 4) != 4) goto writefailure; + } + } + fd2->write(&offset, 4); //compBufIdxOffset + fd2->write(&offset, 4); + fd2->write(&size, 4); + + goto cleanup; + +erroropen1: + retVal = -1; + goto cleanup1; + +erroropen2: + retVal = -1; + goto cleanup; + +writefailure: + retVal = -2; + +cleanup: + FileMgr::getSystemFileMgr()->close(fd2); +cleanup1: + FileMgr::getSystemFileMgr()->close(fd); + + delete [] path; + delete [] buf; + + return retVal; +} + + +SWORD_NAMESPACE_END diff --git a/src/modules/filters/Makefile.am b/src/modules/filters/Makefile.am index a3d1154..3e8556b 100644 --- a/src/modules/filters/Makefile.am +++ b/src/modules/filters/Makefile.am @@ -15,6 +15,7 @@ GBFFIL += $(filtersdir)/gbfheadings.cpp GBFFIL += $(filtersdir)/gbfredletterwords.cpp GBFFIL += $(filtersdir)/gbfmorph.cpp GBFFIL += $(filtersdir)/gbfwordjs.cpp +GBFFIL += $(filtersdir)/gbflatex.cpp THMLFIL = $(filtersdir)/thmlstrongs.cpp THMLFIL += $(filtersdir)/thmlfootnotes.cpp @@ -30,11 +31,13 @@ THMLFIL += $(filtersdir)/thmlhtmlhref.cpp THMLFIL += $(filtersdir)/thmlxhtml.cpp THMLFIL += $(filtersdir)/thmlwebif.cpp THMLFIL += $(filtersdir)/thmlwordjs.cpp +THMLFIL += $(filtersdir)/thmllatex.cpp TEIFIL = $(filtersdir)/teiplain.cpp TEIFIL += $(filtersdir)/teirtf.cpp TEIFIL += $(filtersdir)/teihtmlhref.cpp TEIFIL += $(filtersdir)/teixhtml.cpp +TEIFIL += $(filtersdir)/teilatex.cpp CONVFIL = $(filtersdir)/gbfthml.cpp CONVFIL += $(filtersdir)/gbfosis.cpp @@ -61,6 +64,7 @@ OSISFIL += $(filtersdir)/osisglosses.cpp OSISFIL += $(filtersdir)/osisenum.cpp OSISFIL += $(filtersdir)/osisxlit.cpp OSISFIL += $(filtersdir)/osisreferencelinks.cpp +OSISFIL += $(filtersdir)/osislatex.cpp libsword_la_SOURCES += $(filtersdir)/latin1utf8.cpp libsword_la_SOURCES += $(filtersdir)/latin1utf16.cpp @@ -70,6 +74,7 @@ libsword_la_SOURCES += $(filtersdir)/utf8html.cpp libsword_la_SOURCES += $(filtersdir)/utf8latin1.cpp libsword_la_SOURCES += $(filtersdir)/unicodertf.cpp libsword_la_SOURCES += $(filtersdir)/scsuutf8.cpp +libsword_la_SOURCES += $(filtersdir)/utf8scsu.cpp libsword_la_SOURCES += $(filtersdir)/utf8cantillation.cpp libsword_la_SOURCES += $(filtersdir)/utf8hebrewpoints.cpp diff --git a/src/modules/filters/gbfheadings.cpp b/src/modules/filters/gbfheadings.cpp index 7e19ea1..a679924 100644 --- a/src/modules/filters/gbfheadings.cpp +++ b/src/modules/filters/gbfheadings.cpp @@ -3,7 +3,7 @@ * gbfheadings.cpp - SWFilter descendant to hide or show headings * in a GBF module * - * $Id: gbfheadings.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: gbfheadings.cpp 3427 2016-07-03 14:30:33Z scribe $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -93,11 +93,13 @@ char GBFHeadings::processText(SWBuf &text, const SWKey *key, const SWModule *mod continue; } if (intoken) { - if (tokpos < 2045) + if (tokpos < 2045) { token[tokpos++] = *from; + // TODO: why is this + 2 ? token[tokpos+2] = 0; + } } - else { + else { if (!hide) { text += *from; } diff --git a/src/modules/filters/gbfhtmlhref.cpp b/src/modules/filters/gbfhtmlhref.cpp index 6df038e..723137f 100644 --- a/src/modules/filters/gbfhtmlhref.cpp +++ b/src/modules/filters/gbfhtmlhref.cpp @@ -2,7 +2,7 @@ * * gbfhtmlhref.cpp - GBF to HTML filter with hrefs * - * $Id: gbfhtmlhref.cpp 2833 2013-06-29 06:40:28Z chrislit $ + * $Id: gbfhtmlhref.cpp 3548 2017-12-10 05:11:38Z scribe $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -232,19 +232,13 @@ bool GBFHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData SWBuf type = tag.getAttribute("type"); SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); SWBuf noteName = tag.getAttribute("n"); - VerseKey *vkey = NULL; - // see if we have a VerseKey * or descendant - SWTRY { - vkey = SWDYNAMIC_CAST(VerseKey, u->key); - } - SWCATCH ( ... ) { } - if (vkey) { + if (u->vkey) { // leave this special osis type in for crossReference notes types? Might thml use this some day? Doesn't hurt. //char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); buf.appendFormatted("*n%s ", URL::encode(footnoteNumber.c_str()).c_str(), URL::encode(u->version.c_str()).c_str(), - URL::encode(vkey->getText()).c_str(), + URL::encode(u->vkey->getText()).c_str(), (renderNoteNumbers ? URL::encode(noteName.c_str()).c_str(): "")); } u->suspendTextPassThru = true; diff --git a/src/modules/filters/gbflatex.cpp b/src/modules/filters/gbflatex.cpp new file mode 100644 index 0000000..d3c726a --- /dev/null +++ b/src/modules/filters/gbflatex.cpp @@ -0,0 +1,198 @@ +/****************************************************************************** + * + * gbflatex.cpp - GBF to LaTeX + * + * $Id: gbflatex.cpp 3548 2017-12-10 05:11:38Z scribe $ + * + * Copyright 2011-2014 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 +#include +#include +#include +#include +#include +#include + +SWORD_NAMESPACE_START + +const char *GBFLaTeX::getHeader() const { + return "\\usepackage{color}"; +} + +GBFLaTeX::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) { + if (module) { + version = module->getName(); + } +} + +GBFLaTeX::GBFLaTeX() { + setTokenStart("<"); + setTokenEnd(">"); + + setTokenCaseSensitive(true); + + //addTokenSubstitute("Rf", ")"); + addTokenSubstitute("FA", "{\\color{maroon}"); // for ASV footnotes to mark text + addTokenSubstitute("Rx", "}"); + addTokenSubstitute("FI", "\\emph{"); // italics begin + addTokenSubstitute("Fi", "}"); + addTokenSubstitute("FB", "\\bold{"); // bold begin + addTokenSubstitute("Fb", "}"); + addTokenSubstitute("FR", "{\\swordwoj{"); // words of Jesus begin + addTokenSubstitute("Fr", "}"); + addTokenSubstitute("FU", "\\underline{"); // underline begin + addTokenSubstitute("Fu", "}"); + addTokenSubstitute("FO", "\\begin{quote}"); // Old Testament quote begin + addTokenSubstitute("Fo", "\\end{quote}"); + addTokenSubstitute("FS", "\\textsuperscript{"); // Superscript begin// Subscript begin + addTokenSubstitute("Fs", "}"); + addTokenSubstitute("FV", "\\textsubscript{"); // Subscript begin + addTokenSubstitute("Fv", "}"); + addTokenSubstitute("TT", "\\section*{"); // Book title begin + addTokenSubstitute("Tt", "}"); + addTokenSubstitute("PP", "\\begin{swordpoetry}"); // poetry begin + addTokenSubstitute("Pp", "\\end{swordpoetry}"); + addTokenSubstitute("Fn", ""); // font end + addTokenSubstitute("CL", "\\\\"); // new line + addTokenSubstitute("CM", "\\\\"); // paragraph is a non showing comment that can be changed in the front end to

if desired + addTokenSubstitute("CG", ""); // ??? + addTokenSubstitute("CT", ""); // ??? + addTokenSubstitute("JR", "{\\raggedright{}"); // right align begin + addTokenSubstitute("JC", "{\\raggedcenter{}"); // center align begin + addTokenSubstitute("JL", "}"); // align end + + renderNoteNumbers = false; +} + + +bool GBFLaTeX::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) { + const char *tok; + MyUserData *u = (MyUserData *)userData; + + if (!substituteToken(buf, token)) { + XMLTag tag(token); + + if (!strncmp(token, "WG", 2)) { // strong's numbers + //buf += " <vkey) { + + buf.appendFormatted("\\swordfootnote{%s}{%s}{%s}{", + footnoteNumber.c_str(), + u->version.c_str(), + u->vkey->getText()).c_str(); + } + u->suspendTextPassThru = false; + } + else if (!strcmp(tag.getName(), "Rf")) { + u->suspendTextPassThru = false; + buf += "}"; + } + else if (!strncmp(token, "FN", 2)) { + buf += "\\swordfont{"; + for (tok = token + 2; *tok; tok++) + if(*tok != '\"') + buf += *tok; + buf += "}"; + } + + else if (!strncmp(token, "CA", 2)) { // ASCII value + buf += (char)atoi(&token[2]); + } + + else { + return false; + } + } + return true; +} + +SWORD_NAMESPACE_END diff --git a/src/modules/filters/gbfmorph.cpp b/src/modules/filters/gbfmorph.cpp index 3399ae8..cf1405b 100644 --- a/src/modules/filters/gbfmorph.cpp +++ b/src/modules/filters/gbfmorph.cpp @@ -3,7 +3,7 @@ * gbfmorph.cpp - SWFilter descendant to hide or show morph tags * in a GBF module * - * $Id: gbfmorph.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: gbfmorph.cpp 3427 2016-07-03 14:30:33Z scribe $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -84,11 +84,13 @@ char GBFMorph::processText(SWBuf &text, const SWKey *key, const SWModule *module continue; } if (intoken) { - if (tokpos < 2045) + if (tokpos < 2045) { token[tokpos++] = *from; + // TODO: why is this + 2 ? token[tokpos+2] = 0; + } } - else { + else { text += *from; lastspace = (*from == ' '); } diff --git a/src/modules/filters/gbfplain.cpp b/src/modules/filters/gbfplain.cpp index b2a1ae4..45588af 100644 --- a/src/modules/filters/gbfplain.cpp +++ b/src/modules/filters/gbfplain.cpp @@ -3,7 +3,7 @@ * gbfplain.cpp - SWFilter descendant to strip out all GBF tags or * convert to ASCII rendered symbols * - * $Id: gbfplain.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: gbfplain.cpp 3427 2016-07-03 14:30:33Z scribe $ * * Copyright 1997-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -103,9 +103,11 @@ char GBFPlain::processText (SWBuf &text, const SWKey *key, const SWModule *modul continue; } if (intoken) { - if (tokpos < 2045) + if (tokpos < 2045) { token[tokpos++] = *from; + // TODO: why is this + 2 ? token[tokpos+2] = 0; + } } else text.append(*from); } diff --git a/src/modules/filters/gbfredletterwords.cpp b/src/modules/filters/gbfredletterwords.cpp index cac3cd9..f3e74f3 100644 --- a/src/modules/filters/gbfredletterwords.cpp +++ b/src/modules/filters/gbfredletterwords.cpp @@ -3,7 +3,7 @@ * gbfredletterwords.cpp - SWFilter descendant to toggle red coloring of * words of Christ in a GBF module * - * $Id: gbfredletterwords.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: gbfredletterwords.cpp 3427 2016-07-03 14:30:33Z scribe $ * * Copyright 2003-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -101,9 +101,12 @@ char GBFRedLetterWords::processText(SWBuf &text, const SWKey *key, const SWModul continue; } if (intoken) { - if (tokpos < 4090) + if (tokpos < 4090) { token[tokpos++] = *from; + // TODO: why is this + 2 ? The below comment still doesn't help me understand. The switch statment + // is commented out in this filter token[tokpos+2] = 0; // +2 cuz we init token with 2 extra '0' because of switch statement + } } else { text += *from; diff --git a/src/modules/filters/gbfrtf.cpp b/src/modules/filters/gbfrtf.cpp index 8a8e1b1..c327c82 100644 --- a/src/modules/filters/gbfrtf.cpp +++ b/src/modules/filters/gbfrtf.cpp @@ -2,7 +2,7 @@ * * gbfrtf.cpp - SWFilter descendant to convert all GBF tags to RTF tags * - * $Id: gbfrtf.cpp 2833 2013-06-29 06:40:28Z chrislit $ + * $Id: gbfrtf.cpp 3427 2016-07-03 14:30:33Z scribe $ * * Copyright 1997-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -307,9 +307,11 @@ char GBFRTF::processText(SWBuf &text, const SWKey *key, const SWModule *module) continue; } if (intoken) { - if (tokpos < 2045) + if (tokpos < 2045) { token[tokpos++] = *from; + // TODO: why is this + 2 ? token[tokpos+2] = 0; + } } else { if (!hideText) { diff --git a/src/modules/filters/gbfstrongs.cpp b/src/modules/filters/gbfstrongs.cpp index dd4e167..65473de 100644 --- a/src/modules/filters/gbfstrongs.cpp +++ b/src/modules/filters/gbfstrongs.cpp @@ -3,7 +3,7 @@ * gbfstrongs.cpp - SWFilter descendant to hide or show Strong's number * in a GBF module * - * $Id: gbfstrongs.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: gbfstrongs.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 1999-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -58,7 +58,7 @@ char GBFStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *modu bool lastspace = false; int word = 1; char val[128]; - char wordstr[5]; + char wordstr[11]; char *valto; unsigned int textStart = 0, textEnd = 0; bool newText = false; @@ -75,7 +75,7 @@ char GBFStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *modu token[0] = 0; token[1] = 0; token[2] = 0; - textEnd = text.size(); + textEnd = (unsigned int)text.size(); continue; } if (*from == '>') { // process tokens @@ -110,7 +110,7 @@ char GBFStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *modu if (lastspace) text--; } - if (newText) {textStart = text.size(); newText = false; } + if (newText) {textStart = (unsigned int)text.size(); newText = false; } continue; } } @@ -130,15 +130,17 @@ char GBFStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *modu text += '<'; text += token; text += '>'; - if (newText) {textStart = text.size(); newText = false; } + if (newText) {textStart = (unsigned int)text.size(); newText = false; } continue; } if (intoken) { - if (tokpos < 2045) + if (tokpos < 2045) { token[tokpos++] = *from; + // TODO: why is this + 2 ? token[tokpos+2] = 0; + } } - else { + else { text += *from; lastspace = (*from == ' '); } diff --git a/src/modules/filters/gbfthml.cpp b/src/modules/filters/gbfthml.cpp index 303b240..d3dd611 100644 --- a/src/modules/filters/gbfthml.cpp +++ b/src/modules/filters/gbfthml.cpp @@ -2,7 +2,7 @@ * * gbfthml.cpp - GBF to ThML filter * - * $Id: gbfthml.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: gbfthml.cpp 3427 2016-07-03 14:30:33Z scribe $ * * Copyright 1999-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -52,8 +52,7 @@ char GBFThML::processText(SWBuf &text, const SWKey *key, const SWModule *module) token[2] = 0; continue; } - if (*from == '>') - { + if (*from == '>') { intoken = false; // process desired tokens switch (*token) { @@ -210,9 +209,15 @@ char GBFThML::processText(SWBuf &text, const SWKey *key, const SWModule *module) continue; } if (intoken) { - if (tokpos < 2045) + if (tokpos < 2045) { token[tokpos++] = *from; + //TODO: why is this + 2? Are we trying to keep 2 or 3 nulls after the last valid char? + // tokpos has been incremented past the last valid token. it should be pointing to null + // +1 should give us 2 nulls, but we're +2 here, which actually keeps 3 nulls after the + // last valid char. Why are we doing any of this? These were written before SWBuf and should + // probably be switched to SWBuf, but perf tests before and after the switch should be run token[tokpos+2] = 0; + } } else text += *from; } diff --git a/src/modules/filters/gbfwordjs.cpp b/src/modules/filters/gbfwordjs.cpp index c9d1bd3..b0f352e 100644 --- a/src/modules/filters/gbfwordjs.cpp +++ b/src/modules/filters/gbfwordjs.cpp @@ -2,7 +2,7 @@ * * gbfwordjs.cpp - SWFilter descendant for ??? * - * $Id: gbfwordjs.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: gbfwordjs.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2005-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -88,7 +88,7 @@ char GBFWordJS::processText(SWBuf &text, const SWKey *key, const SWModule *modul token[0] = 0; token[1] = 0; token[2] = 0; - textEnd = text.length(); + textEnd = (unsigned int)text.length(); continue; } if (*from == '>') { // process tokens @@ -137,7 +137,7 @@ char GBFWordJS::processText(SWBuf &text, const SWKey *key, const SWModule *modul text += token; text += '>'; if (needWordOut) { - char wstr[10]; + char wstr[11]; sprintf(wstr, "%03d", word-2); AttributeValue *wAttrs = &(module->getEntryAttributes()["Word"][wstr]); needWordOut = false; @@ -212,27 +212,29 @@ char GBFWordJS::processText(SWBuf &text, const SWKey *key, const SWModule *modul else m = morph.c_str(); spanStart.appendFormatted("", lexName.c_str(), strong.c_str(), wordID.c_str(), m, modName.c_str()); text.insert(textStr, spanStart); - lastAppendLen = spanStart.length(); + lastAppendLen = (unsigned int)spanStart.length(); } } } if (newText) { - textStart = text.length(); newText = false; + textStart = (unsigned int)text.length(); newText = false; } continue; } if (intoken) { - if (tokpos < 2045) + if (tokpos < 2045) { token[tokpos++] = *from; + // TODO: why is this + 2 ? token[tokpos+2] = 0; + } } - else { + else { text += *from; } } - char wstr[10]; + char wstr[11]; sprintf(wstr, "%03d", word-1); AttributeValue *wAttrs = &(module->getEntryAttributes()["Word"][wstr]); needWordOut = false; diff --git a/src/modules/filters/gbfxhtml.cpp b/src/modules/filters/gbfxhtml.cpp index 56d7663..b62fe3a 100644 --- a/src/modules/filters/gbfxhtml.cpp +++ b/src/modules/filters/gbfxhtml.cpp @@ -2,7 +2,7 @@ * * gbfxhtml.cpp - GBF to classed XHTML * - * $Id: gbfxhtml.cpp 2833 2013-06-29 06:40:28Z chrislit $ + * $Id: gbfxhtml.cpp 3548 2017-12-10 05:11:38Z scribe $ * * Copyright 2011-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -171,19 +171,13 @@ bool GBFXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *u SWBuf type = tag.getAttribute("type"); SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); SWBuf noteName = tag.getAttribute("n"); - VerseKey *vkey = NULL; - // see if we have a VerseKey * or descendant - SWTRY { - vkey = SWDYNAMIC_CAST(VerseKey, u->key); - } - SWCATCH ( ... ) { } - if (vkey) { + if (u->vkey) { // leave this special osis type in for crossReference notes types? Might thml use this some day? Doesn't hurt. //char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); buf.appendFormatted("*n%s ", URL::encode(footnoteNumber.c_str()).c_str(), URL::encode(u->version.c_str()).c_str(), - URL::encode(vkey->getText()).c_str(), + URL::encode(u->vkey->getText()).c_str(), (renderNoteNumbers ? URL::encode(noteName.c_str()).c_str(): "")); } u->suspendTextPassThru = true; diff --git a/src/modules/filters/greeklexattribs.cpp b/src/modules/filters/greeklexattribs.cpp index 1c2533d..1d98db2 100644 --- a/src/modules/filters/greeklexattribs.cpp +++ b/src/modules/filters/greeklexattribs.cpp @@ -3,7 +3,7 @@ * greeklexattribs.cpp - SWFilter descendant to set entry attributes * for greek lexicons * - * $Id: greeklexattribs.cpp 2833 2013-06-29 06:40:28Z chrislit $ + * $Id: greeklexattribs.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2002-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -44,7 +44,7 @@ char GreekLexAttribs::processText(SWBuf &text, const SWKey *key, const SWModule string phrase; string freq; char val[128], *valto; - char wordstr[7]; + char wordstr[11]; const char *currentPhrase = 0; const char *currentPhraseEnd = 0; int number = 0; diff --git a/src/modules/filters/osisheadings.cpp b/src/modules/filters/osisheadings.cpp index 7a5f525..74ed5ce 100644 --- a/src/modules/filters/osisheadings.cpp +++ b/src/modules/filters/osisheadings.cpp @@ -3,7 +3,7 @@ * osisheadings.cpp - SWFilter descendant to hide or show headings * in an OSIS module * - * $Id: osisheadings.cpp 3194 2014-04-24 03:02:47Z greg.hellings $ + * $Id: osisheadings.cpp 3423 2016-06-25 13:21:48Z scribe $ * * Copyright 2003-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -51,6 +51,7 @@ namespace { SWBuf heading; int depth; int headerNum; + bool canonical; MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) { clear(); @@ -62,6 +63,7 @@ namespace { heading = ""; depth = 0; headerNum = 0; + canonical=false; } }; } @@ -88,16 +90,16 @@ bool OSISHeadings::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat // are we currently in a heading? if (u->currentHeadingName.size()) { u->heading.append(u->lastTextNode); + if (SWBuf("true") == tag.getAttribute("canonical")) u->canonical = true; if (name == u->currentHeadingName) { if (tag.isEndTag(u->sID)) { if (!u->depth-- || u->sID) { // see comment below about preverse div changed and needing to preserve the container tag for old school pre-verse titles // we've just finished a heading. It's all stored up in u->heading - bool canonical = (SWBuf("true") == u->currentHeadingTag.getAttribute("canonical")); bool preverse = (SWBuf("x-preverse") == u->currentHeadingTag.getAttribute("subType") || SWBuf("x-preverse") == u->currentHeadingTag.getAttribute("subtype")); // do we want to put anything in EntryAttributes? - if (u->module->isProcessEntryAttributes() && (option || canonical || !preverse)) { + if (u->module->isProcessEntryAttributes() && (option || u->canonical || !preverse)) { SWBuf buf; buf.appendFormatted("%i", u->headerNum++); // leave the actual <title...> wrapper in if we're part of an old school preverse title // because now frontend have to deal with preverse as a div which may or may not include <title> elements @@ -121,7 +123,7 @@ bool OSISHeadings::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat } // do we want the heading in the body? - if (!preverse && (option || canonical)) { + if (!preverse && (option || u->canonical)) { buf.append(u->currentHeadingTag); buf.append(u->heading); buf.append(tag); @@ -148,6 +150,7 @@ bool OSISHeadings::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat u->sID = u->currentHeadingTag.getAttribute("sID"); u->depth = 0; u->suspendTextPassThru = true; + u->canonical = (SWBuf("true") == tag.getAttribute("canonical")); return true; } diff --git a/src/modules/filters/osishtmlhref.cpp b/src/modules/filters/osishtmlhref.cpp index 9cda9ab..94194ac 100644 --- a/src/modules/filters/osishtmlhref.cpp +++ b/src/modules/filters/osishtmlhref.cpp @@ -2,7 +2,7 @@ * * osishtmlhref.cpp - OSIS to HTML with hrefs filter * - * $Id: osishtmlhref.cpp 3173 2014-04-17 04:20:33Z greg.hellings $ + * $Id: osishtmlhref.cpp 3548 2017-12-10 05:11:38Z scribe $ * * Copyright 2003-2014 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -117,14 +117,12 @@ OSISHTMLHREF::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : tagStacks = new TagStacks(); wordsOfChristStart = "<font color=\"red\"> "; wordsOfChristEnd = "</font> "; + osisQToTick = true; // default + isBiblicalText = false; if (module) { osisQToTick = ((!module->getConfigEntry("OSISqToTick")) || (strcmp(module->getConfigEntry("OSISqToTick"), "false"))); version = module->getName(); - BiblicalText = (!strcmp(module->getType(), "Biblical Texts")); - } - else { - osisQToTick = true; // default - version = ""; + isBiblicalText = (!strcmp(module->getType(), "Biblical Texts")); } } @@ -201,9 +199,9 @@ bool OSISHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat outText("<ruby><rb>", buf, u); outText(lastText, buf, u); + outText("</rb><rp>(</rp><rt>", buf, u); val = strchr(attrib, ':'); val = (val) ? (val + 1) : attrib; - outText("</rb><rp>(</rp><rt>", buf, u); outText(val, buf, u); outText("</rt><rp>)</rp></ruby>", buf, u); } @@ -241,22 +239,15 @@ bool OSISHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat if (!strongsMarkup) { // leave strong's markup notes out, in the future we'll probably have different option filters to turn different note types on or off SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); SWBuf noteName = tag.getAttribute("n"); - VerseKey *vkey = NULL; char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); u->inXRefNote = true; // Why this change? Ben Morgan: Any note can have references in, so we need to set this to true for all notes // u->inXRefNote = (ch == 'x'); - - // see if we have a VerseKey * or descendant - SWTRY { - vkey = SWDYNAMIC_CAST(VerseKey, u->key); - } - SWCATCH ( ... ) { } buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=%c&value=%s&module=%s&passage=%s\"><small><sup class=\"%c\">*%c%s</sup></small></a>", ch, URL::encode(footnoteNumber.c_str()).c_str(), URL::encode(u->version.c_str()).c_str(), - URL::encode(vkey ? vkey->getText() : u->key->getText()).c_str(), + URL::encode(u->vkey ? u->vkey->getText() : u->key->getText()).c_str(), ch, ch, (renderNoteNumbers ? noteName.c_str() : "")); @@ -267,7 +258,7 @@ bool OSISHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat if (tag.isEndTag()) { u->suspendTextPassThru = (--u->suspendLevel); u->inXRefNote = false; - u->lastSuspendSegment = ""; // fix/work-around for nasb devineName in note bug + u->lastSuspendSegment = ""; // fix/work-around for nasb divineName in note bug } } @@ -322,7 +313,7 @@ bool OSISHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat // Compensate for starting : ref = the_ref + 1; - int size = target.size() - ref.size() - 1; + int size = (int)(target.size() - ref.size() - 1); work.setSize(size); strncpy(work.getRawData(), target, size); @@ -460,7 +451,7 @@ bool OSISHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat const unsigned char *tmpBuf = (const unsigned char *)lastText.c_str(); getUniCharFromUTF8(&tmpBuf); - int char_length = (tmpBuf - (const unsigned char *)lastText.c_str()); + int char_length = (int)(tmpBuf - (const unsigned char *)lastText.c_str()); scratch.setFormatted("%.*s<font size=\"-1\">%s</font>", char_length, lastText.c_str(), @@ -509,7 +500,7 @@ bool OSISHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat else if (type == "ol") { outText("</span>", buf, u); } - else if (type == "sup") { + else if (type == "super") { outText("</sup>", buf, u); } else if (type == "sub") { @@ -595,7 +586,7 @@ bool OSISHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat if ((type == "added") || (type == "supplied")) outText("<i>", buf, u); else if (type == "tenseChange") - buf += "*"; + outText( "*", buf, u); } else if (tag.isEndTag()) { SWBuf type = u->lastTransChange; diff --git a/src/modules/filters/osislatex.cpp b/src/modules/filters/osislatex.cpp new file mode 100644 index 0000000..e642f07 --- /dev/null +++ b/src/modules/filters/osislatex.cpp @@ -0,0 +1,766 @@ +/****************************************************************************** + * + * osislatex.cpp - Render filter for LaTeX of an OSIS module + * + * $Id: osislatex.cpp 3548 2017-12-10 05:11:38Z scribe $ + * + * Copyright 2011-2014 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 <stdlib.h> +#include <ctype.h> +#include <osislatex.h> +#include <utilxml.h> +#include <utilstr.h> +#include <versekey.h> +#include <swmodule.h> +#include <url.h> +#include <stringmgr.h> +#include <stack> + +SWORD_NAMESPACE_START + +const char *OSISLaTeX::getHeader() const { +// can be used to return static start-up info, like packages to load. Not sure yet if I want to retain it. + + const static char *header = "\ + \\LoadClass[11pt,a4paper,twoside,headinclude=true,footinclude=true,BCOR=0mm,DIV=calc]{scrbook}\n\ + \\LoadClass[11pt,a4paper,twoside,headinclude=true,footinclude=true,BCOR=0mm,DIV=calc]{scrbook}\n\ + \\NeedsTeXFormat{LaTeX2e}\n\ + \\ProvidesClass{sword}[2015/03/29 CrossWire LaTeX class for Biblical texts]\n\ + %\\sworddiclink{%s}{%s}{\n\ + %\\sworddictref{%s}{%s}{\n\ + %\\sworddict{%s}{\n\ + %\\sworddivinename}{%s}{\n\ + %\\swordfont{\n\ + %\\swordfootnote[%c]{%s}{%s}{%s}{%s}{\n\ + %\\swordfootnote{%s}{%s}{%s}{\n\ + %\\swordfootnote{%s}{%s}{%s}{%s}{\n\ + %\\swordmorph{\n\ + %\\swordmorph[Greek]{%s}\n\ + %\\swordmorph[lemma]{%s}\n\ + %\\swordmorph{%s}\n\ + %\\swordpoetryline{\n\ + %\\swordquote{\n\ + %\\swordref{%s}{%s}{\n\ + %\\swordsection{\n\ + %\\swordsection{}{\n\ + %\\swordsection{book}{\n\ + %\\swordsection{sechead}{\n\ + %\\swordstrong[Greek]{\n\ + %\\swordstrong[Greektense]{\n\ + %\\swordstrong[Hebrew]{\n\ + %\\swordstrong[Hebrewtense]{\n\ + %\\swordstrong[%s]{%s}{\n\ + %\\swordstrong{%s}{%s}\n\ + %\\swordtitle{\n\ + %\\swordtranschange{supplied}{\n\ + %\\swordtranschange{tense}{\n\ + %\\swordwoj{\n\ + %\\swordxref{\n\ + %\\swordxref{%s}{\n\ + %\\swordxref{%s}{%s}{\n\ + "; + return header; +} + + +namespace { + +// though this might be slightly slower, possibly causing an extra bool check, this is a renderFilter +// so speed isn't the absolute highest priority, and this is a very minor possible hit +static inline void outText(const char *t, SWBuf &o, BasicFilterUserData *u) { if (!u->suspendTextPassThru) o += t; else u->lastSuspendSegment += t; } +static inline void outText(char t, SWBuf &o, BasicFilterUserData *u) { if (!u->suspendTextPassThru) o += t; else u->lastSuspendSegment += t; } + +void processLemma(bool suspendTextPassThru, XMLTag &tag, SWBuf &buf) { + const char *attrib; + const char *val; + if ((attrib = tag.getAttribute("lemma"))) { + int count = tag.getAttributePartCount("lemma", ' '); + int i = (count > 1) ? 0 : -1; // -1 for whole value cuz it's faster, but does the same thing as 0 + do { + attrib = tag.getAttribute("lemma", i, ' '); + if (i < 0) i = 0; // to handle our -1 condition + val = strchr(attrib, ':'); + val = (val) ? (val + 1) : attrib; + SWBuf gh; + if(*val == 'G') + gh = "Greek"; + if(*val == 'H') + gh = "Hebrew"; + const char *val2 = val; + if ((strchr("GH", *val)) && (isdigit(val[1]))) + val2++; + //if ((!strcmp(val2, "3588")) && (lastText.length() < 1)) + // show = false; + //else { + if (!suspendTextPassThru) { + buf.appendFormatted("\\swordstrong{%s}{%s}", + (gh.length()) ? gh.c_str() : "", + val2); + } + //} + + } while (++i < count); + } +} + + + +void processMorph(bool suspendTextPassThru, XMLTag &tag, SWBuf &buf) { + const char * attrib; + const char *val; + if ((attrib = tag.getAttribute("morph"))) { // && (show)) { + SWBuf savelemma = tag.getAttribute("savlm"); + //if ((strstr(savelemma.c_str(), "3588")) && (lastText.length() < 1)) + // show = false; + //if (show) { + int count = tag.getAttributePartCount("morph", ' '); + int i = (count > 1) ? 0 : -1; // -1 for whole value cuz it's faster, but does the same thing as 0 + do { + attrib = tag.getAttribute("morph", i, ' '); + if (i < 0) i = 0; // to handle our -1 condition + val = strchr(attrib, ':'); + val = (val) ? (val + 1) : attrib; + const char *val2 = val; + if ((*val == 'T') && (strchr("GH", val[1])) && (isdigit(val[2]))) + val2+=2; + if (!suspendTextPassThru) { + buf.appendFormatted("\\swordmorph{%s}", + tag.getAttribute("morph") + ); + } + } while (++i < count); + //} + } +} + + +} // end anonymous namespace + +BasicFilterUserData *OSISLaTeX::createUserData(const SWModule *module, const SWKey *key) { + return new MyUserData(module, key); +} + + +OSISLaTeX::OSISLaTeX() { + setTokenStart("<"); + setTokenEnd(">"); + + setEscapeStart("&"); + setEscapeEnd(";"); + + setEscapeStringCaseSensitive(true); + setPassThruNumericEscapeString(true); + + addAllowedEscapeString("quot"); + addAllowedEscapeString("apos"); + addAllowedEscapeString("amp"); + addAllowedEscapeString("lt"); + addAllowedEscapeString("gt"); + + setTokenCaseSensitive(true); + + // addTokenSubstitute("lg", "<br />"); + // addTokenSubstitute("/lg", "<br />"); + + morphFirst = false; + renderNoteNumbers = false; +} + +class OSISLaTeX::TagStack : public std::stack<SWBuf> { +}; + +OSISLaTeX::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key), quoteStack(new TagStack()), hiStack(new TagStack()), titleStack(new TagStack()), lineStack(new TagStack()) { + inXRefNote = false; + suspendLevel = 0; + divLevel = "module"; + wordsOfChristStart = "\\swordwoj{"; + wordsOfChristEnd = "}"; + consecutiveNewlines = 0; + firstCell = false; +} + +OSISLaTeX::MyUserData::~MyUserData() { + delete quoteStack; + delete hiStack; + delete titleStack; + delete lineStack; +} + +void OSISLaTeX::MyUserData::outputNewline(SWBuf &buf) { + if (++consecutiveNewlines <= 2) { + outText("//\n", buf, this); + supressAdjacentWhitespace = true; + } +} +bool OSISLaTeX::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) { + MyUserData *u = (MyUserData *)userData; + SWBuf scratch; + + bool sub = (u->suspendTextPassThru) ? substituteToken(scratch, token) : substituteToken(buf, token); + if (!sub) { + // manually process if it wasn't a simple substitution + XMLTag tag(token); + + // <w> tag + if (!strcmp(tag.getName(), "w")) { + + // start <w> tag + if ((!tag.isEmpty()) && (!tag.isEndTag())) { + u->w = token; + } + + // end or empty <w> tag + else { + bool endTag = tag.isEndTag(); + SWBuf lastText; + //bool show = true; // to handle unplaced article in kjv2003-- temporary till combined + + if (endTag) { + tag = u->w.c_str(); + lastText = u->lastTextNode.c_str(); + } + else lastText = "stuff"; + + const char *attrib; + const char *val; + if ((attrib = tag.getAttribute("xlit"))) { + val = strchr(attrib, ':'); + val = (val) ? (val + 1) : attrib; + outText(" ", buf, u); + outText(val, buf, u); + } + if ((attrib = tag.getAttribute("gloss"))) { + // I'm sure this is not the cleanest way to do it, but it gets the job done + // for rendering ruby chars properly ^_^ + buf -= lastText.length(); + + outText("\\ruby{", buf, u); + outText(lastText, buf, u); + outText("}{", buf, u); + outText(attrib, buf, u); + outText("}", buf, u); + } + if (!morphFirst) { + processLemma(u->suspendTextPassThru, tag, buf); + processMorph(u->suspendTextPassThru, tag, buf); + } + else { + processMorph(u->suspendTextPassThru, tag, buf); + processLemma(u->suspendTextPassThru, tag, buf); + } + if ((attrib = tag.getAttribute("POS"))) { + val = strchr(attrib, ':'); + val = (val) ? (val + 1) : attrib; + outText(" ", buf, u); + outText(val, buf, u); + } + + + } + } + + // <note> tag + + else if (!strcmp(tag.getName(), "note")) { + if (!tag.isEndTag()) { + SWBuf type = tag.getAttribute("type"); + bool strongsMarkup = (type == "x-strongsMarkup" || type == "strongsMarkup"); // the latter is deprecated + if (strongsMarkup) { + tag.setEmpty(false); // handle bug in KJV2003 module where some note open tags were <note ... /> + } + + if (!tag.isEmpty()) { + + if (!strongsMarkup) { // leave strong's markup notes out, in the future we'll probably have different option filters to turn different note types on or off + SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); + SWBuf footnoteBody = ""; + if (u->module){ + footnoteBody += u->module->getEntryAttributes()["Footnote"][footnoteNumber]["body"]; + } + SWBuf noteName = tag.getAttribute("n"); + + u->inXRefNote = true; // Why this change? Ben Morgan: Any note can have references in, so we need to set this to true for all notes +// u->inXRefNote = (ch == 'x'); + + if (u->vkey) { + //printf("URL = %s\n",URL::encode(u->vkey->getText()).c_str()); + buf.appendFormatted("\\swordfootnote{%s}{%s}{%s}{%s}{%s}{", + + footnoteNumber.c_str(), + u->version.c_str(), + u->vkey->getText(), + tag.getAttribute("type"), + (renderNoteNumbers ? noteName.c_str() : "")); + if (u->module) { + outText( u->module->renderText(footnoteBody).c_str(), buf, u); + } + } + else { + buf.appendFormatted("\\swordfootnote{%s}{%s}{%s}{%s}{%s}{", + footnoteNumber.c_str(), + u->version.c_str(), + u->key->getText(), + tag.getAttribute("type"), + (renderNoteNumbers ? noteName.c_str() : "")); + if (u->module) { + outText( u->module->renderText(footnoteBody).c_str(), buf, u); + } + } + } + } + u->suspendTextPassThru = (++u->suspendLevel); + } + if (tag.isEndTag()) { + u->suspendTextPassThru = (--u->suspendLevel); + u->inXRefNote = false; + u->lastSuspendSegment = ""; // fix/work-around for nasb divineName in note bug + outText("}", buf, u); + } + } + + // <p> paragraph and <lg> linegroup tags + else if (!strcmp(tag.getName(), "p") || !strcmp(tag.getName(), "lg")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { // non-empty start tag + u->outputNewline(buf); + } + else if (tag.isEndTag()) { // end tag + u->outputNewline(buf); + } + else { // empty paragraph break marker + u->outputNewline(buf); + } + } + + // Milestoned paragraphs, created by osis2mod + // <div type="paragraph" sID.../> + // <div type="paragraph" eID.../> + else if (tag.isEmpty() && !strcmp(tag.getName(), "div") && tag.getAttribute("type") && (!strcmp(tag.getAttribute("type"), "x-p") || !strcmp(tag.getAttribute("type"), "paragraph"))) { + // <div type="paragraph" sID... /> + if (tag.getAttribute("sID")) { // non-empty start tag + u->outputNewline(buf); + } + // <div type="paragraph" eID... /> + else if (tag.getAttribute("eID")) { + u->outputNewline(buf); + } + } + + // <reference> tag + else if (!strcmp(tag.getName(), "reference")) { + if (!u->inXRefNote) { // only show these if we're not in an xref note + if (!tag.isEndTag()) { + SWBuf target; + SWBuf work; + SWBuf ref; + bool is_scripRef = false; + + target = tag.getAttribute("osisRef"); + const char* the_ref = strchr(target, ':'); + + if(!the_ref) { + // No work + ref = target; + is_scripRef = true; + } + else { + // Compensate for starting : + ref = the_ref + 1; + + int size = (int)(target.size() - ref.size() - 1); + work.setSize(size); + strncpy(work.getRawData(), target, size); + + // For Bible:Gen.3.15 or Bible.vulgate:Gen.3.15 + if(!strncmp(work, "Bible", 5)) + is_scripRef = true; + } + + if(is_scripRef) + { + buf.appendFormatted("\\swordxref{%s}{", + ref.c_str() +// (work.size()) ? URL::encode(work.c_str()).c_str() : "") + ); + } + else + { + // Dictionary link, or something + buf.appendFormatted("\\sworddiclink{%s}{%s}{", // work, entry + work.c_str(), + ref.c_str() + ); + } + } + else { + outText("}", buf, u); + } + } + } + + // <l> poetry, etc + else if (!strcmp(tag.getName(), "l")) { + // start line marker + if (tag.getAttribute("sID") || (!tag.isEndTag() && !tag.isEmpty())) { + // nested lines plus if the line itself has an x-indent type attribute value + outText("\\swordpoetryline{", buf, u); + u->lineStack->push(tag.toString()); + } + // end line marker + else if (tag.getAttribute("eID") || tag.isEndTag()) { + outText("}", buf, u); + u->outputNewline(buf); + if (u->lineStack->size()) u->lineStack->pop(); + } + // <l/> without eID or sID + // Note: this is improper osis. This should be <lb/> + else if (tag.isEmpty() && !tag.getAttribute("sID")) { + u->outputNewline(buf); + } + } + + // <lb.../> + else if (!strcmp(tag.getName(), "lb") && (!tag.getAttribute("type") || strcmp(tag.getAttribute("type"), "x-optional"))) { + u->outputNewline(buf); + } + // <milestone type="line"/> + // <milestone type="x-p"/> + // <milestone type="cQuote" marker="x"/> + else if ((!strcmp(tag.getName(), "milestone")) && (tag.getAttribute("type"))) { + if (!strcmp(tag.getAttribute("type"), "line")) { + u->outputNewline(buf); + if (tag.getAttribute("subType") && !strcmp(tag.getAttribute("subType"), "x-PM")) { + u->outputNewline(buf); + } + } + else if (!strcmp(tag.getAttribute("type"),"x-p")) { + if (tag.getAttribute("marker")) + outText(tag.getAttribute("marker"), buf, u); + else outText("<!p>", buf, u); + } + else if (!strcmp(tag.getAttribute("type"), "cQuote")) { + const char *tmp = tag.getAttribute("marker"); + bool hasMark = tmp; + SWBuf mark = tmp; + tmp = tag.getAttribute("level"); + int level = (tmp) ? atoi(tmp) : 1; + + // first check to see if we've been given an explicit mark + if (hasMark) + outText(mark, buf, u); + // finally, alternate " and ', if config says we should supply a mark + else if (u->osisQToTick) + outText((level % 2) ? '\"' : '\'', buf, u); + } + } + + // <title> + + else if (!strcmp(tag.getName(), "title")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + const char *tmp = tag.getAttribute("type"); + bool hasType = tmp; + SWBuf type = tmp; + + outText("\n\\swordtitle{", buf, u); + outText(u->divLevel, buf, u); + outText("}{", buf, u); + + if (hasType) outText(type, buf, u); + else outText("", buf, u); + + outText("}{", buf, u); + } + else if (tag.isEndTag()) { + outText( "}", buf, u); + ++u->consecutiveNewlines; + u->supressAdjacentWhitespace = true; + } + } + + // <list> + else if (!strcmp(tag.getName(), "list")) { + if((!tag.isEndTag()) && (!tag.isEmpty())) { + outText("\n\\begin{itemize}", buf, u); + } + else if (tag.isEndTag()) { + outText("\n\\end{itemize}", buf, u); + ++u->consecutiveNewlines; + u->supressAdjacentWhitespace = true; + } + } + + // <item> + else if (!strcmp(tag.getName(), "item")) { + if((!tag.isEndTag()) && (!tag.isEmpty())) { + outText("\n\\item ", buf, u); + } + else if (tag.isEndTag()) { + ++u->consecutiveNewlines; + u->supressAdjacentWhitespace = true; + } + } + // <catchWord> & <rdg> tags (italicize) + else if (!strcmp(tag.getName(), "rdg") || !strcmp(tag.getName(), "catchWord")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + outText("\\emph{", buf, u); + } + else if (tag.isEndTag()) { + outText("}", buf, u); + } + } + + // divineName + else if (!strcmp(tag.getName(), "divineName")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + outText( "\\sworddivinename{", buf, u); + u->suspendTextPassThru = (++u->suspendLevel); + } + else if (tag.isEndTag()) { + SWBuf lastText = u->lastSuspendSegment.c_str(); + u->suspendTextPassThru = (--u->suspendLevel); + if (lastText.size()) { + scratch.setFormatted("%s}", lastText.c_str()); + outText(scratch.c_str(), buf, u); + } + } + } + + // <hi> text highlighting + else if (!strcmp(tag.getName(), "hi")) { + SWBuf type = tag.getAttribute("type"); + + // handle tei rend attribute if type doesn't exist + if (!type.length()) type = tag.getAttribute("rend"); + + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + if (type == "bold" || type == "b" || type == "x-b") { + outText("\\textbold{", buf, u); + } + + // there is no officially supported OSIS overline attribute, + // thus either TEI overline or OSIS x-overline would be best, + // but we have used "ol" in the past, as well. Once a valid + // OSIS overline attribute is made available, these should all + // eventually be deprecated and never documented that they are supported. + else if (type == "ol" || type == "overline" || type == "x-overline") { + outText("\\textoverline{", buf, u); + } + + else if (type == "super") { + outText("\\textsuperscript{", buf, u); + } + else if (type == "sub") { + outText("\\textsubscript{", buf, u); + } + else { // all other types + outText("\\emph {", buf, u); + } + u->hiStack->push(tag.toString()); + } + else if (tag.isEndTag()) { + outText("}", buf, u); + } + } + + // <q> quote + // Rules for a quote element: + // If the tag is empty with an sID or an eID then use whatever it specifies for quoting. + // Note: empty elements without sID or eID are ignored. + // If the tag is <q> then use it's specifications and push it onto a stack for </q> + // If the tag is </q> then use the pushed <q> for specification + // If there is a marker attribute, possibly empty, this overrides osisQToTick. + // If osisQToTick, then output the marker, using level to determine the type of mark. + else if (!strcmp(tag.getName(), "q")) { + SWBuf type = tag.getAttribute("type"); + SWBuf who = tag.getAttribute("who"); + const char *tmp = tag.getAttribute("level"); + int level = (tmp) ? atoi(tmp) : 1; + tmp = tag.getAttribute("marker"); + bool hasMark = tmp; + SWBuf mark = tmp; + + // open <q> or <q sID... /> + if ((!tag.isEmpty() && !tag.isEndTag()) || (tag.isEmpty() && tag.getAttribute("sID"))) { + // if <q> then remember it for the </q> + if (!tag.isEmpty()) { + u->quoteStack->push(tag.toString()); + } + + // Do this first so quote marks are included as WoC + if (who == "Jesus") + outText(u->wordsOfChristStart, buf, u); + + // first check to see if we've been given an explicit mark + if (hasMark) + outText(mark, buf, u); + //alternate " and ' + else if (u->osisQToTick) + outText((level % 2) ? '\"' : '\'', buf, u); + } + // close </q> or <q eID... /> + else if ((tag.isEndTag()) || (tag.isEmpty() && tag.getAttribute("eID"))) { + // if it is </q> then pop the stack for the attributes + if (tag.isEndTag() && !u->quoteStack->empty()) { + XMLTag qTag(u->quoteStack->top()); + if (u->quoteStack->size()) u->quoteStack->pop(); + + type = qTag.getAttribute("type"); + who = qTag.getAttribute("who"); + tmp = qTag.getAttribute("level"); + level = (tmp) ? atoi(tmp) : 1; + tmp = qTag.getAttribute("marker"); + hasMark = tmp; + mark = tmp; + } + + // first check to see if we've been given an explicit mark + if (hasMark) + outText(mark, buf, u); + // finally, alternate " and ', if config says we should supply a mark + else if (u->osisQToTick) + outText((level % 2) ? '\"' : '\'', buf, u); + + // Do this last so quote marks are included as WoC + if (who == "Jesus") + outText(u->wordsOfChristEnd, buf, u); + } + } + + // <transChange> + else if (!strcmp(tag.getName(), "transChange")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + SWBuf type = tag.getAttribute("type"); + u->lastTransChange = type; + + // just do all transChange tags this way for now + if ((type == "added") || (type == "supplied")) + outText("\\swordtranschange{supplied}{", buf, u); + else if (type == "tenseChange") + outText( "\\swordtranschange{tense}{", buf, u); + } + else if (tag.isEndTag()) { + outText("}", buf, u); + } + else { // empty transChange marker? + } + } + + // image + else if (!strcmp(tag.getName(), "figure")) { + const char *src = tag.getAttribute("src"); + if (src) { // assert we have a src attribute + SWBuf filepath; + if (userData->module) { + filepath = userData->module->getConfigEntry("AbsoluteDataPath"); + if ((filepath.size()) && (filepath[filepath.size()-1] != '/') && (src[0] != '/')) + filepath += '/'; + } + filepath += src; + + outText("\\figure{", buf, u); + outText("\\includegraphics{", buf, u); + outText(filepath.c_str(), buf, u); + outText("}}", buf, u); + + } + } + + // ok to leave these in + else if (!strcmp(tag.getName(), "div")) { + SWBuf type = tag.getAttribute("type"); + if (type == "module") { + u->divLevel = type; + outText("\n", buf, u); + } + else if (type == "testament") { + u->divLevel = type; + outText("\n", buf, u); + } + else if (type == "bookGroup") { + u->divLevel = type; + outText("\n", buf, u); + } + else if (type == "book") { + u->divLevel = type; + outText("\n", buf, u); + } + else if (type == "majorSection") { + u->divLevel = type; + outText("\n", buf, u); + } + else if (type == "section") { + u->divLevel = type; + outText("\n", buf, u); + } + else if (type == "paragraph") { + u->divLevel = type; + outText("\n", buf, u); + } + } + else if (!strcmp(tag.getName(), "span")) { + outText( "", buf, u); + } + else if (!strcmp(tag.getName(), "br")) { + outText( "\\", buf, u); + } + else if (!strcmp(tag.getName(), "table")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + outText( "\n\\begin{tabular}", buf, u); + } + else if (tag.isEndTag()) { + outText( "\n\\end{tabular}", buf, u); + ++u->consecutiveNewlines; + u->supressAdjacentWhitespace = true; + } + + } + else if (!strcmp(tag.getName(), "row")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + outText( "\n", buf, u); + u->firstCell = true; + } + else if (tag.isEndTag()) { + outText( "//", buf, u); + u->firstCell = false; + } + + } + else if (!strcmp(tag.getName(), "cell")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + if (u->firstCell == false) { + outText( " & ", buf, u); + } + else { + u->firstCell = false; + } + } + else if (tag.isEndTag()) { + outText( "", buf, u); + } + } + else { + if (!u->supressAdjacentWhitespace) u->consecutiveNewlines = 0; + return false; // we still didn't handle token + } + } + if (!u->supressAdjacentWhitespace) u->consecutiveNewlines = 0; + return true; +} + + +SWORD_NAMESPACE_END diff --git a/src/modules/filters/osislemma.cpp b/src/modules/filters/osislemma.cpp index cf5d8f4..12881ff 100644 --- a/src/modules/filters/osislemma.cpp +++ b/src/modules/filters/osislemma.cpp @@ -3,7 +3,7 @@ * osislemma.cpp - SWFilter descendant to hide or show lemmata * in a OSIS module * - * $Id: osislemma.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: osislemma.cpp 3483 2017-06-25 15:19:34Z scribe $ * * Copyright 2003-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -67,6 +67,15 @@ char OSISLemma::processText(SWBuf &text, const SWKey *key, const SWModule *modul intoken = false; if (token.startsWith("w ")) { // Word XMLTag wtag(token); + + // always save off lemma if we haven't yet + if (!wtag.getAttribute("savlm")) { + const char *l = wtag.getAttribute("lemma"); + if (l) { + wtag.setAttribute("savlm", l); + } + } + int count = wtag.getAttributePartCount("lemma", ' '); for (int i = 0; i < count; i++) { SWBuf a = wtag.getAttribute("lemma", i, ' '); @@ -78,6 +87,7 @@ char OSISLemma::processText(SWBuf &text, const SWKey *key, const SWModule *modul count--; } } + token = wtag; token.trim(); // drop <> diff --git a/src/modules/filters/osismorph.cpp b/src/modules/filters/osismorph.cpp index 71de8e5..4ccf15b 100644 --- a/src/modules/filters/osismorph.cpp +++ b/src/modules/filters/osismorph.cpp @@ -3,7 +3,7 @@ * osismorph.cpp - SWFilter descendant to hide or show morph tags * in a OSIS module * - * $Id: osismorph.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: osismorph.cpp 3427 2016-07-03 14:30:33Z scribe $ * * Copyright 2003-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -90,11 +90,12 @@ char OSISMorph::processText(SWBuf &text, const SWKey *key, const SWModule *modul continue; } if (intoken) { - if (tokpos < 2045) + if (tokpos < 2045) { token[tokpos++] = *from; token[tokpos] = 0; + } } - else { + else { text.append(*from); } } diff --git a/src/modules/filters/osismorphsegmentation.cpp b/src/modules/filters/osismorphsegmentation.cpp index 1d91428..0e5c1cc 100644 --- a/src/modules/filters/osismorphsegmentation.cpp +++ b/src/modules/filters/osismorphsegmentation.cpp @@ -4,7 +4,7 @@ * morphemes (for morpheme segmented Hebrew in * the WLC) * - * $Id: osismorphsegmentation.cpp 3186 2014-04-17 04:33:19Z greg.hellings $ + * $Id: osismorphsegmentation.cpp 3153 2014-04-14 16:22:11Z scribe $ * * Copyright 2006-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society diff --git a/src/modules/filters/osisosis.cpp b/src/modules/filters/osisosis.cpp index 2bc5cbb..f3dca3a 100644 --- a/src/modules/filters/osisosis.cpp +++ b/src/modules/filters/osisosis.cpp @@ -2,7 +2,7 @@ * * osisosis.cpp - internal OSIS to public OSIS filter * - * $Id: osisosis.cpp 2833 2013-06-29 06:40:28Z chrislit $ + * $Id: osisosis.cpp 3338 2015-03-12 20:04:06Z refdoc $ * * Copyright 2004-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -58,39 +58,28 @@ char OSISOSIS::processText(SWBuf &text, const SWKey *key, const SWModule *module char status = SWBasicFilter::processText(text, key, module); VerseKey *vkey = SWDYNAMIC_CAST(VerseKey, key); if (vkey) { - SWBuf ref = ""; if (vkey->getVerse()) { - ref.appendFormatted("\t\t<verse osisID=\"%s\">", vkey->getOSISRef()); - } - - if (ref.length() > 0) { - - text = ref + text; - - if (vkey->getVerse()) { - VerseKey *tmp = (VerseKey *)vkey->clone(); - *tmp = *vkey; - tmp->setAutoNormalize(false); - tmp->setIntros(true); - - text += "</verse>"; - + VerseKey *tmp = (VerseKey *)vkey->clone(); + *tmp = *vkey; + tmp->setAutoNormalize(false); + tmp->setIntros(true); + + *tmp = MAXVERSE; + if (*vkey == *tmp) { + tmp->setVerse(0); +// sprintf(ref, "\t</div>"); +// pushString(&to, ref); + *tmp = MAXCHAPTER; *tmp = MAXVERSE; if (*vkey == *tmp) { + tmp->setChapter(0); tmp->setVerse(0); // sprintf(ref, "\t</div>"); // pushString(&to, ref); - *tmp = MAXCHAPTER; - *tmp = MAXVERSE; - if (*vkey == *tmp) { - tmp->setChapter(0); - tmp->setVerse(0); -// sprintf(ref, "\t</div>"); -// pushString(&to, ref); - } } - delete tmp; } + delete tmp; + } // // else if (vkey->Chapter()) { @@ -98,7 +87,7 @@ char OSISOSIS::processText(SWBuf &text, const SWKey *key, const SWModule *module // } // else sprintf(ref, "\t<div type=\"book\" osisID=\"%s\">", vkey->getOSISRef()); // - } + } return status; } @@ -149,11 +138,12 @@ bool OSISOSIS::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *u else if (!strcmp(tag.getName(), "note")) { if (!tag.isEndTag()) { SWBuf type = tag.getAttribute("type"); + bool strongsMarkup = (type == "x-strongsMarkup" || type == "strongsMarkup"); // the latter is deprecated if (strongsMarkup) { tag.setEmpty(false); // handle bug in KJV2003 module where some note open tags were <note ... /> } - + if (!tag.isEmpty()) { tag.setAttribute("swordFootnote", 0); @@ -162,6 +152,13 @@ bool OSISOSIS::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *u } else u->suspendTextPassThru = true; } + + if (u->module) { + XMLTag tag = token; + SWBuf swordFootnote = tag.getAttribute("swordFootnote"); + SWBuf footnoteBody = u->module->getEntryAttributes()["Footnote"][swordFootnote]["body"]; + buf.append(u->module->renderText(footnoteBody)); + } } if (tag.isEndTag()) { if (u->suspendTextPassThru == false) diff --git a/src/modules/filters/osisplain.cpp b/src/modules/filters/osisplain.cpp index d594028..436d0c7 100644 --- a/src/modules/filters/osisplain.cpp +++ b/src/modules/filters/osisplain.cpp @@ -2,7 +2,7 @@ * * osisplain.cpp - An SWFilter that provides stripping of OSIS tags * - * $Id: osisplain.cpp 3290 2014-12-04 04:54:52Z greg.hellings $ + * $Id: osisplain.cpp 3548 2017-12-10 05:11:38Z scribe $ * * Copyright 2003-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -25,6 +25,8 @@ #include <ctype.h> #include <versekey.h> #include <stringmgr.h> +#include <utilxml.h> +#include <swmodule.h> SWORD_NAMESPACE_START @@ -35,7 +37,6 @@ namespace { public: SWBuf w; XMLTag tag; - VerseKey *vk; char testament; SWBuf hiType; MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) {} @@ -58,22 +59,35 @@ OSISPlain::OSISPlain() { addEscapeStringSubstitute("gt", ">"); addEscapeStringSubstitute("quot", "\""); - setTokenCaseSensitive(true); - addTokenSubstitute("title", "\n"); - addTokenSubstitute("/title", "\n"); - addTokenSubstitute("/l", "\n"); - addTokenSubstitute("lg", "\n"); - addTokenSubstitute("/lg", "\n"); + setTokenCaseSensitive(true); + addTokenSubstitute("title", "\n"); + addTokenSubstitute("/title", "\n"); + addTokenSubstitute("/l", "\n"); + addTokenSubstitute("lg", "\n"); + addTokenSubstitute("/lg", "\n"); + + setStageProcessing(PRECHAR); } + BasicFilterUserData *OSISPlain::createUserData(const SWModule *module, const SWKey *key) { MyUserData *u = new MyUserData(module, key); - u->vk = SWDYNAMIC_CAST(VerseKey, u->key); - u->testament = (u->vk) ? u->vk->getTestament() : 2; // default to NT + u->testament = (u->vkey) ? u->vkey->getTestament() : 2; // default to NT return u; } +bool OSISPlain::processStage(char stage, SWBuf &text, char *&from, BasicFilterUserData *userData) { + // this is a strip filter so we want to do this as optimized as possible. Avoid calling + // getUniCharFromUTF8 for slight speed improvement + + if (stage == PRECHAR) { + if (from[0] == 0xC2 && from[1] == 0xAD) return true; // skip soft hyphens + } + return false; +} + + bool OSISPlain::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) { // manually process if it wasn't a simple substitution if (!substituteToken(buf, token)) { @@ -105,10 +119,8 @@ bool OSISPlain::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * buf.append('>'); } if ((attrib = u->tag.getAttribute("gloss"))) { - val = strchr(attrib, ':'); - val = (val) ? (val + 1) : attrib; buf.append(" <"); - buf.append(val); + buf.append(attrib); buf.append('>'); } if ((attrib = u->tag.getAttribute("lemma"))) { @@ -168,6 +180,12 @@ bool OSISPlain::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * buf.append(" ["); } else u->suspendTextPassThru = true; + if (u->module) { + XMLTag tag = token; + SWBuf swordFootnote = tag.getAttribute("swordFootnote"); + SWBuf footnoteBody = u->module->getEntryAttributes()["Footnote"][swordFootnote]["body"]; + buf.append(u->module->renderText(footnoteBody)); + } } else if (!strncmp(token, "/note", 5)) { if (!u->suspendTextPassThru) @@ -234,12 +252,17 @@ bool OSISPlain::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * } } else { - buf.append("*"); + buf.append("* "); buf.append(u->lastSuspendSegment); - buf.append("*"); + buf.append(" *"); } u->suspendTextPassThru = false; } + + else if ((!strncmp(token, "q", 1) && (u->tag.getAttribute("marker")))) { + buf.append(u->tag.getAttribute("marker")); + } + // <milestone type="line"/> else if (!strncmp(token, "milestone", 9)) { @@ -248,6 +271,9 @@ bool OSISPlain::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * userData->supressAdjacentWhitespace = true; buf.append('\n'); } + if (u->tag.getAttribute("marker")) { + buf.append(u->tag.getAttribute("marker")); + } } else { diff --git a/src/modules/filters/osisreferencelinks.cpp b/src/modules/filters/osisreferencelinks.cpp index 83308e4..bb30517 100644 --- a/src/modules/filters/osisreferencelinks.cpp +++ b/src/modules/filters/osisreferencelinks.cpp @@ -3,7 +3,7 @@ * osisreferencelinks.cpp - SWFilter descendant to toggle OSIS reference * links with specified type/subType * - * $Id: osisreferencelinks.cpp 2995 2013-12-28 06:32:26Z greg.hellings $ + * $Id: osisreferencelinks.cpp 2989 2013-10-09 08:22:21Z chrislit $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society diff --git a/src/modules/filters/osisrtf.cpp b/src/modules/filters/osisrtf.cpp index 7bc5639..522a0a8 100644 --- a/src/modules/filters/osisrtf.cpp +++ b/src/modules/filters/osisrtf.cpp @@ -2,7 +2,7 @@ * * osisrtf.cpp - OSIS to RTF filter * - * $Id: osisrtf.cpp 3156 2014-04-17 03:50:37Z greg.hellings $ * + * $Id: osisrtf.cpp 3548 2017-12-10 05:11:38Z scribe $ * * * Copyright 2003-2014 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -36,7 +36,7 @@ namespace { class MyUserData : public BasicFilterUserData { public: bool osisQToTick; - bool BiblicalText; + bool isBiblicalText; bool inXRefNote; int suspendLevel; std::stack<char *> quoteStack; @@ -49,13 +49,14 @@ namespace { MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) { inXRefNote = false; - BiblicalText = false; + isBiblicalText = false; suspendLevel = 0; + osisQToTick = true; // default if (module) { version = module->getName(); - BiblicalText = (!strcmp(module->getType(), "Biblical Texts")); + isBiblicalText = (!strcmp(module->getType(), "Biblical Texts")); + osisQToTick = ((!module->getConfigEntry("OSISqToTick")) || (strcmp(module->getConfigEntry("OSISqToTick"), "false"))); } - osisQToTick = ((!module->getConfigEntry("OSISqToTick")) || (strcmp(module->getConfigEntry("OSISqToTick"), "false"))); } @@ -244,15 +245,9 @@ bool OSISRTF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *us && (type != "strongsMarkup") // deprecated ) { SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); - VerseKey *vkey = NULL; - // see if we have a VerseKey * or descendant - SWTRY { - vkey = SWDYNAMIC_CAST(VerseKey, u->key); - } - SWCATCH ( ... ) { } - if (vkey) { + if (u->vkey) { char ch = ((!strcmp(type.c_str(), "crossReference")) || (!strcmp(type.c_str(), "x-cross-ref"))) ? 'x':'n'; - scratch.setFormatted("{\\super <a href=\"\">*%c%i.%s</a>} ", ch, vkey->getVerse(), footnoteNumber.c_str()); + scratch.setFormatted("{\\super <a href=\"\">*%c%i.%s</a>} ", ch, u->vkey->getVerse(), footnoteNumber.c_str()); outText(scratch.c_str(), buf, u); u->inXRefNote = (ch == 'x'); } diff --git a/src/modules/filters/osisscripref.cpp b/src/modules/filters/osisscripref.cpp index 99d6709..ec188d9 100644 --- a/src/modules/filters/osisscripref.cpp +++ b/src/modules/filters/osisscripref.cpp @@ -3,7 +3,7 @@ * osisscripref.cpp - SWFilter descendant to hide or show scripture * references in an OSIS module * - * $Id: osisscripref.cpp 3156 2014-04-17 03:50:37Z greg.hellings $ + * $Id: osisscripref.cpp 3045 2014-03-02 07:53:52Z chrislit $ * * Copyright 2003-2014 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society diff --git a/src/modules/filters/osisstrongs.cpp b/src/modules/filters/osisstrongs.cpp index b937883..0c17446 100644 --- a/src/modules/filters/osisstrongs.cpp +++ b/src/modules/filters/osisstrongs.cpp @@ -3,7 +3,7 @@ * osisstrongs.cpp - SWFilter descendant to hide or show Strong's number * in a OSIS module * - * $Id: osisstrongs.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: osisstrongs.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2003-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -57,7 +57,7 @@ char OSISStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *mod SWBuf token; bool intoken = false; int wordNum = 1; - char wordstr[5]; + char wordstr[11]; const char *wordStart = 0; SWBuf page = ""; // some modules include <seg> page info, so we add these to the words @@ -88,6 +88,15 @@ char OSISStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *mod if (token.startsWith("w ")) { // Word XMLTag wtag(token); + + // always save off lemma if we haven't yet + if (!wtag.getAttribute("savlm")) { + const char *l = wtag.getAttribute("lemma"); + if (l) { + wtag.setAttribute("savlm", l); + } + } + if (module->isProcessEntryAttributes()) { wordStart = from+1; char gh = 0; @@ -117,7 +126,7 @@ char OSISStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *mod const char *m = strchr(attrib, ':'); if (m) { - int len = m-attrib; + int len = (int)(m-attrib); mClass.append(attrib, len); attrib += (len+1); } @@ -138,19 +147,19 @@ char OSISStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *mod } while (++i < count); } - if ((attrib = wtag.getAttribute("lemma"))) { - int count = wtag.getAttributePartCount("lemma", ' '); + if ((attrib = wtag.getAttribute("savlm"))) { + int count = wtag.getAttributePartCount("savlm", ' '); int i = (count > 1) ? 0 : -1; // -1 for whole value cuz it's faster, but does the same thing as 0 do { gh = 0; SWBuf lClass = ""; SWBuf l = ""; - attrib = wtag.getAttribute("lemma", i, ' '); + attrib = wtag.getAttribute("savlm", i, ' '); if (i < 0) i = 0; // to handle our -1 condition const char *m = strchr(attrib, ':'); if (m) { - int len = m-attrib; + int len = (int)(m-attrib); lClass.append(attrib, len); attrib += (len+1); } @@ -217,7 +226,7 @@ char OSISStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *mod if (wtag.isEmpty()) { int j; - for (j = token.length()-1; ((j>0) && (strchr(" /", token[j]))); j--); + for (j = (int)token.length()-1; ((j>0) && (strchr(" /", token[j]))); j--); token.size(j+1); } @@ -232,35 +241,27 @@ char OSISStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *mod wordNum++; } + // if we won't want strongs, then lets get them out of lemma if (!option) { -/* - * Code which handles multiple lemma types. Kindof works but breaks at least WEBIF filters for strongs. - * int count = wtag.getAttributePartCount("lemma", ' '); - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; ++i) { SWBuf a = wtag.getAttribute("lemma", i, ' '); const char *prefix = a.stripPrefix(':'); if ((prefix) && (!strcmp(prefix, "x-Strongs") || !strcmp(prefix, "strong") || !strcmp(prefix, "Strong"))) { // remove attribute part wtag.setAttribute("lemma", 0, i, ' '); - i--; - count--; + --i; + --count; } } -* Instead the codee below just removes the lemma attribute -*****/ - const char *l = wtag.getAttribute("lemma"); - if (l) { - SWBuf savlm = l; - wtag.setAttribute("lemma", 0); - wtag.setAttribute("savlm", savlm); - token = wtag; - token.trim(); - // drop <> - token << 1; - token--; - } + + } + token = wtag; + token.trim(); + // drop <> + token << 1; + token--; } if (token.startsWith("/w")) { // Word End if (module->isProcessEntryAttributes()) { diff --git a/src/modules/filters/osiswebif.cpp b/src/modules/filters/osiswebif.cpp index 4894777..2aa80a7 100644 --- a/src/modules/filters/osiswebif.cpp +++ b/src/modules/filters/osiswebif.cpp @@ -3,7 +3,7 @@ * osiswebif.cpp - OSIS to HTML filter with hrefs for strongs and * morph tags * - * $Id: osiswebif.cpp 3285 2014-12-03 06:14:50Z greg.hellings $ + * $Id: osiswebif.cpp 3548 2017-12-10 05:11:38Z scribe $ * * Copyright 2003-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -83,7 +83,7 @@ bool OSISWEBIF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * if ((attrib = tag.getAttribute("gloss"))) { val = strchr(attrib, ':'); val = (val) ? (val + 1) : attrib; - buf.appendFormatted(" %s", val); +// buf.appendFormatted(" %s", val); } if ((attrib = tag.getAttribute("lemma"))) { int count = tag.getAttributePartCount("lemma", ' '); @@ -144,15 +144,9 @@ bool OSISWEBIF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * if (!strongsMarkup) { // leave strong's markup notes out, in the future we'll probably have different option filters to turn different note types on or off SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); SWBuf modName = (u->module) ? u->module->getName() : ""; - VerseKey *vkey = NULL; - // see if we have a VerseKey * or descendant - SWTRY { - vkey = SWDYNAMIC_CAST(VerseKey, u->key); - } - SWCATCH ( ... ) { } - if (vkey) { + if (u->vkey) { char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); -// buf.appendFormatted("<a href=\"noteID=%s.%c.%s\"><small><sup>*%c</sup></small></a> ", vkey->getText(), ch, footnoteNumber.c_str(), ch); +// buf.appendFormatted("<a href=\"noteID=%s.%c.%s\"><small><sup>*%c</sup></small></a> ", u->vkey->getText(), ch, footnoteNumber.c_str(), ch); buf.appendFormatted("<span class=\"fn\" onclick=\"f(\'%s\',\'%s\',\'%s\');\" >%c</span>", modName.c_str(), u->key->getText(), footnoteNumber.c_str(), ch); } } diff --git a/src/modules/filters/osiswordjs.cpp b/src/modules/filters/osiswordjs.cpp index 75946a8..2da57c9 100644 --- a/src/modules/filters/osiswordjs.cpp +++ b/src/modules/filters/osiswordjs.cpp @@ -2,7 +2,7 @@ * * osiswordjs.cpp - SWFilter descendant for ??? * - * $Id: osiswordjs.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: osiswordjs.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2005-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -66,7 +66,7 @@ char OSISWordJS::processText(SWBuf &text, const SWKey *key, const SWModule *modu int tokpos = 0; bool intoken = false; int wordNum = 1; - char wordstr[5]; + char wordstr[11]; SWBuf modName = (module)?module->getName():""; // add TR to w src in KJV then remove this next line SWBuf wordSrcPrefix = (modName == "KJV")?SWBuf("TR"):modName; @@ -171,6 +171,10 @@ char OSISWordJS::processText(SWBuf &text, const SWKey *key, const SWModule *modu // 'p' = 'fillpop' to save bandwidth text.appendFormatted("<span class=\"clk\" onclick=\"p('%s','%s','%s','%s','%s','%s');\" >", lexName.c_str(), lemma.c_str(), wordID.c_str(), morph.c_str(), page.c_str(), modName.c_str()); wordNum++; + + if (wtag.isEmpty()) { + text += "</w></span>"; + } } if ((*token == '/') && (token[1] == 'w') && option) { // Word text += "</w></span>"; @@ -185,9 +189,10 @@ char OSISWordJS::processText(SWBuf &text, const SWKey *key, const SWModule *modu continue; } if (intoken) { - if (tokpos < 2045) + if (tokpos < 2045) { token[tokpos++] = *from; token[tokpos+2] = 0; + } } else { text.append(*from); diff --git a/src/modules/filters/osisxhtml.cpp b/src/modules/filters/osisxhtml.cpp index fb743e2..bfdb123 100644 --- a/src/modules/filters/osisxhtml.cpp +++ b/src/modules/filters/osisxhtml.cpp @@ -2,7 +2,7 @@ * * osisxhtml.cpp - Render filter for classed XHTML of an OSIS module * - * $Id: osisxhtml.cpp 3290 2014-12-04 04:54:52Z greg.hellings $ + * $Id: osisxhtml.cpp 3548 2017-12-10 05:11:38Z scribe $ * * Copyright 2011-2014 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -37,15 +37,25 @@ const char *OSISXHTML::getHeader() const { const static char *header = "\ .divineName { font-variant: small-caps; }\n\ .wordsOfJesus { color: red; }\n\ - .transChangeSupplied { font-style: italic; }\n\ - .overline { text-decoration: overline; }\n\ - .indent1 { margin-left: 10px }\n\ - .indent2 { margin-left: 20px }\n\ - .indent3 { margin-left: 30px }\n\ - .indent4 { margin-left: 40px }\n\ + .transChange { font-style: italic; }\n\ + .transChange.transChange-supplied { font-style: italic; }\n\ + .transChange.transChange-added { font-style: italic; }\n\ + .transChange.transChange-tenseChange::before { content: '*'; }\n\ + .transChange.transChange-tenseChange { font-style: normal; }\n\ + .transChange:lang(zh) { font-style: normal; text-decoration: dotted underline; }\n\ + .overline { text-decoration: overline; }\n\ + .indent1 { margin-left: 1em; }\n\ + .indent2 { margin-left: 2em; }\n\ + .indent3 { margin-left: 3em; }\n\ + .indent4 { margin-left: 4em; }\n\ + abbr { &:hover{ &:before{ content: attr(title); } } }\n\ .small-caps { font-variant: small-caps; }\n\ .selah { text-align: right; width: 50%; margin: 0; padding: 0; }\n\ .acrostic { text-align: center; }\n\ + .colophon {font-style: italic; font-size: small; display: block; }\n\ + .rdg { font-style: italic; }\n\ + .catchWord {font-style: bold; }\n\ + .x-p-indent {text-indent: 1em; }\n\ "; // Acrostic for things like the titles in Psalm 119 return header; @@ -67,14 +77,19 @@ void processLemma(bool suspendTextPassThru, XMLTag &tag, SWBuf &buf) { int i = (count > 1) ? 0 : -1; // -1 for whole value cuz it's faster, but does the same thing as 0 do { attrib = tag.getAttribute("lemma", i, ' '); + SWBuf at = attrib; + const char *prefix = at.stripPrefix(':'); if (i < 0) i = 0; // to handle our -1 condition val = strchr(attrib, ':'); val = (val) ? (val + 1) : attrib; SWBuf gh; - if(*val == 'G') + if (*val == 'G') { gh = "Greek"; - if(*val == 'H') + } + else if (*val == 'H') { gh = "Hebrew"; + } + else if (prefix) gh = prefix; const char *val2 = val; if ((strchr("GH", *val)) && (isdigit(val[1]))) val2++; @@ -82,7 +97,7 @@ void processLemma(bool suspendTextPassThru, XMLTag &tag, SWBuf &buf) { // show = false; //else { if (!suspendTextPassThru) { - buf.appendFormatted("<small><em class=\"strongs\"><<a href=\"passagestudy.jsp?action=showStrongs&type=%s&value=%s\" class=\"strongs\">%s</a>></em></small>", + buf.appendFormatted("<small><em class=\"strongs\"><<a class=\"strongs\" href=\"passagestudy.jsp?action=showStrongs&type=%s&value=%s\" class=\"strongs\">%s</a>></em></small>", (gh.length()) ? gh.c_str() : "", URL::encode(val2).c_str(), val2); @@ -114,7 +129,7 @@ void processMorph(bool suspendTextPassThru, XMLTag &tag, SWBuf &buf) { if ((*val == 'T') && (strchr("GH", val[1])) && (isdigit(val[2]))) val2+=2; if (!suspendTextPassThru) { - buf.appendFormatted("<small><em class=\"morph\">(<a href=\"passagestudy.jsp?action=showMorph&type=%s&value=%s\" class=\"morph\">%s</a>)</em></small>", + buf.appendFormatted("<small><em class=\"morph\">(<a class=\"morph\" href=\"passagestudy.jsp?action=showMorph&type=%s&value=%s\" class=\"morph\">%s</a>)</em></small>", URL::encode(tag.getAttribute("morph")).c_str(), URL::encode(val).c_str(), val2); @@ -165,18 +180,16 @@ OSISXHTML::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : Ba suspendLevel = 0; wordsOfChristStart = "<span class=\"wordsOfJesus\"> "; wordsOfChristEnd = "</span> "; - interModuleLinkStart = "<a href=\"sword://%s/%s\">"; + interModuleLinkStart = "<a class=\"%s\" href=\"sword://%s/%s\">"; interModuleLinkEnd = "</a>"; + isBiblicalText = false; + osisQToTick = true; // default + consecutiveNewlines = 0; if (module) { osisQToTick = ((!module->getConfigEntry("OSISqToTick")) || (strcmp(module->getConfigEntry("OSISqToTick"), "false"))); version = module->getName(); - BiblicalText = (!strcmp(module->getType(), "Biblical Texts")); + isBiblicalText = (!strcmp(module->getType(), "Biblical Texts")); } - else { - osisQToTick = true; // default - version = ""; - } - consecutiveNewlines = 0; } OSISXHTML::MyUserData::~MyUserData() { @@ -186,9 +199,17 @@ OSISXHTML::MyUserData::~MyUserData() { delete lineStack; } + void OSISXHTML::MyUserData::outputNewline(SWBuf &buf) { if (++consecutiveNewlines <= 2) { - outText("<br />\n", buf, this); + // any newlines at the start of a verse should get appended to a preverse heading + // since preverse cause a newline, simply be sure we have a preverse + if (!buf.size() && vkey && vkey->getVerse() && module && module->isProcessEntryAttributes()) { + module->getEntryAttributes()["Heading"]["Preverse"]["0"] += "<div></div>"; + } + else { + outText("<br />\n", buf, this); + } supressAdjacentWhitespace = true; } } @@ -235,9 +256,9 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * outText("<ruby><rb>", buf, u); outText(lastText, buf, u); + outText("</rb><rp>(</rp><rt>", buf, u); val = strchr(attrib, ':'); val = (val) ? (val + 1) : attrib; - outText("</rb><rp>(</rp><rt>", buf, u); outText(val, buf, u); outText("</rt><rp>)</rp></ruby>", buf, u); } @@ -257,7 +278,7 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * } /*if (endTag) - buf += "}";*/ + outText( "}", buf, u);*/ } } @@ -265,6 +286,16 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * else if (!strcmp(tag.getName(), "note")) { if (!tag.isEndTag()) { SWBuf type = tag.getAttribute("type"); + SWBuf subType = tag.getAttribute("subType"); + SWBuf classExtras = ""; + + if (type.size()) { + classExtras.append(" ").append(type); + } + if (subType.size()) { + classExtras.append(" ").append(subType); + } + bool strongsMarkup = (type == "x-strongsMarkup" || type == "strongsMarkup"); // the latter is deprecated if (strongsMarkup) { tag.setEmpty(false); // handle bug in KJV2003 module where some note open tags were <note ... /> @@ -275,30 +306,26 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * if (!strongsMarkup) { // leave strong's markup notes out, in the future we'll probably have different option filters to turn different note types on or off SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); SWBuf noteName = tag.getAttribute("n"); - VerseKey *vkey = NULL; char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); u->inXRefNote = true; // Why this change? Ben Morgan: Any note can have references in, so we need to set this to true for all notes // u->inXRefNote = (ch == 'x'); - // see if we have a VerseKey * or descendant - SWTRY { - vkey = SWDYNAMIC_CAST(VerseKey, u->key); - } - SWCATCH ( ... ) { } - if (vkey) { - //printf("URL = %s\n",URL::encode(vkey->getText()).c_str()); - buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=%c&value=%s&module=%s&passage=%s\"><small><sup class=\"%c\">*%c%s</sup></small></a>", + if (u->vkey) { + //printf("URL = %s\n",URL::encode(u->vkey->getText()).c_str()); + buf.appendFormatted("<a class=\"%s\" href=\"passagestudy.jsp?action=showNote&type=%c&value=%s&module=%s&passage=%s\"><small><sup class=\"%c\">*%c%s</sup></small></a>", + classExtras.c_str(), ch, URL::encode(footnoteNumber.c_str()).c_str(), URL::encode(u->version.c_str()).c_str(), - URL::encode(vkey->getText()).c_str(), + URL::encode(u->vkey->getText()).c_str(), ch, ch, (renderNoteNumbers ? noteName.c_str() : "")); } else { - buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=%c&value=%s&module=%s&passage=%s\"><small><sup class=\"%c\">*%c%s</sup></small></a>", + buf.appendFormatted("<a class=\"%s\" href=\"passagestudy.jsp?action=showNote&type=%c&value=%s&module=%s&passage=%s\"><small><sup class=\"%c\">*%c%s</sup></small></a>", + classExtras.c_str(), ch, URL::encode(footnoteNumber.c_str()).c_str(), URL::encode(u->version.c_str()).c_str(), @@ -314,11 +341,11 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * if (tag.isEndTag()) { u->suspendTextPassThru = (--u->suspendLevel); u->inXRefNote = false; - u->lastSuspendSegment = ""; // fix/work-around for nasb devineName in note bug + u->lastSuspendSegment = ""; // fix/work-around for nasb divineName in note bug } } - // <p> paragraph and <lg> linegroup tags + // <p> paragraph and <lg> linegroup tags except newline at start of verse (immediately after verse number) else if (!strcmp(tag.getName(), "p") || !strcmp(tag.getName(), "lg")) { if ((!tag.isEndTag()) && (!tag.isEmpty())) { // non-empty start tag u->outputNewline(buf); @@ -334,14 +361,24 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * // Milestoned paragraphs, created by osis2mod // <div type="paragraph" sID.../> // <div type="paragraph" eID.../> - else if (tag.isEmpty() && !strcmp(tag.getName(), "div") && tag.getAttribute("type") && (!strcmp(tag.getAttribute("type"), "x-p") || !strcmp(tag.getAttribute("type"), "paragraph"))) { + else if (tag.isEmpty() && !strcmp(tag.getName(), "div") && tag.getAttribute("type") && (!strcmp(tag.getAttribute("type"), "x-p") || !strcmp(tag.getAttribute("type"), "paragraph") || !strcmp(tag.getAttribute("type"), "colophon"))) { // <div type="paragraph" sID... /> if (tag.getAttribute("sID")) { // non-empty start tag u->outputNewline(buf); + // safe because we've verified type is present from if statement above + if (!strcmp(tag.getAttribute("type"), "colophon")) { + outText("<div class=\"colophon\">", buf, u); + } + } // <div type="paragraph" eID... /> else if (tag.getAttribute("eID")) { u->outputNewline(buf); + // safe because we've verified type is present from if statement above + if (!strcmp(tag.getAttribute("type"), "colophon")) { + outText("</div>", buf, u); + } + } } @@ -352,10 +389,18 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * SWBuf target; SWBuf work; SWBuf ref; + SWBuf type; + SWBuf classes = ""; + bool is_scripRef = false; target = tag.getAttribute("osisRef"); const char* the_ref = strchr(target, ':'); + type = tag.getAttribute("type"); + + if (type.size()) { + classes.append(type); + } if(!the_ref) { // No work @@ -377,7 +422,8 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * if(is_scripRef) { - buf.appendFormatted("<a href=\"passagestudy.jsp?action=showRef&type=scripRef&value=%s&module=\">", + buf.appendFormatted("<a class=\"%s\" href=\"passagestudy.jsp?action=showRef&type=scripRef&value=%s&module=\">", + classes.c_str(), URL::encode(ref.c_str()).c_str() // (work.size()) ? URL::encode(work.c_str()).c_str() : "") ); @@ -385,7 +431,8 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * else { // Dictionary link, or something - buf.appendFormatted(u->interModuleLinkStart, + buf.appendFormatted(u->interModuleLinkStart, + classes.c_str(), URL::encode(work.c_str()).c_str(), URL::encode(ref.c_str()).c_str() ); @@ -440,18 +487,20 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * // <milestone type="x-p"/> // <milestone type="cQuote" marker="x"/> else if ((!strcmp(tag.getName(), "milestone")) && (tag.getAttribute("type"))) { - if (!strcmp(tag.getAttribute("type"), "line")) { + // safe because we've verified type is present from if statement above + const char *type = tag.getAttribute("type"); + if (!strcmp(type, "line")) { u->outputNewline(buf); if (tag.getAttribute("subType") && !strcmp(tag.getAttribute("subType"), "x-PM")) { u->outputNewline(buf); } } - else if (!strcmp(tag.getAttribute("type"),"x-p")) { + else if (!strcmp(type,"x-p")) { if (tag.getAttribute("marker")) outText(tag.getAttribute("marker"), buf, u); else outText("<!p>", buf, u); } - else if (!strcmp(tag.getAttribute("type"), "cQuote")) { + else if (!strcmp(type, "cQuote")) { const char *tmp = tag.getAttribute("marker"); bool hasMark = tmp; SWBuf mark = tmp; @@ -465,41 +514,55 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * else if (u->osisQToTick) outText((level % 2) ? '\"' : '\'', buf, u); } + else if (!strcmp(type, "x-importer")) { + //drop tag as not relevant + } + + + else { + SWBuf type = tag.getAttribute("type"); + outText(SWBuf("<span class=\"") + type + "\"/>", buf,u); + } } // <title> else if (!strcmp(tag.getName(), "title")) { if ((!tag.isEndTag()) && (!tag.isEmpty())) { SWBuf type = tag.getAttribute("type"); - bool keepType = false; + SWBuf canonical = tag.getAttribute("canonical"); + + SWBuf classExtras = ""; + if (type.size()) { - keepType = true; - } - VerseKey *vkey = SWDYNAMIC_CAST(VerseKey, u->key); - if (vkey && !vkey->getVerse()) { - if (!vkey->getChapter()) { - if (!vkey->getBook()) { - if (!vkey->getTestament()) { - buf += SWBuf("<h1 class=\"moduleHeader ") + (keepType ? type : "") + "\">"; + classExtras.append(" ").append(type); + } + if (canonical.size() && !strcmp(canonical,"true")) { + classExtras.append(" canonical"); + } + if (u->vkey && !u->vkey->getVerse()) { + if (!u->vkey->getChapter()) { + if (!u->vkey->getBook()) { + if (!u->vkey->getTestament()) { + outText(SWBuf("<h1 class=\"moduleHeader") + classExtras + "\">", buf, u); tag.setAttribute("pushed", "h1"); } else { - buf += SWBuf("<h1 class=\"testamentHeader ") + (keepType ? type : "") + "\">"; + outText(SWBuf("<h1 class=\"testamentHeader") + classExtras + "\">", buf, u); tag.setAttribute("pushed", "h1"); } } else { - buf += SWBuf("<h1 class=\"bookHeader ") + (keepType ? type : "") + "\">"; + outText(SWBuf("<h1 class=\"bookHeader") + classExtras + "\">", buf, u); tag.setAttribute("pushed", "h1"); } } else { - buf += SWBuf("<h2 class=\"chapterHeader ") + (keepType ? type : "") + "\">"; + outText(SWBuf("<h2 class=\"chapterHeader") + classExtras + "\">", buf, u); tag.setAttribute("pushed", "h2"); } } else { - buf += SWBuf("<h3 class=\"") + (keepType ? type : "") + "\">"; + outText(SWBuf("<h3 class=\"title") + classExtras + "\">", buf, u); tag.setAttribute("pushed", "h3"); } u->titleStack->push(tag.toString()); @@ -510,10 +573,10 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * if (u->titleStack->size()) u->titleStack->pop(); SWBuf pushed = tag.getAttribute("pushed"); if (pushed.size()) { - buf += (SWBuf)"</" + pushed + ">\n\n"; + outText((SWBuf)"</" + pushed + ">\n\n", buf, u); } else { - buf += "</h3>\n\n"; + outText( "</h3>\n\n", buf, u); } ++u->consecutiveNewlines; u->supressAdjacentWhitespace = true; @@ -547,10 +610,12 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * // <catchWord> & <rdg> tags (italicize) else if (!strcmp(tag.getName(), "rdg") || !strcmp(tag.getName(), "catchWord")) { if ((!tag.isEndTag()) && (!tag.isEmpty())) { - outText("<i>", buf, u); + outText("<span class=\"", buf, u); + outText(tag.getName(), buf, u); + outText("\">", buf, u); } else if (tag.isEndTag()) { - outText("</i>", buf, u); + outText("</span>", buf, u); } } @@ -617,7 +682,7 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * else if (type == "ol") { outText("</span>", buf, u); } - else if (type == "sup") { + else if (type == "super") { outText("</sup>", buf, u); } else if (type == "sub") { @@ -700,17 +765,16 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * if ((!tag.isEndTag()) && (!tag.isEmpty())) { SWBuf type = tag.getAttribute("type"); u->lastTransChange = type; - - // just do all transChange tags this way for now - if ((type == "added") || (type == "supplied")) - outText("<span class=\"transChangeSupplied\">", buf, u); - else if (type == "tenseChange") - buf += "*"; + + outText("<span class=\"transChange", buf, u); + if (type.length()) { + outText(" transChange-", buf, u); + outText(type, buf, u); + } + outText("\">", buf, u); } else if (tag.isEndTag()) { - SWBuf type = u->lastTransChange; - if ((type == "added") || (type == "supplied")) - outText("</span>", buf, u); + outText("</span>", buf, u); } else { // empty transChange marker? } @@ -754,22 +818,42 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * } else if (type == "majorSection") { } - else { - buf += tag; + else if ((!tag.isEndTag()) && (!tag.isEmpty())) { + SWBuf type = tag.getAttribute("type"); + outText("<div class=\"", buf, u); + outText(type, buf, u); + outText("\">", buf, u); + } + else if (tag.isEndTag()) { + outText("</div>", buf, u); } + else if (!(type == "colophon")) outText(tag, buf, u); + } else if (!strcmp(tag.getName(), "span")) { - buf += tag; + outText(tag, buf, u); + } + else if (!strcmp(tag.getName(), "abbr")) { + if (!tag.isEndTag()) { + SWBuf title = tag.getAttribute("expansion"); + outText("<abbr title=\"", buf, u); + outText(title, buf, u); + outText("\">", buf, u); + } + else if (tag.isEndTag()) { + outText("</abbr>", buf, u); + } + } else if (!strcmp(tag.getName(), "br")) { - buf += tag; + outText( tag, buf, u); } else if (!strcmp(tag.getName(), "table")) { if ((!tag.isEndTag()) && (!tag.isEmpty())) { - buf += "<table><tbody>\n"; + outText( "<table><tbody>\n", buf, u); } else if (tag.isEndTag()) { - buf += "</tbody></table>\n"; + outText( "</tbody></table>\n", buf, u); ++u->consecutiveNewlines; u->supressAdjacentWhitespace = true; } @@ -777,19 +861,19 @@ bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * } else if (!strcmp(tag.getName(), "row")) { if ((!tag.isEndTag()) && (!tag.isEmpty())) { - buf += "\t<tr>"; + outText( "\t<tr>", buf, u); } else if (tag.isEndTag()) { - buf += "</tr>\n"; + outText( "</tr>\n", buf, u); } } else if (!strcmp(tag.getName(), "cell")) { if ((!tag.isEndTag()) && (!tag.isEmpty())) { - buf += "<td>"; + outText( "<td>", buf, u); } else if (tag.isEndTag()) { - buf += "</td>"; + outText( "</td>", buf, u); } } else { diff --git a/src/modules/filters/rtfhtml.cpp b/src/modules/filters/rtfhtml.cpp index df02f38..81a38ea 100644 --- a/src/modules/filters/rtfhtml.cpp +++ b/src/modules/filters/rtfhtml.cpp @@ -2,7 +2,7 @@ * * rtfhtml.cpp - filter to convert RTF to HTML * - * $Id: rtfhtml.cpp 2981 2013-09-15 00:05:26Z scribe $ + * $Id: rtfhtml.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 1999 The team of Bibletime (info@bibletime.de) * Copyright 2000-2013 CrossWire Bible Society (http://www.crosswire.org) @@ -55,7 +55,7 @@ char RTFHTML::processText(SWBuf &text, const SWKey *key, const SWModule *module) num.append(from, end-from); __s16 n = atoi(num.c_str()); __u32 u = (__u16)n; - text.append(getUTF8FromUniChar(u)); + getUTF8FromUniChar(u, &text); from += (end-from); continue; } diff --git a/src/modules/filters/scsuutf8.cpp b/src/modules/filters/scsuutf8.cpp index c68ea1f..73e4a3f 100644 --- a/src/modules/filters/scsuutf8.cpp +++ b/src/modules/filters/scsuutf8.cpp @@ -3,9 +3,9 @@ * scsuutf8.cpp - SWFilter descendant to convert a SCSU character to * UTF-8 * - * $Id: scsuutf8.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: scsuutf8.cpp 3472 2017-05-22 04:19:02Z scribe $ * - * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) + * Copyright 2001-2014 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society * P. O. Box 2528 * Tempe, AZ 85280-2528 @@ -23,223 +23,240 @@ /* This class is based on: * http://czyborra.com/scsu/scsu.c written by Roman Czyborra@dds.nl - * on Andrea's balcony in North Amsterdam on 1998-08-04 - * Thanks to Richard Verhoeven <rcb5@win.tue.nl> for his suggestion - * to correct the haphazard "if" after UQU to "else if" on 1998-10-01 - * + * * This is a deflator to UTF-8 output for input compressed in SCSU, * the (Reuters) Standard Compression Scheme for Unicode as described * in http://www.unicode.org/unicode/reports/tr6.html */ -#include <stdlib.h> -#include <stdio.h> -#include <swmodule.h> - #include <scsuutf8.h> +#include <swbuf.h> +#ifdef _ICU_ +#include <unicode/unistr.h> +#endif + SWORD_NAMESPACE_START SCSUUTF8::SCSUUTF8() { +#ifdef _ICU_ + // initialize SCSU converter + scsuConv = ucnv_open("SCSU", &err); + // initialize UTF-8 converter + utf8Conv = ucnv_open("UTF-8", &err); +#else + active = 0; + mode = 0; +#endif } - -unsigned char* SCSUUTF8::UTF8Output(unsigned long uchar, unsigned char* text) -{ - /* join UTF-16 surrogates without any pairing sanity checks */ - - static int d; - - if (uchar >= 0xd800 && uchar <= 0xdbff) { d = uchar & 0x3f; return text; } - if (uchar >= 0xdc00 && uchar <= 0xdfff) { uchar = uchar + 0x2400 + d * 0x400; } - - /* output one character as UTF-8 multibyte sequence */ - - if (uchar < 0x80) { - *text++ = c; - } - else if (uchar < 0x800) { - *text++ = 0xc0 | uchar >> 6; - *text++ = 0x80 | (uchar & 0x3f); - } - else if (uchar < 0x10000) { - *text++ = 0xe0 | uchar >> 12; - *text++ = 0x80 | (uchar >> 6 & 0x3f); - *text++ = 0x80 | (uchar & 0x3f); - } - else if (uchar < 0x200000) { - *text++ = 0xf0 | uchar >> 18; - *text++ = 0x80 | (uchar >> 12 & 0x3f); - *text++ = 0x80 | (uchar >> 6 & 0x3f); - *text++ = 0x80 | (uchar & 0x3f); - } - - return text; +SCSUUTF8::~SCSUUTF8() { +#ifdef _ICU_ + ucnv_close(scsuConv); + ucnv_close(utf8Conv); +#endif } - -char SCSUUTF8::processText(SWBuf &text, const SWKey *key, const SWModule *module) { -/* - unsigned char *to, *from; - unsigned long buflen = len * FILTERPAD; - char active = 0, mode = 0; - if ((unsigned long)key < 2) // hack, we're en(1)/de(0)ciphering - return -1; - - static unsigned short start[8] = {0x0000,0x0080,0x0100,0x0300,0x2000,0x2080,0x2100,0x3000}; - static unsigned short slide[8] = {0x0080,0x00C0,0x0400,0x0600,0x0900,0x3040,0x30A0,0xFF00}; - static unsigned short win[256] = { - 0x0000, 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, - 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, - 0x0800, 0x0880, 0x0900, 0x0980, 0x0A00, 0x0A80, 0x0B00, 0x0B80, - 0x0C00, 0x0C80, 0x0D00, 0x0D80, 0x0E00, 0x0E80, 0x0F00, 0x0F80, - 0x1000, 0x1080, 0x1100, 0x1180, 0x1200, 0x1280, 0x1300, 0x1380, - 0x1400, 0x1480, 0x1500, 0x1580, 0x1600, 0x1680, 0x1700, 0x1780, - 0x1800, 0x1880, 0x1900, 0x1980, 0x1A00, 0x1A80, 0x1B00, 0x1B80, - 0x1C00, 0x1C80, 0x1D00, 0x1D80, 0x1E00, 0x1E80, 0x1F00, 0x1F80, - 0x2000, 0x2080, 0x2100, 0x2180, 0x2200, 0x2280, 0x2300, 0x2380, - 0x2400, 0x2480, 0x2500, 0x2580, 0x2600, 0x2680, 0x2700, 0x2780, - 0x2800, 0x2880, 0x2900, 0x2980, 0x2A00, 0x2A80, 0x2B00, 0x2B80, - 0x2C00, 0x2C80, 0x2D00, 0x2D80, 0x2E00, 0x2E80, 0x2F00, 0x2F80, - 0x3000, 0x3080, 0x3100, 0x3180, 0x3200, 0x3280, 0x3300, 0x3800, - 0xE000, 0xE080, 0xE100, 0xE180, 0xE200, 0xE280, 0xE300, 0xE380, - 0xE400, 0xE480, 0xE500, 0xE580, 0xE600, 0xE680, 0xE700, 0xE780, - 0xE800, 0xE880, 0xE900, 0xE980, 0xEA00, 0xEA80, 0xEB00, 0xEB80, - 0xEC00, 0xEC80, 0xED00, 0xED80, 0xEE00, 0xEE80, 0xEF00, 0xEF80, - 0xF000, 0xF080, 0xF100, 0xF180, 0xF200, 0xF280, 0xF300, 0xF380, - 0xF400, 0xF480, 0xF500, 0xF580, 0xF600, 0xF680, 0xF700, 0xF780, - 0xF800, 0xF880, 0xF900, 0xF980, 0xFA00, 0xFA80, 0xFB00, 0xFB80, - 0xFC00, 0xFC80, 0xFD00, 0xFD80, 0xFE00, 0xFE80, 0xFF00, 0xFF80, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x00C0, 0x0250, 0x0370, 0x0530, 0x3040, 0x30A0, 0xFF60 - }; - - if (!len) - return 0; - - memmove(&text[buflen - len], text, len); - from = (unsigned char*)&text[buflen - len]; - to = (unsigned char *)text; - - // ------------------------------- - - for (int i = 0; i < len;) { - - - if (i >= len) break; - c = from[i++]; - - if (c >= 0x80) - { - to = UTF8Output (c - 0x80 + slide[active], to); +#ifndef _ICU_ +unsigned short SCSUUTF8::start[] = {0x0000,0x0080,0x0100,0x0300,0x2000,0x2080,0x2100,0x3000}; +unsigned short SCSUUTF8::slide[] = {0x0080,0x00C0,0x0400,0x0600,0x0900,0x3040,0x30A0,0xFF00}; +unsigned short SCSUUTF8::win[] = { + 0x0000, 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, + 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, + 0x0800, 0x0880, 0x0900, 0x0980, 0x0A00, 0x0A80, 0x0B00, 0x0B80, + 0x0C00, 0x0C80, 0x0D00, 0x0D80, 0x0E00, 0x0E80, 0x0F00, 0x0F80, + 0x1000, 0x1080, 0x1100, 0x1180, 0x1200, 0x1280, 0x1300, 0x1380, + 0x1400, 0x1480, 0x1500, 0x1580, 0x1600, 0x1680, 0x1700, 0x1780, + 0x1800, 0x1880, 0x1900, 0x1980, 0x1A00, 0x1A80, 0x1B00, 0x1B80, + 0x1C00, 0x1C80, 0x1D00, 0x1D80, 0x1E00, 0x1E80, 0x1F00, 0x1F80, + 0x2000, 0x2080, 0x2100, 0x2180, 0x2200, 0x2280, 0x2300, 0x2380, + 0x2400, 0x2480, 0x2500, 0x2580, 0x2600, 0x2680, 0x2700, 0x2780, + 0x2800, 0x2880, 0x2900, 0x2980, 0x2A00, 0x2A80, 0x2B00, 0x2B80, + 0x2C00, 0x2C80, 0x2D00, 0x2D80, 0x2E00, 0x2E80, 0x2F00, 0x2F80, + 0x3000, 0x3080, 0x3100, 0x3180, 0x3200, 0x3280, 0x3300, 0x3800, + 0xE000, 0xE080, 0xE100, 0xE180, 0xE200, 0xE280, 0xE300, 0xE380, + 0xE400, 0xE480, 0xE500, 0xE580, 0xE600, 0xE680, 0xE700, 0xE780, + 0xE800, 0xE880, 0xE900, 0xE980, 0xEA00, 0xEA80, 0xEB00, 0xEB80, + 0xEC00, 0xEC80, 0xED00, 0xED80, 0xEE00, 0xEE80, 0xEF00, 0xEF80, + 0xF000, 0xF080, 0xF100, 0xF180, 0xF200, 0xF280, 0xF300, 0xF380, + 0xF400, 0xF480, 0xF500, 0xF580, 0xF600, 0xF680, 0xF700, 0xF780, + 0xF800, 0xF880, 0xF900, 0xF980, 0xFA00, 0xFA80, 0xFB00, 0xFB80, + 0xFC00, 0xFC80, 0xFD00, 0xFD80, 0xFE00, 0xFE80, 0xFF00, 0xFF80, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x00C0, 0x0250, 0x0370, 0x0530, 0x3040, 0x30A0, 0xFF60, +}; + +int SCSUUTF8::UTF8Output(unsigned long uchar, SWBuf* utf8Buf) +{ + // join UTF-16 surrogates without any pairing sanity checks + if (uchar >= 0xd800 && uchar <= 0xdbff) { + d = uchar & 0x3ff; + return 0; } - else if (c >= 0x20 && c <= 0x7F) - { - to = UTF8Output (c, to); + if (uchar >= 0xdc00 && uchar <= 0xdfff) { + uchar = uchar + 0x2400 + d * 0x400; } - else if (c == 0x0 || c == 0x9 || c == 0xA || c == 0xC || c == 0xD) - { - to = UTF8Output (c, to); + + // output one character as UTF-8 multibyte sequence + + if (uchar < 0x80) { + utf8Buf += uchar; } - else if (c >= 0x1 && c <= 0x8) // SQn - { - if (i >= len) break; - d = from[i++]; // single quote - - to = UTF8Output (d < 0x80 ? d + start [c - 0x1] : - d - 0x80 + slide [c - 0x1], to); + else if (uchar < 0x800) { + utf8Buf += (0xc0 | (uchar>>6)); + utf8Buf += (0x80 | (uchar & 0x3f)); } - else if (c >= 0x10 && c <= 0x17) // SCn - { - active = c - 0x10; // change window + else if (uchar < 0x10000) { + utf8Buf += (0xe0 | (uchar>>12)); + utf8Buf += (0x80 | (uchar>>6 & 0x3f)); + utf8Buf += (0x80 | (uchar & 0x3f)); } - else if (c >= 0x18 && c <= 0x1F) // SDn - { - active = c - 0x18; // define window - if (i >= len) break; - slide [active] = win [from[i++]]; + else if (uchar < 0x200000) { + utf8Buf += (0xf0 | (uchar>>18)); + utf8Buf += (0x80 | (uchar>>12 & 0x3f)); + utf8Buf += (0x80 | (uchar>>6 & 0x3f)); + utf8Buf += (0x80 | (uchar & 0x3f)); } - else if (c == 0xB) // SDX - { - if (i >= len) break; - c = from[i++]; - - if (i >= len) break; - d = from[i++]; + + return 0; +} +#endif - slide [active = c>>5] = 0x10000 + (((c & 0x1F) << 8 | d) << 7); +char SCSUUTF8::processText(SWBuf &text, const SWKey *key, const SWModule *module) { + if ((unsigned long)key < 2) // hack, we're en(1)/de(0)ciphering + return -1; + +#ifdef _ICU_ + // Try decoding with ICU if possible + err = U_ZERO_ERROR; + UnicodeString utf16Text(text.getRawData(), text.length(), scsuConv, err); + err = U_ZERO_ERROR; + int32_t len = utf16Text.extract(text.getRawData(), text.size(), utf8Conv, err); + if (len > (int32_t)text.size()+1) { + text.setSize(len+1); + utf16Text.extract(text.getRawData(), text.size(), utf8Conv, err); } - else if (c == 0xE) // SQU - { +#else + // If ICU is unavailable, decode using Czyborra's decoder + SWBuf utf8Buf = ""; + int len = text.length(); + const char* scsuString = text.c_str(); + + for (int i = 0; i < len;) { + if (i >= len) break; - c = from[i++]; // SQU - - if (i >= len) break; - to = UTF8Output (c << 8 | from[i++], to); + c = scsuString[i++]; + + if (c >= 0x80) + { + UTF8Output(c - 0x80 + slide[active], &utf8Buf); } - else if (c == 0xF) // SCU - { - mode = 1; // change to Unicode mode - - while (mode) - { - if (i >= len) break; - c = from[i++]; - - if (c <= 0xDF || c >= 0xF3) + else if (c >= 0x20 && c <= 0x7F) { - if (i >= len) break; - to = UTF8Output (c << 8 | from[i++], to); + UTF8Output(c, &utf8Buf); } - else if (c == 0xF0) // UQU + else if (c == 0x0 || c == 0x9 || c == 0xA || c == 0xC || c == 0xD) { - if (i >= len) break; - c = from[i++]; - - if (i >= len) break; - to = UTF8Output (c << 8 | from[i++], to); + UTF8Output(c, &utf8Buf); } - else if (c >= 0xE0 && c <= 0xE7) // UCn + else if (c >= 0x1 && c <= 0x8) // SQn { - active = c - 0xE0; mode = 0; + if (i >= len) break; + d = scsuString[i++]; // single quote + + UTF8Output(d < 0x80 ? d + start[c - 0x1] : + d - 0x80 + slide[c - 0x1], &utf8Buf); } - else if (c >= 0xE8 && c <= 0xEF) // UDn + else if (c >= 0x10 && c <= 0x17) // SCn { - if (i >= len) break; - slide [active=c-0xE8] = win [from[i++]]; mode = 0; + active = c - 0x10; // change window } - else if (c == 0xF1) // UDX + else if (c >= 0x18 && c <= 0x1F) // SDn { - if (i >= len) break; - c = from[i++]; - - if (i >= len) break; - d = from[i++]; - - slide [active = c>>5] = - 0x10000 + (((c & 0x1F) << 8 | d) << 7); mode = 0; + active = c - 0x18; // define window + if (i >= len) break; + slide[active] = win[(unsigned char)scsuString[i++]]; + } + else if (c == 0xB) // SDX + { + if (i >= len) break; + c = scsuString[i++]; + + if (i >= len) break; + d = scsuString[i++]; + + slide[active = c>>5] = 0x10000 + (((c & 0x1F) << 8 | d) << 7); + } + else if (c == 0xE) // SQU + { + if (i >= len) break; + c = scsuString[i++]; // SQU + + if (i >= len) break; + UTF8Output(c << 8 | scsuString[i++], &utf8Buf); + } + else if (c == 0xF) // SCU + { + mode = 1; // change to Unicode mode + + while (mode) + { + if (i >= len) break; + c = scsuString[i++]; + + if (c <= 0xDF || c >= 0xF3) + { + if (i >= len) break; + UTF8Output(c << 8 | scsuString[i++], &utf8Buf); + } + else if (c == 0xF0) // UQU + { + if (i >= len) break; + c = scsuString[i++]; + + if (i >= len) break; + UTF8Output(c << 8 | scsuString[i++], &utf8Buf); + } + else if (c >= 0xE0 && c <= 0xE7) // UCn + { + active = c - 0xE0; + mode = 0; + } + else if (c >= 0xE8 && c <= 0xEF) // UDn + { + if (i >= len) break; + slide[active=c-0xE8] = win[(unsigned char)scsuString[i++]]; + mode = 0; + } + else if (c == 0xF1) // UDX + { + if (i >= len) break; + c = scsuString[i++]; + + if (i >= len) break; + d = scsuString[i++]; + + slide[active = c>>5] = + 0x10000 + (((c & 0x1F) << 8 | d) << 7); + mode = 0; + } + } } - } } - - - } - - *to++ = 0; - *to = 0; -*/ - return 0; +#endif + + return 0; } diff --git a/src/modules/filters/swbasicfilter.cpp b/src/modules/filters/swbasicfilter.cpp index e66017e..8e3ce0a 100644 --- a/src/modules/filters/swbasicfilter.cpp +++ b/src/modules/filters/swbasicfilter.cpp @@ -5,7 +5,7 @@ * many filters will need and can use as a starting * point. * - * $Id: swbasicfilter.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: swbasicfilter.cpp 3548 2017-12-10 05:11:38Z scribe $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -29,6 +29,7 @@ #include <stdarg.h> #include <utilstr.h> #include <stringmgr.h> +#include <versekey.h> #include <map> #include <set> @@ -54,6 +55,19 @@ const char SWBasicFilter::POSTCHAR = 4; const char SWBasicFilter::FINALIZE = 8; +BasicFilterUserData::BasicFilterUserData(const SWModule *module, const SWKey *key) { + this->module = module; + this->key = key; + suspendTextPassThru = false; + supressAdjacentWhitespace = false; + vkey = 0; + SWTRY { + vkey = SWDYNAMIC_CAST(VerseKey, key); + } + SWCATCH ( ... ) { } +} + + SWBasicFilter::SWBasicFilter() { p = new Private; @@ -383,6 +397,9 @@ char SWBasicFilter::processText(SWBuf &text, const SWKey *key, const SWModule *m } escEndPos = escStartPos = tokenEndPos = tokenStartPos = 0; lastTextNode = ""; + if (!userData->suspendTextPassThru) { + userData->lastSuspendSegment.size(0); + } continue; } } @@ -398,7 +415,6 @@ char SWBasicFilter::processText(SWBuf &text, const SWKey *key, const SWModule *m if ((!userData->supressAdjacentWhitespace) || (*from != ' ')) { if (!userData->suspendTextPassThru) { text.append(*from); - userData->lastSuspendSegment.size(0); } else userData->lastSuspendSegment.append(*from); lastTextNode.append(*from); diff --git a/src/modules/filters/teihtmlhref.cpp b/src/modules/filters/teihtmlhref.cpp index f08f994..443fd9c 100644 --- a/src/modules/filters/teihtmlhref.cpp +++ b/src/modules/filters/teihtmlhref.cpp @@ -2,7 +2,7 @@ * * teihtmlhref.cpp - TEI to HTML with hrefs filter * - * $Id: teihtmlhref.cpp 3160 2014-04-17 04:02:17Z greg.hellings $ + * $Id: teihtmlhref.cpp 3548 2017-12-10 05:11:38Z scribe $ * * Copyright 2008-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -33,10 +33,10 @@ SWORD_NAMESPACE_START TEIHTMLHREF::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) { - BiblicalText = false; + isBiblicalText = false; if (module) { version = module->getName(); - BiblicalText = (!strcmp(module->getType(), "Biblical Texts")); + isBiblicalText = (!strcmp(module->getType(), "Biblical Texts")); } } @@ -132,7 +132,7 @@ bool TEIHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData if (n != "") { buf += "<br /><b>"; buf += n; - buf += "</b>"; + buf += "</b> "; } } } @@ -221,7 +221,7 @@ bool TEIHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData // Compensate for starting : ref = the_ref + 1; - int size = target.size() - ref.size() - 1; + int size = (int)(target.size() - ref.size() - 1); work.setSize(size); strncpy(work.getRawData(), target, size); } @@ -275,6 +275,52 @@ bool TEIHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData u->suspendTextPassThru = false; } } + // <graphic> image tag + else if (!strcmp(tag.getName(), "graphic")) { + const char *url = tag.getAttribute("url"); + if (url) { // assert we have a url attribute + SWBuf filepath; + if (userData->module) { + filepath = userData->module->getConfigEntry("AbsoluteDataPath"); + if ((filepath.size()) && (filepath[filepath.size()-1] != '/') && (url[0] != '/')) + filepath += '/'; + } + filepath += url; + // images become clickable, if the UI supports showImage. + buf.appendFormatted("<a href=\"passagestudy.jsp?action=showImage&value=%s&module=%s\"><img src=\"file:%s\" border=\"0\" /></a>", + URL::encode(filepath.c_str()).c_str(), + URL::encode(u->version.c_str()).c_str(), + filepath.c_str()); + u->suspendTextPassThru = true; + } + } + // <table> <row> <cell> + else if (!strcmp(tag.getName(), "table")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + buf += "<table><tbody>\n"; + } + else if (tag.isEndTag()) { + buf += "</tbody></table>\n"; + u->supressAdjacentWhitespace = true; + } + + } + else if (!strcmp(tag.getName(), "row")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + buf += "\t<tr>"; + } + else if (tag.isEndTag()) { + buf += "</tr>\n"; + } + } + else if (!strcmp(tag.getName(), "cell")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + buf += "<td>"; + } + else if (tag.isEndTag()) { + buf += "</td>"; + } + } else { return false; // we still didn't handle token diff --git a/src/modules/filters/teilatex.cpp b/src/modules/filters/teilatex.cpp new file mode 100644 index 0000000..8b05107 --- /dev/null +++ b/src/modules/filters/teilatex.cpp @@ -0,0 +1,326 @@ +/*************************************************************************** + * + * teilatex.cpp - TEI to LATEX filter + * + * $Id: teilatex.cpp 3548 2017-12-10 05:11:38Z scribe $ + * + * Copyright 2012-2014 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 <stdlib.h> +#include <ctype.h> +#include <teilatex.h> +#include <utilxml.h> +#include <swmodule.h> +#include <url.h> +#include <iostream> + + +SWORD_NAMESPACE_START + + +TEILaTeX::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) { + isBiblicalText = false; + if (module) { + version = module->getName(); + isBiblicalText = (!strcmp(module->getType(), "Biblical Texts")); + } +} + + +TEILaTeX::TEILaTeX() { + setTokenStart("<"); + setTokenEnd(">"); + + setEscapeStart("&"); + setEscapeEnd(";"); + + setEscapeStringCaseSensitive(true); + + addAllowedEscapeString("quot"); + addAllowedEscapeString("apos"); + addAllowedEscapeString("amp"); + addAllowedEscapeString("lt"); + addAllowedEscapeString("gt"); + + setTokenCaseSensitive(true); + + renderNoteNumbers = false; +} + +bool TEILaTeX::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) { + // manually process if it wasn't a simple substitution + if (!substituteToken(buf, token)) { + MyUserData *u = (MyUserData *)userData; + XMLTag tag(token); + + if (!strcmp(tag.getName(), "p")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { // non-empty start tag + buf += ""; + } + else if (tag.isEndTag()) { // end tag + buf += "//\n"; + //userData->supressAdjacentWhitespace = true; + } + else { // empty paragraph break marker + buf += "//\n"; + //userData->supressAdjacentWhitespace = true; + } + } + + // <hi> + else if (!strcmp(tag.getName(), "hi")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + SWBuf rend = tag.getAttribute("rend"); + + u->lastHi = rend; + if (rend == "italic" || rend == "ital") + buf += "\\it{"; + else if (rend == "bold") + buf += "\\bd{"; + else if (rend == "super" || rend == "sup") + buf += "^{"; + else if (rend == "sub") + buf += "_{"; + else if (rend == "overline") + buf += "\\overline{"; + + } + else if (tag.isEndTag()) { + buf += "}"; + } + } + + // <entryFree> + else if (!strcmp(tag.getName(), "entryFree")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + SWBuf n = tag.getAttribute("n"); + if (n != "") { + buf += "\\teiEntryFree{"; + buf += n; + buf += "}"; + } + } + } + + // <sense> + else if (!strcmp(tag.getName(), "sense")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + SWBuf n = tag.getAttribute("n"); + if (n != "") { + buf += "\n\\teiSense{"; + buf += n; + buf += "}"; + } + } + } + + // <div> + else if (!strcmp(tag.getName(), "div")) { + + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + buf += ""; + } + else if (tag.isEndTag()) { + } + } + + // <lb.../> + else if (!strcmp(tag.getName(), "lb")) { + buf += "//\n"; + } + + // <pos>, <gen>, <case>, <gram>, <number>, <mood>, <pron>, <def> + else if (!strcmp(tag.getName(), "pos") || + !strcmp(tag.getName(), "gen") || + !strcmp(tag.getName(), "case") || + !strcmp(tag.getName(), "gram") || + !strcmp(tag.getName(), "number") || + !strcmp(tag.getName(), "pron") || + !strcmp(tag.getName(), "tr") || + !strcmp(tag.getName(), "orth") || + !strcmp(tag.getName(), "etym") || + !strcmp(tag.getName(), "usg") || + + + !strcmp(tag.getName(), "def")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + buf += "\\tei"; + buf += tag.getName(); + buf += "{"; + } + else if (tag.isEndTag()) { + buf += "}"; + } + } + + else if (!strcmp(tag.getName(), "ref")) { + if (!tag.isEndTag()) { + u->suspendTextPassThru = true; + SWBuf target; + SWBuf work; + SWBuf ref; + + int was_osisref = false; + if(tag.getAttribute("osisRef")) + { + target += tag.getAttribute("osisRef"); + was_osisref=true; + } + else if(tag.getAttribute("target")) + target += tag.getAttribute("target"); + + if(target.size()) + { + const char* the_ref = strchr(target, ':'); + + if(!the_ref) { + // No work + ref = target; + } + else { + // Compensate for starting : + ref = the_ref + 1; + + int size = target.size() - ref.size() - 1; + work.setSize(size); + strncpy(work.getRawData(), target, size); + } + + if(was_osisref) + { + buf.appendFormatted("\\swordref{%s}{%s}{", + (ref) ? ref.c_str() : "", + (work.size()) ? work.c_str() : "" ); + } + else + { + // Dictionary link, or something + buf.appendFormatted("\\sworddictref{%s}{%s}{", + (work.size()) ? work.c_str() : u->version.c_str(), + (ref) ? ref.c_str() : "" + ); + } + } + else + { + //std::cout << "TARGET WASN'T\n"; + } + + } + else { + buf += u->lastTextNode.c_str(); + buf += "}"; + + u->suspendTextPassThru = false; + } + } + + // <note> tag + else if (!strcmp(tag.getName(), "note")) { + if (!tag.isEndTag()) { + if (!tag.isEmpty()) { + u->suspendTextPassThru = true; + } + } + if (tag.isEndTag()) { + SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); + SWBuf noteName = tag.getAttribute("n"); + SWBuf footnoteBody = ""; + if (u->module){ + footnoteBody += u->module->getEntryAttributes()["Footnote"][footnoteNumber]["body"]; + } + + buf.appendFormatted("\\swordfootnote{%s}{%s}{%s}{%s}{", + footnoteNumber.c_str(), + u->version.c_str(), + u->key->getText(), + renderNoteNumbers ? noteName.c_str() : ""); + if (u->module) { + buf += u->module->renderText(footnoteBody).c_str(); + } + u->suspendTextPassThru = false; + } + } + + // <graphic> image tag + else if (!strcmp(tag.getName(), "graphic")) { + const char *url = tag.getAttribute("url"); + if (url) { // assert we have a url attribute + SWBuf filepath; + if (userData->module) { + filepath = userData->module->getConfigEntry("AbsoluteDataPath"); + if ((filepath.size()) && (filepath[filepath.size()-1] != '/') && (url[0] != '/')) + filepath += '/'; + } + filepath += url; + + buf.appendFormatted("\\figure{\\includegraphics{%s}}", + filepath.c_str()); + u->suspendTextPassThru = false; + + } + } + + // <table> <row> <cell> + else if (!strcmp(tag.getName(), "table")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + buf += "\n\\begin{tabular}"; + } + else if (tag.isEndTag()) { + buf += "\n\\end{tabular}"; + ++u->consecutiveNewlines; + u->supressAdjacentWhitespace = true; + } + + } + else if (!strcmp(tag.getName(), "row")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + buf += "\n"; + u->firstCell = true; + } + else if (tag.isEndTag()) { + buf += "//"; + u->firstCell = false; + } + + } + else if (!strcmp(tag.getName(), "cell")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + if (u->firstCell == false) { + buf += " & "; + } + else { + u->firstCell = false; + } + } + else if (tag.isEndTag()) { + buf += ""; + } + } + + + else { + return false; // we still didn't handle token + } + + } + return true; +} + + +SWORD_NAMESPACE_END + diff --git a/src/modules/filters/teirtf.cpp b/src/modules/filters/teirtf.cpp index 1213221..0871270 100644 --- a/src/modules/filters/teirtf.cpp +++ b/src/modules/filters/teirtf.cpp @@ -2,7 +2,7 @@ * * teirtf.cpp - TEI to RTF filter * - * $Id: teirtf.cpp 3160 2014-04-17 04:02:17Z greg.hellings $ + * $Id: teirtf.cpp 3548 2017-12-10 05:11:38Z scribe $ * * Copyright 2006-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -31,11 +31,11 @@ SWORD_NAMESPACE_START TEIRTF::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) { - BiblicalText = false; + isBiblicalText = false; inOsisRef = false; if (module) { version = module->getName(); - BiblicalText = (!strcmp(module->getType(), "Biblical Texts")); + isBiblicalText = (!strcmp(module->getType(), "Biblical Texts")); } } @@ -170,13 +170,7 @@ bool TEIRTF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *use SWBuf type = tag.getAttribute("type"); SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); - VerseKey *vkey = 0; - // see if we have a VerseKey * or descendant - SWTRY { - vkey = SWDYNAMIC_CAST(VerseKey, u->key); - } - SWCATCH ( ... ) { } - if (vkey) { + if (u->vkey) { buf.appendFormatted("{\\super <a href=\"\">*%s</a>} ", footnoteNumber.c_str()); } u->suspendTextPassThru = true; @@ -205,6 +199,22 @@ bool TEIRTF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *use } } + else if (!strcmp(tag.getName(), "graphic")) { + const char *src = tag.getAttribute("url"); + if (!src) // assert we have a src attribute + return false; + + char* filepath = new char[strlen(u->module->getConfigEntry("AbsoluteDataPath")) + strlen(token)]; + *filepath = 0; + strcpy(filepath, userData->module->getConfigEntry("AbsoluteDataPath")); + strcat(filepath, src); + +// we do this because BibleCS looks for this EXACT format for an image tag + buf += "<img src=\""; + buf += filepath; + buf += "\" />"; + delete [] filepath; + } else { return false; // we still didn't handle token diff --git a/src/modules/filters/teixhtml.cpp b/src/modules/filters/teixhtml.cpp index 4ae0d89..1eab978 100644 --- a/src/modules/filters/teixhtml.cpp +++ b/src/modules/filters/teixhtml.cpp @@ -2,7 +2,7 @@ * * teixhtml.cpp - TEI to XHTML filter * - * $Id: teixhtml.cpp 3161 2014-04-17 04:04:03Z greg.hellings $ + * $Id: teixhtml.cpp 3548 2017-12-10 05:11:38Z scribe $ * * Copyright 2012-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -32,11 +32,41 @@ SWORD_NAMESPACE_START +const char *TEIXHTML::getHeader() const { + // <pos>, <gen>, <case>, <gram>, <number>, <mood>, <pron>, <def> <tr> <orth> <etym> <usg> + const static char *header = "\n\ + .entryFree, .form, .etym, .def, .usg, .quote {display:block;}\n\ + .pron, .pos, .oVar, .ref, {display:inline}\n\ + [type=headword] {font-weight:bold; font-variant:small-caps; text-decoration:underline;}\n\ + [type=derivative] {font-weight:bold; font-variant:small-caps;}\n\ + [rend=italic] {font-style:italic;}\n\ + [rend=bold] {font-weight:bold;}\n\ + [rend=small-caps] {font-variant:small-caps}\n\ + .pos:before {content: \"Pos.: \"; font-weight:bold;}\n\ + .pron:before {content:\" \\\\ \";}\n\ + .pron:after {content:\" \\\\ \";}\n\ + .etym:before {content:\"Etym.:\"; display:block; font-weight:bold;}\n\ + .usg:before {content:\"Usg.:\"; display:block; font-weight:bold;}\n\ + .def:before {content:\"Def.:\" display:block; font-weight:bold;}\n\ + .quote {background-color:#cfcfdf; padding:0.3em; margin:0.5em; border-width:1px; border-style:solid;}\n\ + .cit:before {content:\"quote:\" ; display:block; margin-top:0.5em; font-size:small;}\n\ + .cit {align:center;}\n\ + .persName:before {content:\" (\"; font-size:small;}\n\ + .persName:after {content:\") \"; font-size:small;}\n\ + .persName {font-size:small;}\n\ + .number {font-style:bold;}\n\ + .def {font-style:bold;}\n\ + "; + return header; +} + + + TEIXHTML::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) { - BiblicalText = false; + isBiblicalText = false; if (module) { version = module->getName(); - BiblicalText = (!strcmp(module->getType(), "Biblical Texts")); + isBiblicalText = (!strcmp(module->getType(), "Biblical Texts")); } } @@ -119,9 +149,9 @@ bool TEIXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *u if ((!tag.isEndTag()) && (!tag.isEmpty())) { SWBuf n = tag.getAttribute("n"); if (n != "") { - buf += "<b>"; + buf += "<span class=\"entryFree\">"; buf += n; - buf += "</b>"; + buf += "</span>"; } } } @@ -130,11 +160,17 @@ bool TEIXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *u else if (!strcmp(tag.getName(), "sense")) { if ((!tag.isEndTag()) && (!tag.isEmpty())) { SWBuf n = tag.getAttribute("n"); + buf += "<br/><span class=\"sense"; if (n != "") { - buf += "<br /><b>"; + buf += "\" n=\""; buf += n; - buf += "</b>"; + + } + buf += "\">"; + } + else if (tag.isEndTag()) { + buf += "</span> "; } } @@ -153,47 +189,41 @@ bool TEIXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *u buf += "<br />"; } - // <pos>, <gen>, <case>, <gram>, <number>, <mood>, <pron>, <def> + // <pos>, <gen>, <case>, <gram>, <number>, <mood>, <pron>, <def> <tr> <orth> <etym> <usg> else if (!strcmp(tag.getName(), "pos") || !strcmp(tag.getName(), "gen") || !strcmp(tag.getName(), "case") || !strcmp(tag.getName(), "gram") || !strcmp(tag.getName(), "number") || - !strcmp(tag.getName(), "pron") /*|| - !strcmp(tag.getName(), "def")*/) { - if ((!tag.isEndTag()) && (!tag.isEmpty())) { - buf += "<i>"; - } - else if (tag.isEndTag()) { - buf += "</i>"; - } - } - - // <tr> - else if (!strcmp(tag.getName(), "tr")) { - if ((!tag.isEndTag()) && (!tag.isEmpty())) { - buf += "<i>"; - } - else if (tag.isEndTag()) { - buf += "</i>"; - } - } - - // orth - else if (!strcmp(tag.getName(), "orth")) { + !strcmp(tag.getName(), "pron") || + !strcmp(tag.getName(), "def") || + !strcmp(tag.getName(), "tr") || + !strcmp(tag.getName(), "orth") || + !strcmp(tag.getName(), "etym") || + !strcmp(tag.getName(), "usg") || + !strcmp(tag.getName(), "quote")|| + !strcmp(tag.getName(), "cit")|| + !strcmp(tag.getName(), "persName")|| + !strcmp(tag.getName(), "oVar")) + { if ((!tag.isEndTag()) && (!tag.isEmpty())) { - buf += "<b>"; + buf += "<span class=\""; + buf += tag.getName(); + if (tag.getAttribute("type")) { + buf += "\" type =\""; + buf += tag.getAttribute("type"); + } + if (tag.getAttribute("rend")) { + buf += "\" rend =\""; + buf += tag.getAttribute("rend"); + } + buf += "\">"; } else if (tag.isEndTag()) { - buf += "</b>"; + buf += "</span>"; } } - // <etym>, <usg> - else if (!strcmp(tag.getName(), "etym") || - !strcmp(tag.getName(), "usg")) { - // do nothing here - } else if (!strcmp(tag.getName(), "ref")) { if (!tag.isEndTag()) { u->suspendTextPassThru = true; @@ -276,7 +306,50 @@ bool TEIXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *u u->suspendTextPassThru = false; } } - + // <graphic> image tag + else if (!strcmp(tag.getName(), "graphic")) { + const char *url = tag.getAttribute("url"); + if (url) { // assert we have a url attribute + SWBuf filepath; + if (userData->module) { + filepath = userData->module->getConfigEntry("AbsoluteDataPath"); + if ((filepath.size()) && (filepath[filepath.size()-1] != '/') && (url[0] != '/')) + filepath += '/'; + } + filepath += url; + buf.appendFormatted("<a href=\"passagestudy.jsp?action=showImage&value=%s&module=%s\"><img src=\"file:%s\" border=\"0\" /></a>", + URL::encode(filepath.c_str()).c_str(), + URL::encode(u->version.c_str()).c_str(), + filepath.c_str()); + u->suspendTextPassThru = false; + } + } + // <table> <row> <cell> + else if (!strcmp(tag.getName(), "table")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + buf += "<table><tbody>\n"; + } + else if (tag.isEndTag()) { + buf += "</tbody></table>\n"; + u->supressAdjacentWhitespace = true; + } + } + else if (!strcmp(tag.getName(), "row")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + buf += "\t<tr>"; + } + else if (tag.isEndTag()) { + buf += "</tr>\n"; + } + } + else if (!strcmp(tag.getName(), "cell")) { + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + buf += "<td>"; + } + else if (tag.isEndTag()) { + buf += "</td>"; + } + } else { return false; // we still didn't handle token } diff --git a/src/modules/filters/thmlgbf.cpp b/src/modules/filters/thmlgbf.cpp index e85fdef..14e0203 100644 --- a/src/modules/filters/thmlgbf.cpp +++ b/src/modules/filters/thmlgbf.cpp @@ -2,7 +2,7 @@ * * thmlgbf.cpp - ThML to GBF filter * - * $Id: thmlgbf.cpp 2833 2013-06-29 06:40:28Z chrislit $ + * $Id: thmlgbf.cpp 3427 2016-07-03 14:30:33Z scribe $ * * Copyright 1999-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -269,9 +269,11 @@ char ThMLGBF::processText(SWBuf &text, const SWKey *key, const SWModule *module) continue; } if (intoken) { - if (tokpos < 2045) + if (tokpos < 2045) { token[tokpos++] = *from; + // TODO: why is this + 2 ? token[tokpos+2] = 0; + } } else text += *from; } diff --git a/src/modules/filters/thmlheadings.cpp b/src/modules/filters/thmlheadings.cpp index 99bd12a..8dfcb4e 100644 --- a/src/modules/filters/thmlheadings.cpp +++ b/src/modules/filters/thmlheadings.cpp @@ -3,7 +3,7 @@ * thmlheadings.cpp - SWFilter descendant to hide or show headings * in a ThML module * - * $Id: thmlheadings.cpp 3195 2014-04-24 03:03:26Z greg.hellings $ + * $Id: thmlheadings.cpp 3191 2014-04-19 17:06:38Z scribe $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society diff --git a/src/modules/filters/thmlhtml.cpp b/src/modules/filters/thmlhtml.cpp index b5f624e..30213f5 100644 --- a/src/modules/filters/thmlhtml.cpp +++ b/src/modules/filters/thmlhtml.cpp @@ -2,7 +2,7 @@ * * thmlhtml.cpp - ThML to HTML filter * - * $Id: thmlhtml.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: thmlhtml.cpp 3548 2017-12-10 05:11:38Z scribe $ * * Copyright 1999-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -185,17 +185,17 @@ bool ThMLHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *u } } else if (!strcmp(tag.getName(), "div")) { - if (tag.isEndTag() && (u->SecHead)) { + if (tag.isEndTag() && (u->inSecHead)) { buf += "</i></b><br />"; - u->SecHead = false; + u->inSecHead = false; } else if (tag.getAttribute("class")) { if (!strcmp(tag.getAttribute("class"), "sechead")) { - u->SecHead = true; + u->inSecHead = true; buf += "<br /><b><i>"; } else if (!strcmp(tag.getAttribute("class"), "title")) { - u->SecHead = true; + u->inSecHead = true; buf += "<br /><b><i>"; } } diff --git a/src/modules/filters/thmlhtmlhref.cpp b/src/modules/filters/thmlhtmlhref.cpp index f72a93e..6523aa3 100644 --- a/src/modules/filters/thmlhtmlhref.cpp +++ b/src/modules/filters/thmlhtmlhref.cpp @@ -2,7 +2,7 @@ * * thmlhtmlhref.cpp - ThML to HTML filter with hrefs * - * $Id: thmlhtmlhref.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: thmlhtmlhref.cpp 3548 2017-12-10 05:11:38Z scribe $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -33,10 +33,11 @@ SWORD_NAMESPACE_START ThMLHTMLHREF::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) { + isBiblicalText = false; + inSecHead = false; if (module) { version = module->getName(); - BiblicalText = (!strcmp(module->getType(), "Biblical Texts")); - SecHead = false; + isBiblicalText = (!strcmp(module->getType(), "Biblical Texts")); } } @@ -209,20 +210,14 @@ bool ThMLHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat SWBuf type = tag.getAttribute("type"); SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); SWBuf noteName = tag.getAttribute("n"); - VerseKey *vkey = NULL; - // see if we have a VerseKey * or descendant - SWTRY { - vkey = SWDYNAMIC_CAST(VerseKey, u->key); - } - SWCATCH ( ... ) { } - if (vkey) { + if (u->vkey) { // leave this special osis type in for crossReference notes types? Might thml use this some day? Doesn't hurt. char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=%c&value=%s&module=%s&passage=%s\"><small><sup class=\"%c\">*%c%s</sup></small></a>", ch, URL::encode(footnoteNumber.c_str()).c_str(), URL::encode(u->version.c_str()).c_str(), - URL::encode(vkey->getText()).c_str(), + URL::encode(u->vkey->getText()).c_str(), ch, ch, (renderNoteNumbers ? URL::encode(noteName.c_str()).c_str() : "")); @@ -256,7 +251,7 @@ bool ThMLHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat } } if (tag.isEndTag()) { // </scripRef> - if (!u->BiblicalText) { + if (!u->isBiblicalText) { SWBuf refList = u->startTag.getAttribute("passage"); if (!refList.length()) refList = u->lastTextNode; @@ -271,19 +266,13 @@ bool ThMLHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat else { SWBuf footnoteNumber = u->startTag.getAttribute("swordFootnote"); SWBuf noteName = tag.getAttribute("n"); - VerseKey *vkey = NULL; - // see if we have a VerseKey * or descendant - SWTRY { - vkey = SWDYNAMIC_CAST(VerseKey, u->key); - } - SWCATCH ( ... ) {} - if (vkey) { + if (u->vkey) { // leave this special osis type in for crossReference notes types? Might thml use this some day? Doesn't hurt. - //buf.appendFormatted("<a href=\"noteID=%s.x.%s\"><small><sup>*x</sup></small></a> ", vkey->getText(), footnoteNumber.c_str()); + //buf.appendFormatted("<a href=\"noteID=%s.x.%s\"><small><sup>*x</sup></small></a> ", u->vkey->getText(), footnoteNumber.c_str()); buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=x&value=%s&module=%s&passage=%s\"><small><sup class=\"x\">*x%s</sup></small></a>", URL::encode(footnoteNumber.c_str()).c_str(), URL::encode(u->version.c_str()).c_str(), - URL::encode(vkey->getText()).c_str(), + URL::encode(u->vkey->getText()).c_str(), (renderNoteNumbers ? URL::encode(noteName.c_str()).c_str() : "")); } } @@ -293,17 +282,17 @@ bool ThMLHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserDat } } else if (tag.getName() && !strcmp(tag.getName(), "div")) { - if (tag.isEndTag() && u->SecHead) { + if (tag.isEndTag() && u->inSecHead) { buf += "</i></b><br />"; - u->SecHead = false; + u->inSecHead = false; } else if (tag.getAttribute("class")) { if (!stricmp(tag.getAttribute("class"), "sechead")) { - u->SecHead = true; + u->inSecHead = true; buf += "<br /><b><i>"; } else if (!stricmp(tag.getAttribute("class"), "title")) { - u->SecHead = true; + u->inSecHead = true; buf += "<br /><b><i>"; } else { diff --git a/src/modules/filters/thmllatex.cpp b/src/modules/filters/thmllatex.cpp new file mode 100644 index 0000000..7213249 --- /dev/null +++ b/src/modules/filters/thmllatex.cpp @@ -0,0 +1,396 @@ +/****************************************************************************** + * + * thmllatex.cpp - ThML to classed LaTeX + * + * $Id: thmllatex.cpp 3548 2017-12-10 05:11:38Z scribe $ + * + * Copyright 2011-2014 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 <stdlib.h> +#include <thmllatex.h> +#include <swmodule.h> +#include <utilxml.h> +#include <utilstr.h> +#include <versekey.h> +#include <url.h> + +SWORD_NAMESPACE_START + + +const char *ThMLLaTeX::getHeader() const { + return "\ + "; +} + + +ThMLLaTeX::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) { + isBiblicalText = false; + inSecHead = false; + if (module) { + version = module->getName(); + isBiblicalText = (!strcmp(module->getType(), "Biblical Texts")); + } +} + + +ThMLLaTeX::ThMLLaTeX() { + setTokenStart("<"); + setTokenEnd(">"); + + setEscapeStart("&"); + setEscapeEnd(";"); + + setEscapeStringCaseSensitive(true); + setPassThruNumericEscapeString(true); + + addAllowedEscapeString("quot"); + addAllowedEscapeString("amp"); + addAllowedEscapeString("lt"); + addAllowedEscapeString("gt"); + + addAllowedEscapeString("nbsp"); + addAllowedEscapeString("brvbar"); // "Š" + addAllowedEscapeString("sect"); // "§" + addAllowedEscapeString("copy"); // "©" + addAllowedEscapeString("laquo"); // "«" + addAllowedEscapeString("reg"); // "®" + addAllowedEscapeString("acute"); // "Ž" + addAllowedEscapeString("para"); // "¶" + addAllowedEscapeString("raquo"); // "»" + + addAllowedEscapeString("Aacute"); // "Á" + addAllowedEscapeString("Agrave"); // "À" + addAllowedEscapeString("Acirc"); // "Â" + addAllowedEscapeString("Auml"); // "Ä" + addAllowedEscapeString("Atilde"); // "Ã" + addAllowedEscapeString("Aring"); // "Å" + addAllowedEscapeString("aacute"); // "á" + addAllowedEscapeString("agrave"); // "à" + addAllowedEscapeString("acirc"); // "â" + addAllowedEscapeString("auml"); // "ä" + addAllowedEscapeString("atilde"); // "ã" + addAllowedEscapeString("aring"); // "å" + addAllowedEscapeString("Eacute"); // "É" + addAllowedEscapeString("Egrave"); // "È" + addAllowedEscapeString("Ecirc"); // "Ê" + addAllowedEscapeString("Euml"); // "Ë" + addAllowedEscapeString("eacute"); // "é" + addAllowedEscapeString("egrave"); // "è" + addAllowedEscapeString("ecirc"); // "ê" + addAllowedEscapeString("euml"); // "ë" + addAllowedEscapeString("Iacute"); // "Í" + addAllowedEscapeString("Igrave"); // "Ì" + addAllowedEscapeString("Icirc"); // "Î" + addAllowedEscapeString("Iuml"); // "Ï" + addAllowedEscapeString("iacute"); // "í" + addAllowedEscapeString("igrave"); // "ì" + addAllowedEscapeString("icirc"); // "î" + addAllowedEscapeString("iuml"); // "ï" + addAllowedEscapeString("Oacute"); // "Ó" + addAllowedEscapeString("Ograve"); // "Ò" + addAllowedEscapeString("Ocirc"); // "Ô" + addAllowedEscapeString("Ouml"); // "Ö" + addAllowedEscapeString("Otilde"); // "Õ" + addAllowedEscapeString("oacute"); // "ó" + addAllowedEscapeString("ograve"); // "ò" + addAllowedEscapeString("ocirc"); // "ô" + addAllowedEscapeString("ouml"); // "ö" + addAllowedEscapeString("otilde"); // "õ" + addAllowedEscapeString("Uacute"); // "Ú" + addAllowedEscapeString("Ugrave"); // "Ù" + addAllowedEscapeString("Ucirc"); // "Û" + addAllowedEscapeString("Uuml"); // "Ü" + addAllowedEscapeString("uacute"); // "ú" + addAllowedEscapeString("ugrave"); // "ù" + addAllowedEscapeString("ucirc"); // "û" + addAllowedEscapeString("uuml"); // "ü" + addAllowedEscapeString("Yacute"); // "Ý" + addAllowedEscapeString("yacute"); // "ý" + addAllowedEscapeString("yuml"); // "ÿ" + + addAllowedEscapeString("deg"); // "°" + addAllowedEscapeString("plusmn"); // "±" + addAllowedEscapeString("sup2"); // "²" + addAllowedEscapeString("sup3"); // "³" + addAllowedEscapeString("sup1"); // "¹" + addAllowedEscapeString("nbsp"); // "º" + addAllowedEscapeString("pound"); // "£" + addAllowedEscapeString("cent"); // "¢" + addAllowedEscapeString("frac14"); // "Œ" + addAllowedEscapeString("frac12"); // "œ" + addAllowedEscapeString("frac34"); // "Ÿ" + addAllowedEscapeString("iquest"); // "¿" + addAllowedEscapeString("iexcl"); // "¡" + addAllowedEscapeString("ETH"); // "Ð" + addAllowedEscapeString("eth"); // "ð" + addAllowedEscapeString("THORN"); // "Þ" + addAllowedEscapeString("thorn"); // "þ" + addAllowedEscapeString("AElig"); // "Æ" + addAllowedEscapeString("aelig"); // "æ" + addAllowedEscapeString("Oslash"); // "Ø" + addAllowedEscapeString("curren"); // "€" + addAllowedEscapeString("Ccedil"); // "Ç" + addAllowedEscapeString("ccedil"); // "ç" + addAllowedEscapeString("szlig"); // "ß" + addAllowedEscapeString("Ntilde"); // "Ñ" + addAllowedEscapeString("ntilde"); // "ñ" + addAllowedEscapeString("yen"); // "¥" + addAllowedEscapeString("not"); // "¬" + addAllowedEscapeString("ordf"); // "ª" + addAllowedEscapeString("uml"); // "š" + addAllowedEscapeString("shy"); // "­" + addAllowedEscapeString("macr"); // "¯" + + addAllowedEscapeString("micro"); // "µ" + addAllowedEscapeString("middot"); // "·" + addAllowedEscapeString("cedil"); // "ž" + addAllowedEscapeString("ordm"); // "º" + addAllowedEscapeString("times"); // "×" + addAllowedEscapeString("divide"); // "÷" + addAllowedEscapeString("oslash"); // "ø" + + setTokenCaseSensitive(true); + addTokenSubstitute("scripture", " \\swordquote{ "); + addTokenSubstitute("/scripture", "}"); + + renderNoteNumbers = false; +} + + +bool ThMLLaTeX::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) { + if (!substituteToken(buf, token)) { // manually process if it wasn't a simple substitution + MyUserData *u = (MyUserData *)userData; + + XMLTag tag(token); + if ((!tag.isEndTag()) && (!tag.isEmpty())) + u->startTag = tag; + + if (tag.getName() && !strcmp(tag.getName(), "sync")) { + SWBuf value = tag.getAttribute("value"); + if (tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "morph")) { //> + if (value.length()) + buf.appendFormatted("\\swordmorph[Greek]{%s}", + value.c_str()); + } + else if (tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "lemma")) { //> + if (value.length()) + // empty "type=" is deliberate. + buf.appendFormatted("\\swordmorph[lemma]{%s}", + value.c_str()); + } + else if (tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "Strongs")) { + if (!tag.isEndTag()) { + char ch = *value; + value<<1; + buf.appendFormatted("\\swordstrong[%s]{%s}{", + ((ch == 'H') ? "Hebrew" : "Greek"), + value.c_str()); + } + else { buf += "}"; } + } + + else if (tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "Dict")) { + if (!tag.isEndTag()) { + buf.appendFormatted("\\sworddict{%s}{", + value.c_str()); + } + else { buf += "}"; } + } + + } + // <note> tag + else if (!strcmp(tag.getName(), "note")) { + if (!tag.isEndTag()) { + if (!tag.isEmpty()) { + SWBuf type = tag.getAttribute("type"); + SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); + SWBuf noteName = tag.getAttribute("n"); + SWBuf footnoteBody = ""; + if (u->module){ + footnoteBody += u->module->getEntryAttributes()["Footnote"][footnoteNumber]["body"]; + } + if (u->vkey) { + // leave this special osis type in for crossReference notes types? Might thml use this some day? Doesn't hurt. + char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); + buf.appendFormatted("\\swordfootnote[%c]{%s}{%s}{%s}{%s}{", + ch, + footnoteNumber.c_str(), + u->version.c_str(), + u->vkey->getText(), + noteName.c_str()); + } + else { + char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); + buf.appendFormatted("\\swordfootnote[%c]{%s}{%s}{%s}{%s}{", + ch, + footnoteNumber.c_str(), + u->version.c_str(), + u->key->getText(), + noteName.c_str()); + } + u->suspendTextPassThru = true; + if (u->module) { + buf += u->module->renderText(footnoteBody).c_str(); + } + } + } + if (tag.isEndTag()) { + buf += "}"; + u->suspendTextPassThru = false; + } + } + else if (!strcmp(tag.getName(), "scripture")) { + buf += (tag.isEndTag() ? "\\swordquote" : "}"); + } + // <scripRef> tag + else if (!strcmp(tag.getName(), "scripRef")) { + if (!tag.isEndTag()) { + if (!tag.isEmpty()) { + u->suspendTextPassThru = true; + } + } + if (!tag.isEndTag()) { // </scripRef> + if (!u->isBiblicalText) { + SWBuf refList = u->startTag.getAttribute("passage"); + if (!refList.length()) + refList = u->lastTextNode; + SWBuf version = tag.getAttribute("version"); + + buf.appendFormatted("\\swordxref{%s}{%s}{", + (refList.length()) ? refList.c_str() : "", + (version.length()) ? version.c_str() : ""); + buf += u->lastTextNode.c_str(); + buf += "}"; + } + else { + SWBuf footnoteNumber = u->startTag.getAttribute("swordFootnote"); + SWBuf noteName = tag.getAttribute("n"); + SWBuf footnoteBody = ""; + if (u->module){ + footnoteBody += u->module->getEntryAttributes()["Footnote"][footnoteNumber]["body"]; + } + if (u->vkey) { + // leave this special osis type in for crossReference notes types? Might thml use this some day? Doesn't hurt. + //buf.appendFormatted("<a href=\"noteID=%s.x.%s\"><small><sup>*x</sup></small></a> ", u->vkey->getText(), footnoteNumber.c_str()); + // char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); + char ch = 'x'; + buf.appendFormatted("\\swordfootnote[%c]{%s}{%s}{%s}{%s}{", + ch, + footnoteNumber.c_str(), + u->version.c_str(), + u->vkey->getText(), + (renderNoteNumbers ? noteName.c_str() : "")); + if (u->module) { + buf += u->module->renderText(footnoteBody).c_str(); + } + } + } + + + } + else if (tag.isEndTag()){ + buf +="}"; + // let's let text resume to output again + u->suspendTextPassThru = false; + } + } + else if (tag.getName() && !strcmp(tag.getName(), "div")) { + + //if (!tag.isEndTag() && u->vkey && !u->vkey->getChapter()) + // buf += "\\swordsection{book}{"; + //} + + + if (!tag.isEndTag() && u->inSecHead) { + buf += "\\swordsection{sechead}{"; + u->inSecHead = false; + } + + else if (!tag.isEndTag() && tag.getAttribute("class")) { + buf += "\\swordsection{"; + buf += tag.getAttribute("class"); + buf += "}{"; + + } + else if (!tag.isEndTag()) { + buf += "\\swordsection{}{"; + } + + else if (tag.isEndTag()) { + buf += "}"; + } + } + else if (tag.getName() && (!strcmp(tag.getName(), "img") || !strcmp(tag.getName(), "image"))) { + const char *src = strstr(token, "src"); + if (!src) // assert we have a src attribute + return false; + + const char *c, *d; + if (((c = strchr(src+3, '"')) == NULL) || + ((d = strchr( ++c , '"')) == NULL)) // identify endpoints. + return false; // abandon hope. + + + // images become clickable, if the UI supports showImage. + buf +="\\figure{"; + + for (c = token; *c; c++) { + if ((*c == '/') && (*(c+1) == '\0')) + continue; + if (c == src) { + for (;((*c) && (*c != '"')); c++) + buf += *c; + + if (!*c) { c--; continue; } + + buf += '"'; + if (*(c+1) == '/') { + buf += "\\includegraphics{"; + buf += userData->module->getConfigEntry("AbsoluteDataPath"); + if (buf[buf.length()-2] == '/') + c++; // skip '/' + } + continue; + } + buf += *c; + } + buf += "}}"; + } + else if (tag.getName() && (!strcmp(tag.getName(), "i"))){ + if (!tag.isEndTag()) { + buf += "\\emph{"; + } + else { buf += "}"; } + } + else if (tag.getName() && (!strcmp(tag.getName(), "br"))){ + buf += "\\\\"; + + } + else { + buf += '<'; + /*for (const char *tok = token; *tok; tok++) + buf += *tok;*/ + buf += token; + buf += '>'; + //return false; // we still didn't handle token + } + } + return true; +} + + +SWORD_NAMESPACE_END diff --git a/src/modules/filters/thmlplain.cpp b/src/modules/filters/thmlplain.cpp index b9b9839..b30173b 100644 --- a/src/modules/filters/thmlplain.cpp +++ b/src/modules/filters/thmlplain.cpp @@ -3,7 +3,7 @@ * thmlplain.cpp - SWFilter descendant to strip out all ThML tags or * convert to ASCII rendered symbols * - * $Id: thmlplain.cpp 2833 2013-06-29 06:40:28Z chrislit $ + * $Id: thmlplain.cpp 3427 2016-07-03 14:30:33Z scribe $ * * Copyright 1999-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -206,9 +206,15 @@ char ThMLPlain::processText(SWBuf &text, const SWKey *key, const SWModule *modul continue; } if (intoken) { - if (tokpos < 2045) + if (tokpos < 2045) { token[tokpos++] = *from; + //TODO: why is this + 2? Are we trying to keep 2 or 3 nulls after the last valid char? + // tokpos has been incremented past the last valid token. it should be pointing to null + // +1 should give us 2 nulls, but we're +2 here, which actually keeps 3 nulls after the + // last valid char. Why are we doing any of this? These were written before SWBuf and should + // probably be switched to SWBuf, but perf tests before and after the switch should be run token[tokpos+2] = 0; + } } else text += *from; } diff --git a/src/modules/filters/thmlrtf.cpp b/src/modules/filters/thmlrtf.cpp index dc50ae9..7852fd7 100644 --- a/src/modules/filters/thmlrtf.cpp +++ b/src/modules/filters/thmlrtf.cpp @@ -2,7 +2,7 @@ * * thmlrtf.cpp - ThML to RTF filter * - * $Id: thmlrtf.cpp 2833 2013-06-29 06:40:28Z chrislit $ + * $Id: thmlrtf.cpp 3548 2017-12-10 05:11:38Z scribe $ * * Copyright 1999-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -211,11 +211,12 @@ char ThMLRTF::processText(SWBuf &text, const SWKey *key, const SWModule *module) ThMLRTF::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) { - this->SecHead = false; + isBiblicalText = false; + inSecHead = false; XMLTag startTag = ""; if (module) { version = module->getName(); - BiblicalText = (!strcmp(module->getType(), "Biblical Texts")); + isBiblicalText = (!strcmp(module->getType(), "Biblical Texts")); } } @@ -253,16 +254,10 @@ bool ThMLRTF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *us if (!tag.isEmpty()) { SWBuf type = tag.getAttribute("type"); SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); - VerseKey *vkey = NULL; - // see if we have a VerseKey * or descendant - SWTRY { - vkey = SWDYNAMIC_CAST(VerseKey, u->key); - } - SWCATCH ( ... ) { } - if (vkey) { + if (u->vkey) { // leave this special osis type in for crossReference notes types? Might thml use this some day? Doesn't hurt. char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); - buf.appendFormatted("{\\super <a href=\"\">*%c%i.%s</a>} ", ch, vkey->getVerse(), footnoteNumber.c_str()); + buf.appendFormatted("{\\super <a href=\"\">*%c%i.%s</a>} ", ch, u->vkey->getVerse(), footnoteNumber.c_str()); } u->suspendTextPassThru = true; } @@ -280,7 +275,7 @@ bool ThMLRTF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *us } } if (tag.isEndTag()) { // </scripRef> - if (!u->BiblicalText) { + if (!u->isBiblicalText) { SWBuf refList = u->startTag.getAttribute("passage"); if (!refList.length()) refList = u->lastTextNode; @@ -292,15 +287,9 @@ bool ThMLRTF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *us } else { SWBuf footnoteNumber = u->startTag.getAttribute("swordFootnote"); - VerseKey *vkey = NULL; - // see if we have a VerseKey * or descendant - SWTRY { - vkey = SWDYNAMIC_CAST(VerseKey, u->key); - } - SWCATCH ( ... ) {} - if (vkey) { + if (u->vkey) { // leave this special osis type in for crossReference notes types? Might thml use this some day? Doesn't hurt. - buf.appendFormatted("{\\super <a href=\"\">*x%i.%s</a>} ", vkey->getVerse(), footnoteNumber.c_str()); + buf.appendFormatted("{\\super <a href=\"\">*x%i.%s</a>} ", u->vkey->getVerse(), footnoteNumber.c_str()); } } @@ -310,17 +299,17 @@ bool ThMLRTF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *us } else if (tag.getName() && !strcmp(tag.getName(), "div")) { - if (tag.isEndTag() && u->SecHead) { + if (tag.isEndTag() && u->inSecHead) { buf += "\\par}"; - u->SecHead = false; + u->inSecHead = false; } else if (tag.getAttribute("class")) { if (!stricmp(tag.getAttribute("class"), "sechead")) { - u->SecHead = true; + u->inSecHead = true; buf += "{\\par\\i1\\b1 "; } else if (!stricmp(tag.getAttribute("class"), "title")) { - u->SecHead = true; + u->inSecHead = true; buf += "{\\par\\i1\\b1 "; } } diff --git a/src/modules/filters/thmlscripref.cpp b/src/modules/filters/thmlscripref.cpp index 3a8b12a..7bc84ef 100644 --- a/src/modules/filters/thmlscripref.cpp +++ b/src/modules/filters/thmlscripref.cpp @@ -3,7 +3,7 @@ * thmlscripref.cpp - SWFilter descendant to hide or show scripture * referebces in a ThML module * - * $Id: thmlscripref.cpp 3156 2014-04-17 03:50:37Z greg.hellings $ + * $Id: thmlscripref.cpp 3045 2014-03-02 07:53:52Z chrislit $ * * Copyright 2001-2014 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society diff --git a/src/modules/filters/thmlstrongs.cpp b/src/modules/filters/thmlstrongs.cpp index 09658a9..a43c7aa 100644 --- a/src/modules/filters/thmlstrongs.cpp +++ b/src/modules/filters/thmlstrongs.cpp @@ -3,7 +3,7 @@ * thmlstrongs.cpp - SWFilter descendant to hide or show Strong's number * in a ThML module * - * $Id: thmlstrongs.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: thmlstrongs.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -60,7 +60,7 @@ char ThMLStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *mod bool lastspace = false; int word = 1; char val[128]; - char wordstr[5]; + char wordstr[11]; char *valto; char *ch; unsigned int textStart = 0, textEnd = 0; @@ -77,7 +77,7 @@ char ThMLStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *mod token[0] = 0; token[1] = 0; token[2] = 0; - textEnd = text.length(); + textEnd = (unsigned int)text.length(); continue; } if (*from == '>') { // process tokens @@ -116,7 +116,7 @@ char ThMLStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *mod if (lastspace) text--; } - if (newText) {textStart = text.length(); newText = false; } + if (newText) {textStart = (unsigned int)text.length(); newText = false; } continue; } } @@ -150,15 +150,17 @@ char ThMLStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *mod text += '<'; text += token; text += '>'; - if (newText) {textStart = text.length(); newText = false; } + if (newText) {textStart = (unsigned int)text.length(); newText = false; } continue; } if (intoken) { - if (tokpos < 2045) + if (tokpos < 2045) { token[tokpos++] = *from; + // TODO: why is this + 2 ? token[tokpos+2] = 0; + } } - else { + else { text += *from; lastspace = (*from == ' '); } diff --git a/src/modules/filters/thmlwordjs.cpp b/src/modules/filters/thmlwordjs.cpp index 7d80a00..2042453 100644 --- a/src/modules/filters/thmlwordjs.cpp +++ b/src/modules/filters/thmlwordjs.cpp @@ -2,7 +2,7 @@ * * thmlwordjs.cpp - SWFilter descendant to ??? * - * $Id: thmlwordjs.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: thmlwordjs.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2005-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -68,7 +68,7 @@ char ThMLWordJS::processText(SWBuf &text, const SWKey *key, const SWModule *modu char val[128]; char *valto; char *ch; - char wordstr[5]; + char wordstr[11]; unsigned int textStart = 0, lastAppendLen = 0, textEnd = 0; SWBuf tmp; bool newText = false; @@ -91,7 +91,7 @@ char ThMLWordJS::processText(SWBuf &text, const SWKey *key, const SWModule *modu token[0] = 0; token[1] = 0; token[2] = 0; - textEnd = text.length(); + textEnd = (unsigned int)text.length(); continue; } if (*from == '>') { // process tokens @@ -151,7 +151,7 @@ char ThMLWordJS::processText(SWBuf &text, const SWKey *key, const SWModule *modu text += token; text += '>'; if (needWordOut) { - char wstr[10]; + char wstr[11]; sprintf(wstr, "%03d", word-2); AttributeValue *wAttrs = &(module->getEntryAttributes()["Word"][wstr]); needWordOut = false; @@ -226,27 +226,29 @@ char ThMLWordJS::processText(SWBuf &text, const SWKey *key, const SWModule *modu else m = morph.c_str(); spanStart.appendFormatted("<span class=\"clk\" onclick=\"p('%s','%s','%s','%s','','%s');\" >", lexName.c_str(), strong.c_str(), wordID.c_str(), m, modName.c_str()); text.insert(textStr, spanStart); - lastAppendLen = spanStart.length(); + lastAppendLen = (unsigned int)spanStart.length(); } } } if (newText) { - textStart = text.length(); newText = false; + textStart = (unsigned int)text.length(); newText = false; } continue; } if (intoken) { - if (tokpos < 2045) + if (tokpos < 2045) { token[tokpos++] = *from; + // TODO: why is this + 2 ? token[tokpos+2] = 0; + } } else { text += *from; } } - char wstr[10]; + char wstr[11]; sprintf(wstr, "%03d", word-1); AttributeValue *wAttrs = &(module->getEntryAttributes()["Word"][wstr]); needWordOut = false; diff --git a/src/modules/filters/thmlxhtml.cpp b/src/modules/filters/thmlxhtml.cpp index eb9c40a..af47c72 100644 --- a/src/modules/filters/thmlxhtml.cpp +++ b/src/modules/filters/thmlxhtml.cpp @@ -2,7 +2,7 @@ * * thmlxhtml.cpp - ThML to classed XHTML * - * $Id: thmlxhtml.cpp 3205 2014-05-01 02:31:28Z greg.hellings $ + * $Id: thmlxhtml.cpp 3548 2017-12-10 05:11:38Z scribe $ * * Copyright 2011-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -38,10 +38,11 @@ const char *ThMLXHTML::getHeader() const { ThMLXHTML::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) { + isBiblicalText = false; + secHeadLevel = 0; if (module) { version = module->getName(); - BiblicalText = (!strcmp(module->getType(), "Biblical Texts")); - SecHead = false; + isBiblicalText = (!strcmp(module->getType(), "Biblical Texts")); } } @@ -214,20 +215,14 @@ bool ThMLXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * SWBuf type = tag.getAttribute("type"); SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); SWBuf noteName = tag.getAttribute("n"); - VerseKey *vkey = NULL; - // see if we have a VerseKey * or descendant - SWTRY { - vkey = SWDYNAMIC_CAST(VerseKey, u->key); - } - SWCATCH ( ... ) { } - if (vkey) { + if (u->vkey) { // leave this special osis type in for crossReference notes types? Might thml use this some day? Doesn't hurt. char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=%c&value=%s&module=%s&passage=%s\"><small><sup class=\"%c\">*%c%s</sup></small></a>", ch, URL::encode(footnoteNumber.c_str()).c_str(), URL::encode(u->version.c_str()).c_str(), - URL::encode(vkey->getText()).c_str(), + URL::encode(u->vkey->getText()).c_str(), ch, ch, (renderNoteNumbers ? noteName.c_str() : "")); @@ -261,7 +256,7 @@ bool ThMLXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * } } if (tag.isEndTag()) { // </scripRef> - if (!u->BiblicalText) { + if (!u->isBiblicalText) { SWBuf refList = u->startTag.getAttribute("passage"); if (!refList.length()) refList = u->lastTextNode; @@ -276,19 +271,13 @@ bool ThMLXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * else { SWBuf footnoteNumber = u->startTag.getAttribute("swordFootnote"); SWBuf noteName = tag.getAttribute("n"); - VerseKey *vkey = NULL; - // see if we have a VerseKey * or descendant - SWTRY { - vkey = SWDYNAMIC_CAST(VerseKey, u->key); - } - SWCATCH ( ... ) {} - if (vkey) { + if (u->vkey) { // leave this special osis type in for crossReference notes types? Might thml use this some day? Doesn't hurt. - //buf.appendFormatted("<a href=\"noteID=%s.x.%s\"><small><sup>*x</sup></small></a> ", vkey->getText(), footnoteNumber.c_str()); + //buf.appendFormatted("<a href=\"noteID=%s.x.%s\"><small><sup>*x</sup></small></a> ", u->vkey->getText(), footnoteNumber.c_str()); buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=x&value=%s&module=%s&passage=%s\"><small><sup class=\"x\">*x%s</sup></small></a>", URL::encode(footnoteNumber.c_str()).c_str(), URL::encode(u->version.c_str()).c_str(), - URL::encode(vkey->getText()).c_str(), + URL::encode(u->vkey->getText()).c_str(), (renderNoteNumbers ? noteName.c_str() : "")); } } @@ -298,19 +287,19 @@ bool ThMLXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData * } } else if (tag.getName() && !strcmp(tag.getName(), "div")) { - if (tag.isEndTag() && u->SecHead) { + if (tag.isEndTag() && u->secHeadLevel) { buf += "</h"; - buf += u->SecHead; + buf += u->secHeadLevel; buf += ">"; - u->SecHead = false; + u->secHeadLevel = 0; } else if (tag.getAttribute("class")) { if (!stricmp(tag.getAttribute("class"), "sechead")) { - u->SecHead = '3'; + u->secHeadLevel = '3'; buf += "<h3>"; } else if (!stricmp(tag.getAttribute("class"), "title")) { - u->SecHead = '2'; + u->secHeadLevel = '2'; buf += "<h2>"; } else { diff --git a/src/modules/filters/unicodertf.cpp b/src/modules/filters/unicodertf.cpp index 1cde086..bdd2ae1 100644 --- a/src/modules/filters/unicodertf.cpp +++ b/src/modules/filters/unicodertf.cpp @@ -2,7 +2,7 @@ * * unicodertf.cpp - SWFilter descendant to convert UTF-8 to RTF tags * - * $Id: unicodertf.cpp 3157 2014-04-17 03:56:12Z greg.hellings $ + * $Id: unicodertf.cpp 3081 2014-03-05 19:52:08Z chrislit $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society diff --git a/src/modules/filters/utf16utf8.cpp b/src/modules/filters/utf16utf8.cpp index d224db2..3929471 100644 --- a/src/modules/filters/utf16utf8.cpp +++ b/src/modules/filters/utf16utf8.cpp @@ -2,7 +2,7 @@ * * utf16utf8.cpp - SWFilter descendant to convert UTF-16 to UTF-8 * - * $Id: utf16utf8.cpp 3157 2014-04-17 03:56:12Z greg.hellings $ + * $Id: utf16utf8.cpp 3081 2014-03-05 19:52:08Z chrislit $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society diff --git a/src/modules/filters/utf8arabicpoints.cpp b/src/modules/filters/utf8arabicpoints.cpp index 42bfaa5..932fc64 100644 --- a/src/modules/filters/utf8arabicpoints.cpp +++ b/src/modules/filters/utf8arabicpoints.cpp @@ -3,7 +3,7 @@ * utf8arabicpoints.cpp - SWFilter descendant to remove UTF-8 * Arabic vowel points * - * $Id: utf8arabicpoints.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: utf8arabicpoints.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 2009-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -163,7 +163,7 @@ char UTF8ArabicPoints::processText(SWBuf &text, const SWKey *, const SWModule *) // "start_of_input" is either mark_pos or any text between the // end of any previous mark and the current mark_pos. // This text is now ready to be moved into the output. - int ready_size = mark_pos - start_of_input; + int ready_size = (int)(mark_pos - start_of_input); if (ready_size > 0) { // Append the input text before the current mark to the // output. diff --git a/src/modules/filters/utf8greekaccents.cpp b/src/modules/filters/utf8greekaccents.cpp index 039f9a4..cd98f96 100644 --- a/src/modules/filters/utf8greekaccents.cpp +++ b/src/modules/filters/utf8greekaccents.cpp @@ -3,7 +3,7 @@ * utf8greekaccents.cpp - SWFilter descendant to remove UTF-8 Greek * accents * - * $Id: utf8greekaccents.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: utf8greekaccents.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -22,8 +22,10 @@ */ #include <stdlib.h> +#include <map> #include <stdio.h> #include <utf8greekaccents.h> +#include <utilstr.h> #ifdef _ICU_ @@ -31,6 +33,7 @@ sword::UTF8NFKD decompose; #endif +using std::map; SWORD_NAMESPACE_START @@ -44,6 +47,297 @@ namespace { static const StringList oVals(&choices[0], &choices[2]); return &oVals; } + + std::map<__u32, SWBuf> converters; + class converters_init { + public: + converters_init() { + SWBuf myBuf = ""; + //first just remove combining characters + converters[0x2019] = ""; // RIGHT SINGLE QUOTATION MARK + converters[0x1FBF] = ""; // GREEK PSILI + converters[0x2CFF] = ""; // COPTIC MORPHOLOGICAL DIVIDER + converters[0xFE24] = ""; // COMBINING MACRON LEFT HALF + converters[0xFE25] = ""; // COMBINING MACRON RIGHT HALF + converters[0xFE26] = ""; // COMBINING CONJOINING MACRON + converters[0x0300] = ""; // COMBINING GRAVE ACCENT + converters[0x0301] = ""; // COMBINING ACUTE ACCENT + converters[0x0302] = ""; // COMBINING CIRCUMFLEX ACCENT + converters[0x0308] = ""; // COMBINING DIAERESIS + converters[0x0313] = ""; // COMBINING COMMA ABOVE + converters[0x0314] = ""; // COMBINING REVERSED COMMA ABOVE + converters[0x037A] = ""; // GREEK YPOGEGRAMMENI + converters[0x0342] = ""; // COMBINING GREEK PERISPOMENI + // Now converted pre-composed characters to their alphabetic bases, discarding the accents + // Greek + // UPPER case + converters[0x0386] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH TONOS + converters[0x0388] = *getUTF8FromUniChar(0x0395, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER EPSILON WITH TONOS + converters[0x0389] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH TONOS + converters[0x038A] = *getUTF8FromUniChar(0x0399, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER IOTA WITH TONOS + converters[0x03AA] = *getUTF8FromUniChar(0x0399, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + converters[0x038C] = *getUTF8FromUniChar(0x039F, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMICRON WITH TONOS + converters[0x038E] = *getUTF8FromUniChar(0x03A5, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER UPSILON WITH TONOS + converters[0x03AB] = *getUTF8FromUniChar(0x03A5, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + converters[0x038F] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH TONOS + + // lower case + converters[0x03AC] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH TONOS + converters[0x03AD] = *getUTF8FromUniChar(0x03B5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER EPSILON WITH TONOS + converters[0x03AE] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH TONOS + converters[0x03AF] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH TONOS + converters[0x03CA] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH DIALYTIKA + converters[0x03CC] = *getUTF8FromUniChar(0x03BF, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMICRON WITH TONOS + converters[0x03CD] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH TONOS + converters[0x03CB] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH DIALYTIKA + converters[0x03CE] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH TONOS + + // Extended Greek + // UPPER case + converters[0x1F08] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH PSILI + converters[0x1F09] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH DASIA + converters[0x1F0A] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA + converters[0x1F0B] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA + converters[0x1F0C] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA + converters[0x1F0D] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA + converters[0x1F0E] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI + converters[0x1F0F] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI + converters[0x1F88] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI + converters[0x1F89] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI + converters[0x1F8A] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI + converters[0x1F8B] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI + converters[0x1F8C] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI + converters[0x1F8D] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI + converters[0x1F8E] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI + converters[0x1F8F] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI + converters[0x1FB8] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH VRACHY + converters[0x1FB9] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH MACRON + converters[0x1FBA] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH VARIA + converters[0x1FBB] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH OXIA + converters[0x1FBC] = *getUTF8FromUniChar(0x0391, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI + + converters[0x1F18] = *getUTF8FromUniChar(0x0395, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER EPSILON WITH PSILI + converters[0x1F19] = *getUTF8FromUniChar(0x0395, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER EPSILON WITH DASIA + converters[0x1F1A] = *getUTF8FromUniChar(0x0395, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA + converters[0x1F1B] = *getUTF8FromUniChar(0x0395, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA + converters[0x1F1C] = *getUTF8FromUniChar(0x0395, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA + converters[0x1F1D] = *getUTF8FromUniChar(0x0395, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA + converters[0x1FC8] = *getUTF8FromUniChar(0x0395, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER EPSILON WITH VARIA + converters[0x1FC9] = *getUTF8FromUniChar(0x0395, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER EPSILON WITH OXIA + + converters[0x1F28] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH PSILI + converters[0x1F29] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH DASIA + converters[0x1F2A] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA + converters[0x1F2B] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA + converters[0x1F2C] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA + converters[0x1F2D] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA + converters[0x1F2E] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI + converters[0x1F2F] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI + converters[0x1F98] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI + converters[0x1F99] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI + converters[0x1F9A] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI + converters[0x1F9B] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI + converters[0x1F9C] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI + converters[0x1F9D] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI + converters[0x1F9E] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI + converters[0x1F9F] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI + converters[0x1FCA] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH VARIA + converters[0x1FCB] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH OXIA + converters[0x1FCC] = *getUTF8FromUniChar(0x0397, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI + + converters[0x1F38] = *getUTF8FromUniChar(0x0399, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER IOTA WITH PSILI + converters[0x1F39] = *getUTF8FromUniChar(0x0399, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER IOTA WITH DASIA + converters[0x1F3A] = *getUTF8FromUniChar(0x0399, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA + converters[0x1F3B] = *getUTF8FromUniChar(0x0399, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA + converters[0x1F3C] = *getUTF8FromUniChar(0x0399, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA + converters[0x1F3D] = *getUTF8FromUniChar(0x0399, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA + converters[0x1F3E] = *getUTF8FromUniChar(0x0399, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI + converters[0x1F3F] = *getUTF8FromUniChar(0x0399, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI + converters[0x1FD8] = *getUTF8FromUniChar(0x0399, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER IOTA WITH VRACHY + converters[0x1FD9] = *getUTF8FromUniChar(0x0399, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER IOTA WITH MACRON + converters[0x1FDA] = *getUTF8FromUniChar(0x0399, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER IOTA WITH VARIA + converters[0x1FDB] = *getUTF8FromUniChar(0x0399, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER IOTA WITH OXIA + + converters[0x1F48] = *getUTF8FromUniChar(0x039F, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMICRON WITH PSILI + converters[0x1F49] = *getUTF8FromUniChar(0x039F, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMICRON WITH DASIA + converters[0x1F4A] = *getUTF8FromUniChar(0x039F, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA + converters[0x1F4B] = *getUTF8FromUniChar(0x039F, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA + converters[0x1F4C] = *getUTF8FromUniChar(0x039F, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA + converters[0x1F4D] = *getUTF8FromUniChar(0x039F, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA + converters[0x1FF8] = *getUTF8FromUniChar(0x039F, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMICRON WITH VARIA + converters[0x1FF9] = *getUTF8FromUniChar(0x039F, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMICRON WITH OXIA + + converters[0x1F59] = *getUTF8FromUniChar(0x03A5, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER UPSILON WITH DASIA + converters[0x1F5A] = *getUTF8FromUniChar(0x03A5, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER UPSILON WITH PSILI AND VARIA + converters[0x1F5B] = *getUTF8FromUniChar(0x03A5, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA + converters[0x1F5C] = *getUTF8FromUniChar(0x03A5, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER UPSILON WITH PSILI AND OXIA + converters[0x1F5D] = *getUTF8FromUniChar(0x03A5, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA + converters[0x1F5E] = *getUTF8FromUniChar(0x03A5, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER UPSILON WITH PSILI AND PERISPOMENI + converters[0x1F5F] = *getUTF8FromUniChar(0x03A5, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI + converters[0x1FE8] = *getUTF8FromUniChar(0x03A5, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER UPSILON WITH VRACHY + converters[0x1FE9] = *getUTF8FromUniChar(0x03A5, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER UPSILON WITH MACRON + converters[0x1FEA] = *getUTF8FromUniChar(0x03A5, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER UPSILON WITH VARIA + converters[0x1FEB] = *getUTF8FromUniChar(0x03A5, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER UPSILON WITH OXIA + + converters[0x1F68] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH PSILI + converters[0x1F69] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH DASIA + converters[0x1F6A] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA + converters[0x1F6B] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA + converters[0x1F6C] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA + converters[0x1F6D] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA + converters[0x1F6E] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI + converters[0x1F6F] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI + converters[0x1FA8] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI + converters[0x1FA9] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI + converters[0x1FAA] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI + converters[0x1FAB] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI + converters[0x1FAC] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI + converters[0x1FAD] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI + converters[0x1FAE] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI + converters[0x1FAF] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI + converters[0x1FFA] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH VARIA + converters[0x1FFB] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH OXIA + converters[0x1FFC] = *getUTF8FromUniChar(0x03A9, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI + + converters[0x1FEC] = *getUTF8FromUniChar(0x03A1, &myBuf); myBuf.setSize(0); // GREEK CAPITAL LETTER RHO WITH DASIA + + // lower case + //alpha + converters[0x1F00] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH PSILI + converters[0x1F01] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH DASIA + converters[0x1F02] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA + converters[0x1F03] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA + converters[0x1F04] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA + converters[0x1F05] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA + converters[0x1F06] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI + converters[0x1F07] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI + converters[0x1F80] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI + converters[0x1F81] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI + converters[0x1F82] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI + converters[0x1F83] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI + converters[0x1F84] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI + converters[0x1F85] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI + converters[0x1F86] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI + converters[0x1F87] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI + converters[0x1F70] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH VARIA + converters[0x1F71] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH OXIA + converters[0x1FB0] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH VRACHY + converters[0x1FB1] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH MACRON + converters[0x1FB2] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI + converters[0x1FB3] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI + converters[0x1FB4] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI + converters[0x1FB5] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // unused? + converters[0x1FB6] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH PERISPOMENI + converters[0x1FB7] = *getUTF8FromUniChar(0x03B1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI + + converters[0x1F10] = *getUTF8FromUniChar(0x03B5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER EPSILON WITH PSILI + converters[0x1F11] = *getUTF8FromUniChar(0x03B5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER EPSILON WITH DASIA + converters[0x1F12] = *getUTF8FromUniChar(0x03B5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA + converters[0x1F13] = *getUTF8FromUniChar(0x03B5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA + converters[0x1F14] = *getUTF8FromUniChar(0x03B5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA + converters[0x1F15] = *getUTF8FromUniChar(0x03B5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA + converters[0x1F72] = *getUTF8FromUniChar(0x03B5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER EPSILON WITH VARIA + converters[0x1F73] = *getUTF8FromUniChar(0x03B5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER EPSILON WITH OXIA + + converters[0x1F90] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI + converters[0x1F91] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI + converters[0x1F92] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI + converters[0x1F93] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI + converters[0x1F94] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI + converters[0x1F95] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI + converters[0x1F96] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI + converters[0x1F97] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI + converters[0x1F20] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH PSILI + converters[0x1F21] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH DASIA + converters[0x1F22] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH PSILI AND VARIA + converters[0x1F23] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH DASIA AND VARIA + converters[0x1F24] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH PSILI AND OXIA + converters[0x1F25] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH DASIA AND OXIA + converters[0x1F26] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI + converters[0x1F27] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI + converters[0x1FC2] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI + converters[0x1FC3] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI + converters[0x1FC4] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI + converters[0x1FC5] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // unused? + converters[0x1FC6] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH PERISPOMENI + converters[0x1FC7] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI + converters[0x1F74] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH VARIA + converters[0x1F75] = *getUTF8FromUniChar(0x03B7, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER ETA WITH OXIA + + converters[0x1F30] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH PSILI + converters[0x1F31] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH DASIA + converters[0x1F32] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH PSILI AND VARIA + converters[0x1F33] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH DASIA AND VARIA + converters[0x1F34] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH PSILI AND OXIA + converters[0x1F35] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH DASIA AND OXIA + converters[0x1F36] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI + converters[0x1F37] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI + converters[0x1F76] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH VARIA + converters[0x1F77] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH OXIA + converters[0x1FD0] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH VRACHY + converters[0x1FD1] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH MACRON + converters[0x1FD2] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA + converters[0x1FD3] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA + converters[0x1FD4] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // unused? + converters[0x1FD5] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // unused? + converters[0x1FD6] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH PERISPOMENI + converters[0x1FD7] = *getUTF8FromUniChar(0x03B9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI + + converters[0x1F40] = *getUTF8FromUniChar(0x03BF, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMICRON WITH PSILI + converters[0x1F41] = *getUTF8FromUniChar(0x03BF, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMICRON WITH DASIA + converters[0x1F42] = *getUTF8FromUniChar(0x03BF, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA + converters[0x1F43] = *getUTF8FromUniChar(0x03BF, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA + converters[0x1F44] = *getUTF8FromUniChar(0x03BF, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA + converters[0x1F45] = *getUTF8FromUniChar(0x03BF, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA + converters[0x1F78] = *getUTF8FromUniChar(0x03BF, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMICRON WITH VARIA + converters[0x1F79] = *getUTF8FromUniChar(0x03BF, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMICRON WITH OXIA + + converters[0x1F50] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH PSILI + converters[0x1F51] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH DASIA + converters[0x1F52] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA + converters[0x1F53] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA + converters[0x1F54] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA + converters[0x1F55] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA + converters[0x1F56] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI + converters[0x1F57] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI + converters[0x1F7A] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH VARIA + converters[0x1F7B] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH OXIA + converters[0x1FE0] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH VRACHY + converters[0x1FE1] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH MACRON + converters[0x1FE2] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA + converters[0x1FE3] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA + converters[0x1FE6] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH PERISPOMENI + converters[0x1FE7] = *getUTF8FromUniChar(0x03C5, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI + + converters[0x1F60] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH PSILI + converters[0x1F61] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH DASIA + converters[0x1F62] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA + converters[0x1F63] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA + converters[0x1F64] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA + converters[0x1F65] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA + converters[0x1F66] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI + converters[0x1F67] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI + converters[0x1F7C] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH VARIA + converters[0x1F7D] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH OXIA + converters[0x1FA0] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI + converters[0x1FA1] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI + converters[0x1FA2] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI + converters[0x1FA3] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI + converters[0x1FA4] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI + converters[0x1FA5] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI + converters[0x1FA6] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI + converters[0x1FA7] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI + converters[0x1FF2] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI + converters[0x1FF3] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI + converters[0x1FF4] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI + converters[0x1FF5] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // unused? + converters[0x1FF6] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH PERISPOMENI + converters[0x1FF7] = *getUTF8FromUniChar(0x03C9, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI + + converters[0x1FE4] = *getUTF8FromUniChar(0x03C1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER RHO WITH PSILI + converters[0x1FE5] = *getUTF8FromUniChar(0x03C1, &myBuf); myBuf.setSize(0); // GREEK SMALL LETTER RHO WITH DASIA + } + } __converters_init; } @@ -57,229 +351,24 @@ UTF8GreekAccents::~UTF8GreekAccents() {}; char UTF8GreekAccents::processText(SWBuf &text, const SWKey *key, const SWModule *module) { if (!option) { //we don't want greek accents - //unsigned char *to, *from; - //to = (unsigned char*)text; - //for (from = (unsigned char*)text; *from; from++) { -#ifdef _ICU_ - decompose.processText(text, (SWKey *)2); // note the hack of 2 to mimic a real key. TODO: remove all hacks -#endif - SWBuf orig = text; const unsigned char* from = (unsigned char*)orig.c_str(); - for (text = ""; *from; from++) { - //first just remove combining characters - if (*from == 0xE2 && *(from + 1) == 0x80 && *(from + 2) == 0x99) { - from += 2; - } - else if (*from == 0xCC && *(from + 1)) { - if (*(from + 1) == 0x80 || *(from + 1) == 0x81 || *(from + 1) == 0x82 || *(from + 1) == 0x88 || *(from + 1) == 0x93 || *(from + 1) == 0x94) { - from++; - } - } - else if (*from == 0xCD && (*(from + 1) == 0xBA || *(from + 1) == 0x82)) { - from++; - } - //now converted pre-composed characters to their alphabetic bases, discarding the accents - - //Greek - //capital alpha - else if ((*from == 0xCE && *(from + 1) == 0x86)) { - text += 0xCE; - text += 0x91; - from++; - } - //capital epsilon - else if ((*from == 0xCE && *(from + 1) == 0x88)) { - text += 0xCE; - text += 0x95; - from++; - } - //capital eta - else if ((*from == 0xCE && *(from + 1) == 0x89)) { - text += 0xCE; - text += 0x97; - from++; - } - //capital iota - else if ((*from == 0xCE && (*(from + 1) == 0x8A || *(from + 1) == 0xAA))) { - text += 0xCE; - text += 0x99; - from++; - } - //capital omicron - else if ((*from == 0xCE && *(from + 1) == 0x8C)) { - text += 0xCE; - text += 0x9F; - from++; - } - //capital upsilon - else if ((*from == 0xCE && (*(from + 1) == 0x8E || *(from + 1) == 0xAB))) { - text += 0xCE; - text += 0xA5; - from++; - } - //capital omega - else if ((*from == 0xCE && *(from + 1) == 0x8F)) { - text += 0xCE; - text += 0xA9; - from++; - } - - //alpha - else if ((*from == 0xCE && *(from + 1) == 0xAC)) { - text += 0xCE; - text += 0xB1; - from++; - } - //epsilon - else if ((*from == 0xCE && *(from + 1) == 0xAD)) { - text += 0xCE; - text += 0xB5; - from++; - } - //eta - else if ((*from == 0xCE && *(from + 1) == 0xAE)) { - text += 0xCE; - text += 0xB7; - from++; - } - //iota - else if ((*from == 0xCE && *(from + 1) == 0xAF) || (*from == 0xCF && *(from + 1) == 0x8A)) { - text += 0xCE; - text += 0xB9; - from++; - } - //omicron - else if ((*from == 0xCF && *(from + 1) == 0x8C)) { - text += 0xCE; - text += 0xBF; - from++; - } - //upsilon - else if ((*from == 0xCE && *(from + 1) == 0x88) || (*from == 0xCF && (*(from + 1) == 0x8B || *(from + 1) == 0x8D))) { - text += 0xCF; - text += 0x85; - from++; - } - //omega - else if ((*from == 0xCF && *(from + 1) == 0x8E)) { - text += 0xCF; - text += 0x89; - from++; - } - - //Extended Greek - //capital alpha - else if (*from == 0xE1 && (((*(from + 1) == 0xBC || *(from + 1) == 0xBE) && *(from + 2) >= 0x88 && *(from + 2) <= 0x8F) || (*(from + 1) == 0xBE && *(from + 2) >= 0xB8 && *(from + 2) <= 0xBC))) { - text += 0xCE; - text += 0x91; - from+=2; - } - //capital epsilon - else if (*from == 0xE1 && ((*(from + 1) == 0xBC && *(from + 2) >= 0x98 && *(from + 2) <= 0x9D) || (*(from + 1) == 0xBF && (*(from + 2) == 0x88 || *(from + 2) == 0x89)))) { - text += 0xCE; - text += 0x95; - from+=2; - } - //capital eta - else if (*from == 0xE1 && ((*(from + 1) == 0xBC && *(from + 2) >= 0xA8 && *(from + 2) <= 0xAF) || (*(from + 1) == 0xBE && *(from + 2) >= 0x98 && *(from + 2) <= 0x9F) || (*(from + 1) == 0xBF && *(from + 2) >= 0x8A && *(from + 2) <= 0x8C))) { - text += 0xCE; - text += 0x97; - from+=2; - } - //capital iota - else if (*from == 0xE1 && ((*(from + 1) == 0xBC && *(from + 2) >= 0xB8 && *(from + 2) <= 0xBF) || (*(from + 1) == 0xBF && *(from + 2) >= 0x98 && *(from + 2) <= 0x9B))) { - text += 0xCE; - text += 0x99; - from+=2; - } - //capital omicron - else if (*from == 0xE1 && (((*(from + 1) == 0xBD && *(from + 2) >= 0x88 && *(from + 2) <= 0x8D)) || ((*(from + 1) == 0xBF && (*(from + 2) == 0xB8 || *(from + 2) == 0xB9))))) { - text += 0xCE; - text += 0x9F; - from+=2; - } - //capital upsilon - else if (*from == 0xE1 && ((*(from + 1) == 0xBD && *(from + 2) >= 0x99 && *(from + 2) <= 0x9F) || (*(from + 1) == 0xBF && *(from + 2) >= 0xA8 && *(from + 2) <= 0xAB))) { - text += 0xCE; - text += 0xA5; - from+=2; - } - //capital omega - else if (*from == 0xE1 && (((*(from + 1) == 0xBD || *(from + 1) == 0xBE) && *(from + 2) >= 0xA8 && *(from + 2) <= 0xAF) || (*(from + 1) == 0xBF && *(from + 2) >= 0xBA && *(from + 2) <= 0xBC))) { - text += 0xCE; - text += 0xA9; - from+=2; - } - //capital rho - else if (*from == 0xE1 && *(from + 1) == 0xBF && *(from + 2) == 0xAC) { - text += 0xCE; - text += 0xA1; - from+=2; - } + text = ""; + map<__u32, SWBuf>::const_iterator it = converters.end(); + while (*from) { + __u32 ch = getUniCharFromUTF8(&from, true); + // if ch is bad, then convert to replacement char + if (!ch) ch = 0xFFFD; - //alpha - else if (*from == 0xE1 && ( - ((*(from + 1) == 0xBC || *(from + 1) == 0xBE) && *(from + 2) >= 0x80 && *(from + 2) <= 0x87) - || (*(from + 1) == 0xBD && (*(from + 2) == 0xB0 || *(from + 2) == 0xB1)) - || (*(from + 1) == 0xBE && *(from + 2) >= 0xB0 && *(from + 2) <= 0xB7))) { - text += 0xCE; - text += 0xB1; - from+=2; - } - //epsilon - else if (*from == 0xE1 && ((*(from + 1) == 0xBC && *(from + 2) >= 0x90 && *(from + 2) <= 0x95) || (*(from + 1) == 0xBD && (*(from + 2) == 0xB2 || *(from + 2) == 0xB3)))) { - text += 0xCE; - text += 0xB5; - from+=2; - } - //eta - else if (*from == 0xE1 && ((*(from + 1) == 0xBE && *(from + 2) >= 0x90 && *(from + 2) <= 0x97) || (*(from + 1) == 0xBC && *(from + 2) >= 0xA0 && *(from + 2) <= 0xA7) || (*(from + 1) == 0xBF && *(from + 2) >= 0x82 && *(from + 2) <= 0x87) || (*(from + 1) == 0xBD && (*(from + 2) == 0xB4 || *(from + 2) == 0xB5)))) { - text += 0xCE; - text += 0xB7; - from+=2; - } - //iota - else if (*from == 0xE1 && ((*(from + 1) == 0xBC && *(from + 2) >= 0xB0 && *(from + 2) <= 0xB7) || (*(from + 1) == 0xBD && (*(from + 2) == 0xB6 || *(from + 2) == 0xB7)) || (*(from + 1) == 0xBF && *(from + 2) >= 0x90 && *(from + 2) <= 0x97))) { - text += 0xCE; - text += 0xB9; - from+=2; - } - //omicron - else if (*from == 0xE1 && (*(from + 1) == 0xBD && ((*(from + 2) >= 0x80 && *(from + 2) <= 0x85) || (*(from + 2) == 0xB8 || *(from + 2) == 0xB9)))) { - text += 0xCE; - text += 0xBF; - from+=2; - } - //upsilon - else if (*from == 0xE1 && ((*(from + 1) == 0xBD && ((*(from + 2) >= 0x90 && *(from + 2) <= 0x97) || *(from + 2) == 0xBA || *(from + 2) == 0xBB)) || (*(from + 1) == 0xBF && ((*(from + 2) >= 0xA0 && *(from + 2) <= 0xA3) || *(from + 2) == 0xA6 || *(from + 2) == 0xA7)))) { - text += 0xCF; - text += 0x85; - from+=2; - } - //omega - else if (*from == 0xE1 && ((*(from + 1) == 0xBD && ((*(from + 2) >= 0xA0 && *(from + 2) <= 0xA7) || (*(from + 2) == 0xBC || *(from + 2) == 0xBD))) || (*(from + 1) == 0xBE && (*(from + 2) >= 0xA0 && *(from + 2) <= 0xA7)) || (*(from + 1) == 0xBF && *(from + 2) >= 0xB2 && *(from + 2) <= 0xB7))) { - text += 0xCF; - text += 0x89; - from+=2; - } - //rho - else if (*from == 0xE1 && *(from + 1) == 0xBF && (*(from + 2) == 0xA4 && *(from + 2) == 0xA5)) { - text += 0xCF; - text += 0x81; - from+=2; - } - else { //no characters we filter - text += *from; + it = converters.find(ch); + if (it == converters.end()) { + getUTF8FromUniChar(ch, &text); } + else text.append((const char *)it->second, it->second.size()); // save a strlen, since we know our size } } return 0; } - - - - SWORD_NAMESPACE_END diff --git a/src/modules/filters/utf8html.cpp b/src/modules/filters/utf8html.cpp index d504418..0a9eeb8 100644 --- a/src/modules/filters/utf8html.cpp +++ b/src/modules/filters/utf8html.cpp @@ -3,7 +3,7 @@ * utf8html.cpp - SWFilter descendant to convert a UTF-8 stream to * HTML escapes * - * $Id: utf8html.cpp 3157 2014-04-17 03:56:12Z greg.hellings $ + * $Id: utf8html.cpp 3081 2014-03-05 19:52:08Z chrislit $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society diff --git a/src/modules/filters/utf8latin1.cpp b/src/modules/filters/utf8latin1.cpp index db5237c..6408e10 100644 --- a/src/modules/filters/utf8latin1.cpp +++ b/src/modules/filters/utf8latin1.cpp @@ -2,7 +2,7 @@ * * utf8latin1.cpp - SWFilter descendant to convert UTF-8 to Latin-1 * - * $Id: utf8latin1.cpp 3157 2014-04-17 03:56:12Z greg.hellings $ + * $Id: utf8latin1.cpp 3081 2014-03-05 19:52:08Z chrislit $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society diff --git a/src/modules/filters/utf8nfc.cpp b/src/modules/filters/utf8nfc.cpp index 06bd76f..16a5c54 100644 --- a/src/modules/filters/utf8nfc.cpp +++ b/src/modules/filters/utf8nfc.cpp @@ -3,7 +3,7 @@ * utf8nfc.cpp - SWFilter descendant to perform NFC (canonical * composition normalization) on UTF-8 text * - * $Id: utf8nfc.cpp 3157 2014-04-17 03:56:12Z greg.hellings $ + * $Id: utf8nfc.cpp 3081 2014-03-05 19:52:08Z chrislit $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society diff --git a/src/modules/filters/utf8nfkd.cpp b/src/modules/filters/utf8nfkd.cpp index 3a782ab..047422a 100644 --- a/src/modules/filters/utf8nfkd.cpp +++ b/src/modules/filters/utf8nfkd.cpp @@ -3,7 +3,7 @@ * utf8nfkd.cpp - SWFilter descendant to perform NFKD (compatability * decomposition normalization) on UTF-8 text * - * $Id: utf8nfkd.cpp 3157 2014-04-17 03:56:12Z greg.hellings $ + * $Id: utf8nfkd.cpp 3081 2014-03-05 19:52:08Z chrislit $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society diff --git a/src/modules/filters/utf8scsu.cpp b/src/modules/filters/utf8scsu.cpp new file mode 100644 index 0000000..bf5bd41 --- /dev/null +++ b/src/modules/filters/utf8scsu.cpp @@ -0,0 +1,61 @@ +/****************************************************************************** + * + * utf8scsu.cpp - SWFilter descendant to convert UTF-8 to SCSU + * + * $Id: utf8scsu.cpp 3100 2014-03-12 04:34:32Z chrislit $ + * + * Copyright 2001-2014 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. + * + */ + +#ifdef _ICU_ + +#include <utf8scsu.h> +#include <swbuf.h> + +SWORD_NAMESPACE_START + + +UTF8SCSU::UTF8SCSU() { + // initialize SCSU converter + scsuConv = ucnv_open("SCSU", &err); + + // initialize UTF-8 converter + utf8Conv = ucnv_open("UTF-8", &err); +} + +UTF8SCSU::~UTF8SCSU() { + ucnv_close(scsuConv); + ucnv_close(utf8Conv); +} + +char UTF8SCSU::processText(SWBuf &text, const SWKey *key, const SWModule *module) { + if ((unsigned long)key < 2) // hack, we're en(1)/de(0)ciphering + return -1; + + err = U_ZERO_ERROR; + UnicodeString utf16Text(text.getRawData(), text.length(), utf8Conv, err); + err = U_ZERO_ERROR; + int32_t len = utf16Text.extract(text.getRawData(), text.size(), scsuConv, err); + if (len > (int32_t)text.size()+1) { + text.setSize(len+1); + utf16Text.extract(text.getRawData(), text.size(), scsuConv, err); + } + + return 0; +} + +SWORD_NAMESPACE_END +#endif diff --git a/src/modules/filters/utf8utf16.cpp b/src/modules/filters/utf8utf16.cpp index 958f1d9..d969dba 100644 --- a/src/modules/filters/utf8utf16.cpp +++ b/src/modules/filters/utf8utf16.cpp @@ -2,7 +2,7 @@ * * utf8utf16.cpp - SWFilter descendant to convert UTF-8 to UTF-16 * - * $Id: utf8utf16.cpp 3157 2014-04-17 03:56:12Z greg.hellings $ + * $Id: utf8utf16.cpp 3081 2014-03-05 19:52:08Z chrislit $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society diff --git a/src/modules/genbook/rawgenbook/rawgenbook.cpp b/src/modules/genbook/rawgenbook/rawgenbook.cpp index 6101241..41cd6e4 100644 --- a/src/modules/genbook/rawgenbook/rawgenbook.cpp +++ b/src/modules/genbook/rawgenbook/rawgenbook.cpp @@ -3,7 +3,7 @@ * rawgenbook.cpp - code for class 'RawGenBook'- a module that reads raw * text files: ot and nt using indexs ??.bks ??.cps ??.vss * - * $Id: rawgenbook.cpp 2833 2013-06-29 06:40:28Z chrislit $ + * $Id: rawgenbook.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 2002-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -133,7 +133,7 @@ SWBuf &RawGenBook::getRawEntryBuf() const { void RawGenBook::setEntry(const char *inbuf, long len) { - __u32 offset = archtosword32(bdtfd->seek(0, SEEK_END)); + __u32 offset = (__u32)archtosword32(bdtfd->seek(0, SEEK_END)); __u32 size = 0; TreeKeyIdx *key = ((TreeKeyIdx *)&(getTreeKey())); @@ -144,7 +144,7 @@ void RawGenBook::setEntry(const char *inbuf, long len) { bdtfd->write(inbuf, len); - size = archtosword32(len); + size = (__u32)archtosword32(len); memcpy(userData, &offset, 4); memcpy(userData+4, &size, 4); key->setUserData(userData, 8); diff --git a/src/modules/lexdict/rawld/rawld.cpp b/src/modules/lexdict/rawld/rawld.cpp index 7446c10..719db56 100644 --- a/src/modules/lexdict/rawld/rawld.cpp +++ b/src/modules/lexdict/rawld/rawld.cpp @@ -3,7 +3,7 @@ * rawld.cpp - code for class 'RawLD'- a module that reads raw lexicon and * dictionary files: *.dat *.idx * - * $Id: rawld.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: rawld.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 1998-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -147,12 +147,26 @@ void RawLD::increment(int steps) { void RawLD::setEntry(const char *inbuf, long len) { - doSetText(*key, inbuf, len); + char *buf = new char [ strlen(*key) + 6 ]; + strcpy(buf, *key); + + if (strongsPadding) strongsPad(buf); + + doSetText(buf, inbuf, len); + + delete [] buf; } void RawLD::linkEntry(const SWKey *inkey) { - doLinkEntry(*key, *inkey); + char *buf = new char [ strlen(*key) + 6 ]; + strcpy(buf, *key); + + if (strongsPadding) strongsPad(buf); + + doLinkEntry(buf, *inkey); + + delete [] buf; } @@ -163,12 +177,19 @@ void RawLD::linkEntry(const SWKey *inkey) { */ void RawLD::deleteEntry() { - doSetText(*key, ""); + char *buf = new char [ strlen(*key) + 6 ]; + strcpy(buf, *key); + + if (strongsPadding) strongsPad(buf); + + doSetText(buf, ""); + + delete [] buf; } long RawLD::getEntryCount() const { - if (idxfd < 0) return 0; + if (!idxfd || idxfd->getFd() < 0) return 0; return idxfd->seek(0, SEEK_END) / IDXENTRYSIZE; } diff --git a/src/modules/lexdict/rawld4/rawld4.cpp b/src/modules/lexdict/rawld4/rawld4.cpp index 1f81d83..e8ec811 100644 --- a/src/modules/lexdict/rawld4/rawld4.cpp +++ b/src/modules/lexdict/rawld4/rawld4.cpp @@ -3,7 +3,7 @@ * rawld4.cpp - code for class 'RawLD'- a module that reads raw * lexicon and dictionary files: *.dat *.idx * - * $Id: rawld4.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: rawld4.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -81,7 +81,7 @@ char RawLD4::getEntry(long away) const char *buf = new char [ strlen(*key) + 6 ]; strcpy(buf, *key); - strongsPad(buf); + if (strongsPadding) strongsPad(buf); entryBuf = ""; if (!(retval = findOffset(buf, &start, &size, away))) { @@ -145,12 +145,26 @@ void RawLD4::increment(int steps) { void RawLD4::setEntry(const char *inbuf, long len) { - doSetText(*key, inbuf, len); + char *buf = new char [ strlen(*key) + 6 ]; + strcpy(buf, *key); + + if (strongsPadding) strongsPad(buf); + + doSetText(buf, inbuf, len); + + delete [] buf; } void RawLD4::linkEntry(const SWKey *inkey) { - doLinkEntry(*key, *inkey); + char *buf = new char [ strlen(*key) + 6 ]; + strcpy(buf, *key); + + if (strongsPadding) strongsPad(buf); + + doLinkEntry(buf, *inkey); + + delete [] buf; } @@ -161,12 +175,19 @@ void RawLD4::linkEntry(const SWKey *inkey) { */ void RawLD4::deleteEntry() { - doSetText(*key, ""); + char *buf = new char [ strlen(*key) + 6 ]; + strcpy(buf, *key); + + if (strongsPadding) strongsPad(buf); + + doSetText(buf, ""); + + delete [] buf; } long RawLD4::getEntryCount() const { - if (idxfd < 0) return 0; + if (!idxfd || idxfd->getFd() < 0) return 0; return idxfd->seek(0, SEEK_END) / IDXENTRYSIZE; } @@ -178,7 +199,7 @@ long RawLD4::getEntryForKey(const char *key) const { char *buf = new char [ strlen(key) + 6 ]; strcpy(buf, key); - strongsPad(buf); + if (strongsPadding) strongsPad(buf); findOffset(buf, &start, &size, 0, &offset); diff --git a/src/modules/lexdict/swld.cpp b/src/modules/lexdict/swld.cpp index 5e1909b..7d724bc 100644 --- a/src/modules/lexdict/swld.cpp +++ b/src/modules/lexdict/swld.cpp @@ -3,7 +3,7 @@ * swld.cpp - code for base class 'SWLD'. SWLD is the basis for all * types of Lexicon and Dictionary modules (hence the 'LD'). * - * $Id: swld.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: swld.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 1997-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -108,7 +108,7 @@ bool SWLD::hasEntry(const SWKey *key) const { if (strongsPadding) strongsPad(buf); bool retVal = !strcmp(buf, getKeyForEntry(getEntryForKey(buf))); - delete buf; + delete [] buf; return retVal; } @@ -125,7 +125,7 @@ void SWLD::strongsPad(char *buf) { char *check; int size = 0; - int len = strlen(buf); + int len = (int)strlen(buf); char subLet = 0; bool bang = false, prefix=false; if ((len < 9) && (len > 0)) { diff --git a/src/modules/lexdict/zld/zld.cpp b/src/modules/lexdict/zld/zld.cpp index 71919d4..5bc0852 100644 --- a/src/modules/lexdict/zld/zld.cpp +++ b/src/modules/lexdict/zld/zld.cpp @@ -3,7 +3,7 @@ * zld.cpp - code for class 'zLD'- a module that reads zlib compressed * lexicon and dictionary files * - * $Id: zld.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: zld.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2001-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -90,7 +90,7 @@ char zLD::getEntry(long away) const { rawFilter(entryBuf, key); - entrySize = size; // support getEntrySize call + entrySize = (int)size; // support getEntrySize call if (!key->isPersist()) // If we have our own key *key = idxbuf; // reset it to entry index buffer @@ -144,12 +144,26 @@ void zLD::increment(int steps) { void zLD::setEntry(const char *inbuf, long len) { - setText(*key, inbuf, len); + char *buf = new char [ strlen(*key) + 6 ]; + strcpy(buf, *key); + + if (strongsPadding) strongsPad(buf); + + setText(buf, inbuf, len); + + delete [] buf; } void zLD::linkEntry(const SWKey *inkey) { - zStr::linkEntry(*key, *inkey); + char *buf = new char [ strlen(*key) + 6 ]; + strcpy(buf, *key); + + if (strongsPadding) strongsPad(buf); + + zStr::linkEntry(buf, *inkey); + + delete [] buf; } @@ -160,13 +174,20 @@ void zLD::linkEntry(const SWKey *inkey) { */ void zLD::deleteEntry() { - setText(*key, ""); + char *buf = new char [ strlen(*key) + 6 ]; + strcpy(buf, *key); + + if (strongsPadding) strongsPad(buf); + + setText(buf, ""); + + delete [] buf; } long zLD::getEntryCount() const { - if (idxfd < 0) return 0; + if (!idxfd || idxfd->getFd() < 0) return 0; return idxfd->seek(0, SEEK_END) / IDXENTRYSIZE; } diff --git a/src/modules/swmodule.cpp b/src/modules/swmodule.cpp index a2d7873..e6ceeda 100644 --- a/src/modules/swmodule.cpp +++ b/src/modules/swmodule.cpp @@ -4,7 +4,7 @@ * for all types of modules (e.g. texts, commentaries, * maps, lexicons, etc.) * - * $Id: swmodule.cpp 3282 2014-12-03 06:09:06Z greg.hellings $ + * $Id: swmodule.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 1999-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -39,16 +39,23 @@ #include <iostream> #endif -#ifdef USECXX11REGEX +#if defined(USECXX11REGEX) #include <regex> #ifndef REG_ICASE #define REG_ICASE std::regex::icase #endif +#elif defined(USEICUREGEX) +#include <unicode/regex.h> +#ifndef REG_ICASE +#define REG_ICASE UREGEX_CASE_INSENSITIVE +#endif #else #include <regex.h> // GNU #endif -#ifdef USELUCENE +#if defined USEXAPIAN +#include <xapian.h> +#elif defined USELUCENE #include <CLucene.h> //Lucence includes @@ -171,6 +178,7 @@ char SWModule::popError() char retval = error; error = 0; + if (!retval) retval = key->popError(); return retval; } @@ -295,7 +303,7 @@ char SWModule::setKey(const SWKey *ikey) { if (oldKey) delete oldKey; - return error = key->popError(); + return error = key->getError(); } @@ -313,13 +321,13 @@ void SWModule::setPosition(SW_POSITION p) { switch (p) { case POS_TOP: - (*this)++; - (*this)--; + this->increment(); + this->decrement(); break; case POS_BOTTOM: - (*this)--; - (*this)++; + this->decrement(); + this->increment(); break; } @@ -360,7 +368,7 @@ void SWModule::decrement(int steps) { * * ENT: istr - string for which to search * searchType - type of search to perform - * >=0 - regex + * >=0 - regex; (for backward compat, if > 0 then used as additional REGEX FLAGS) * -1 - phrase * -2 - multiword * -3 - entryAttrib (eg. Word//Lemma./G1234/) (Lemma with dot means check components (Lemma.[1-9]) also) @@ -379,16 +387,22 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc SWBuf term = istr; bool includeComponents = false; // for entryAttrib e.g., /Lemma.1/ -#ifdef USELUCENE SWBuf target = getConfigEntry("AbsoluteDataPath"); if (!target.endsWith("/") && !target.endsWith("\\")) { target.append('/'); } +#if defined USEXAPIAN + target.append("xapian"); +#elif defined USELUCENE target.append("lucene"); #endif if (justCheckIfSupported) { *justCheckIfSupported = (searchType >= -3); -#ifdef USELUCENE +#if defined USEXAPIAN + if ((searchType == -4) && (FileMgr::existsDir(target))) { + *justCheckIfSupported = true; + } +#elif defined USELUCENE if ((searchType == -4) && (IndexReader::indexExists(target.c_str()))) { *justCheckIfSupported = true; } @@ -407,6 +421,8 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc std::locale::global(std::locale("en_US.UTF-8")); std::regex preg; +#elif defined(USEICUREGEX) + RegexMatcher *matcher = 0; #else regex_t preg; #endif @@ -449,18 +465,48 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc *this = TOP; if (searchType >= 0) { #ifdef USECXX11REGEX - preg = std::regex((SWBuf(".*")+istr+".*").c_str(), std::regex_constants::extended & flags); + preg = std::regex((SWBuf(".*")+istr+".*").c_str(), std::regex_constants::extended | searchType | flags); +#elif defined(USEICUREGEX) + UErrorCode status = U_ZERO_ERROR; + matcher = new RegexMatcher(istr, searchType | flags, status); + if (U_FAILURE(status)) { + SWLog::getSystemLog()->logError("Error compiling Regex: %d", status); + return listKey; + } + #else flags |=searchType|REG_NOSUB|REG_EXTENDED; - regcomp(&preg, istr, flags); + int err = regcomp(&preg, istr, flags); + if (err) { + SWLog::getSystemLog()->logError("Error compiling Regex: %d", err); + return listKey; + } #endif } (*percent)(++perc, percentUserData); -#ifdef USELUCENE - if (searchType == -4) { // lucene +#if defined USEXAPIAN || defined USELUCENE + (*percent)(10, percentUserData); + if (searchType == -4) { // indexed search +#if defined USEXAPIAN + SWTRY { + Xapian::Database database(target.c_str()); + Xapian::QueryParser queryParser; + queryParser.set_default_op(Xapian::Query::OP_AND); + SWTRY { + queryParser.set_stemmer(Xapian::Stem(getLanguage())); + } SWCATCH(...) {} + queryParser.set_stemming_strategy(queryParser.STEM_SOME); + queryParser.add_prefix("content", "C"); + queryParser.add_prefix("lemma", "L"); + queryParser.add_prefix("morph", "M"); + queryParser.add_prefix("prox", "P"); + queryParser.add_prefix("proxlem", "PL"); + queryParser.add_prefix("proxmorph", "PM"); + +#elif defined USELUCENE lucene::index::IndexReader *ir = 0; lucene::search::IndexSearcher *is = 0; @@ -469,22 +515,44 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc SWTRY { ir = IndexReader::open(target); is = new IndexSearcher(ir); - (*percent)(10, percentUserData); - const TCHAR *stopWords[] = { 0 }; standard::StandardAnalyzer analyzer(stopWords); +#endif + + // parse the query +#if defined USEXAPIAN + Xapian::Query q = queryParser.parse_query(istr); + Xapian::Enquire enquire = Xapian::Enquire(database); +#elif defined USELUCENE q = QueryParser::parse((wchar_t *)utf8ToWChar(istr).getRawData(), _T("content"), &analyzer); +#endif (*percent)(20, percentUserData); + + // perform the search +#if defined USEXAPIAN + enquire.set_query(q); + Xapian::MSet h = enquire.get_mset(0, 99999); +#elif defined USELUCENE h = is->search(q); +#endif (*percent)(80, percentUserData); // iterate thru each good module position that meets the search bool checkBounds = getKey()->isBoundSet(); +#if defined USEXAPIAN + Xapian::MSetIterator i; + for (i = h.begin(); i != h.end(); ++i) { +// cout << "Document ID " << *i << "\t"; + __u64 score = i.get_percent(); + Xapian::Document doc = i.get_document(); + *resultKey = doc.get_data().c_str(); +#elif defined USELUCENE for (unsigned long i = 0; i < (unsigned long)h->length(); i++) { Document &doc = h->doc(i); - // set a temporary verse key to this module position *resultKey = wcharToUTF8(doc.get(_T("key"))); //TODO Does a key always accept utf8? + __u64 score = (__u64)((__u32)(h->score(i)*100)); +#endif // check to see if it sets ok (within our bounds) and if not, skip if (checkBounds) { @@ -494,14 +562,19 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc } } listKey << *resultKey; - listKey.getElement()->userData = (__u64)((__u32)(h->score(i)*100)); + listKey.getElement()->userData = score; } (*percent)(98, percentUserData); } SWCATCH (...) { +#if defined USEXAPIAN +#elif defined USELUCENE q = 0; +#endif // invalid clucene query } +#if defined USEXAPIAN +#elif defined USELUCENE delete h; delete q; @@ -509,6 +582,7 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc if (ir) { ir->close(); } +#endif } #endif @@ -587,6 +661,11 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc SWBuf textBuf = stripText(); #ifdef USECXX11REGEX if (std::regex_match(std::string(textBuf.c_str()), preg)) { +#elif defined(USEICUREGEX) + UnicodeString stringToTest = textBuf.c_str(); + matcher->reset(stringToTest); + + if (matcher->find()) { #else if (!regexec(&preg, textBuf, 0, 0, 0)) { #endif @@ -597,6 +676,12 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc } #ifdef USECXX11REGEX else if (std::regex_match(std::string((lastBuf + ' ' + textBuf).c_str()), preg)) { +#elif defined(USEICUREGEX) + else { + stringToTest = (lastBuf + ' ' + textBuf).c_str(); + matcher->reset(stringToTest); + + if (matcher->find()) { #else else if (!regexec(&preg, lastBuf + ' ' + textBuf, 0, 0, 0)) { #endif @@ -607,6 +692,9 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc else { lastBuf = textBuf; } +#if defined(USEICUREGEX) + } +#endif } // phrase @@ -731,6 +819,7 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc } break; } + // NOT DONE case -5: AttributeList &words = getEntryAttributes()["Word"]; SWBuf kjvWord = ""; @@ -789,6 +878,8 @@ ListKey &SWModule::search(const char *istr, int searchType, int flags, SWKey *sc if (searchType >= 0) { #ifdef USECXX11REGEX std::locale::global(oldLocale); +#elif defined(USEICUREGEX) + delete matcher; #else regfree(&preg); #endif @@ -846,14 +937,33 @@ const char *SWModule::getRenderHeader() const { /****************************************************************************** - * SWModule::renderText - calls all renderfilters on current text + * SWModule::renderText - calls all renderfilters on current module + * position + * + * RET: this module's text at current key location massaged by renderText filters + */ +SWBuf SWModule::renderText() { + return renderText((const char *)0); +} + +/****************************************************************************** + * SWModule::renderText - calls all renderfilters on provided text + * or current module position provided text null * - * ENT: buf - buffer to Render instead of current module position + * ENT: buf - buffer to render * * RET: this module's text at current key location massaged by renderText filters + * + * NOTES: This method is only truly const if called with a provided text; using + * module's current position may produce a new entry attributes map which + * logically violates the const semantic, which is why the above method + * which takes no params is not const, i.e., don't call this method with + * null as text param, but instead use non-const method above. The public + * interface for this method expects a value for the text param. We use it + * internally sometimes calling with null to save duplication of code. */ - SWBuf SWModule::renderText(const char *buf, int len, bool render) { +SWBuf SWModule::renderText(const char *buf, int len, bool render) const { bool savePEA = isProcessEntryAttributes(); if (!buf) { entryAttributes.clear(); @@ -873,7 +983,7 @@ const char *SWModule::getRenderHeader() const { if (tmpbuf) { unsigned long size = (len < 0) ? ((getEntrySize()<0) ? strlen(tmpbuf) : getEntrySize()) : len; if (size > 0) { - key = (SWKey *)*this; + key = this->getKey(); optionFilter(tmpbuf, key); @@ -1010,12 +1120,17 @@ void SWModule::deleteSearchFramework() { signed char SWModule::createSearchFramework(void (*percent)(char, void *), void *percentUserData) { -#ifdef USELUCENE +#if defined USELUCENE || defined USEXAPIAN SWBuf target = getConfigEntry("AbsoluteDataPath"); if (!target.endsWith("/") && !target.endsWith("\\")) { target.append('/'); } +#if defined USEXAPIAN + target.append("xapian"); +#elif defined USELUCENE + const int MAX_CONV_SIZE = 1024 * 1024; target.append("lucene"); +#endif int status = FileMgr::createParent(target+"/dummy"); if (status) return -1; @@ -1024,7 +1139,6 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void SWKey textkey; SWBuf c; - const int MAX_CONV_SIZE = 1024 * 1024; // turn all filters to default values StringList filterSettings; @@ -1058,6 +1172,17 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void setKey(*searchKey); } + bool includeKeyInSearch = getConfig().has("SearchOption", "IncludeKeyInSearch"); + + // lets create or open our search index +#if defined USEXAPIAN + Xapian::WritableDatabase database(target.c_str(), Xapian::DB_CREATE_OR_OPEN); + Xapian::TermGenerator termGenerator; + SWTRY { + termGenerator.set_stemmer(Xapian::Stem(getLanguage())); + } SWCATCH(...) {} + +#elif defined USELUCENE RAMDirectory *ramDir = 0; IndexWriter *coreWriter = 0; IndexWriter *fsWriter = 0; @@ -1065,11 +1190,11 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void const TCHAR *stopWords[] = { 0 }; standard::StandardAnalyzer *an = new standard::StandardAnalyzer(stopWords); - bool includeKeyInSearch = getConfig().has("SearchOption", "IncludeKeyInSearch"); ramDir = new RAMDirectory(); coreWriter = new IndexWriter(ramDir, an, true); coreWriter->setMaxFieldLength(MAX_CONV_SIZE); +#endif @@ -1126,7 +1251,12 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void bool good = false; // start out entry +#if defined USEXAPIAN + Xapian::Document doc; + termGenerator.set_document(doc); +#elif defined USELUCENE Document *doc = new Document(); +#endif // get "key" field SWBuf keyText = (vkcheck) ? vkcheck->getOSISRef() : getKeyText(); if (content && *content) { @@ -1172,7 +1302,11 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void } } +#if defined USEXAPIAN + doc.set_data(keyText.c_str()); +#elif defined USELUCENE doc->add(*_CLNEW Field(_T("key"), (wchar_t *)utf8ToWChar(keyText).getRawData(), Field::STORE_YES | Field::INDEX_UNTOKENIZED)); +#endif if (includeKeyInSearch) { c = keyText; @@ -1181,11 +1315,21 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void content = c.c_str(); } +#if defined USEXAPIAN + termGenerator.index_text(content); + termGenerator.index_text(content, 1, "C"); +#elif defined USELUCENE doc->add(*_CLNEW Field(_T("content"), (wchar_t *)utf8ToWChar(content).getRawData(), Field::STORE_NO | Field::INDEX_TOKENIZED)); +#endif if (strong.length() > 0) { +#if defined USEXAPIAN + termGenerator.index_text(strong.c_str(), 1, "L"); + termGenerator.index_text(morph.c_str(), 1, "M"); +#elif defined USELUCENE doc->add(*_CLNEW Field(_T("lemma"), (wchar_t *)utf8ToWChar(strong).getRawData(), Field::STORE_NO | Field::INDEX_TOKENIZED)); doc->add(*_CLNEW Field(_T("morph"), (wchar_t *)utf8ToWChar(morph).getRawData(), Field::STORE_NO | Field::INDEX_TOKENIZED)); +#endif //printf("setting fields (%s).\ncontent: %s\nlemma: %s\n", (const char *)*key, content, strong.c_str()); } @@ -1330,20 +1474,39 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void if (proxBuf.length() > 0) { +#if defined USEXAPIAN + termGenerator.index_text(proxBuf.c_str(), 1, "P"); +#elif defined USELUCENE doc->add(*_CLNEW Field(_T("prox"), (wchar_t *)utf8ToWChar(proxBuf).getRawData(), Field::STORE_NO | Field::INDEX_TOKENIZED)); +#endif good = true; } if (proxLem.length() > 0) { +#if defined USEXAPIAN + termGenerator.index_text(proxLem.c_str(), 1, "PL"); + termGenerator.index_text(proxMorph.c_str(), 1, "PM"); +#elif defined USELUCENE doc->add(*_CLNEW Field(_T("proxlem"), (wchar_t *)utf8ToWChar(proxLem).getRawData(), Field::STORE_NO | Field::INDEX_TOKENIZED) ); doc->add(*_CLNEW Field(_T("proxmorph"), (wchar_t *)utf8ToWChar(proxMorph).getRawData(), Field::STORE_NO | Field::INDEX_TOKENIZED) ); +#endif good = true; } if (good) { //printf("writing (%s).\n", (const char *)*key); //fflush(stdout); +#if defined USEXAPIAN + SWBuf idTerm; + idTerm.setFormatted("Q%ld", key->getIndex()); + doc.add_boolean_term(idTerm.c_str()); + database.replace_document(idTerm.c_str(), doc); +#elif defined USELUCENE coreWriter->addDocument(doc); +#endif } +#if defined USEXAPIAN +#elif defined USELUCENE delete doc; +#endif (*this)++; err = popError(); @@ -1351,6 +1514,8 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void // Optimizing automatically happens with the call to addIndexes //coreWriter->optimize(); +#if defined USEXAPIAN +#elif defined USELUCENE coreWriter->close(); #ifdef CLUCENE2 @@ -1385,6 +1550,7 @@ signed char SWModule::createSearchFramework(void (*percent)(char, void *), void delete coreWriter; delete fsWriter; delete an; +#endif // reposition module back to where it was before we were called setKey(*saveKey); diff --git a/src/modules/texts/Makefile.am b/src/modules/texts/Makefile.am index f5d81b4..2da70fe 100644 --- a/src/modules/texts/Makefile.am +++ b/src/modules/texts/Makefile.am @@ -5,3 +5,4 @@ libsword_la_SOURCES += $(textsdir)/swtext.cpp include ../src/modules/texts/rawtext/Makefile.am include ../src/modules/texts/rawtext4/Makefile.am include ../src/modules/texts/ztext/Makefile.am +include ../src/modules/texts/ztext4/Makefile.am diff --git a/src/modules/texts/rawtext4/Makefile b/src/modules/texts/rawtext4/Makefile index a08e07e..35d6648 100644 --- a/src/modules/texts/rawtext4/Makefile +++ b/src/modules/texts/rawtext4/Makefile @@ -1,5 +1,5 @@ - -root := ../../../.. - -all: - make -C ${root} + +root := ../../../.. + +all: + make -C ${root} diff --git a/src/modules/texts/rawtext4/rawtext4.cpp b/src/modules/texts/rawtext4/rawtext4.cpp index 5980801..caae680 100644 --- a/src/modules/texts/rawtext4/rawtext4.cpp +++ b/src/modules/texts/rawtext4/rawtext4.cpp @@ -3,7 +3,7 @@ * rawtext4.cpp - code for class 'RawText4'- a module that reads raw text * files: ot and nt using indexs ??.bks ??.cps ??.vss * - * $Id: rawtext4.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: rawtext4.cpp 3456 2017-04-24 09:26:34Z scribe $ * * Copyright 2007-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -75,7 +75,7 @@ SWBuf &RawText4::getRawEntryBuf() const { VerseKey &key = getVerseKey(); findOffset(key.getTestament(), key.getTestamentIndex(), &start, &size); - entrySize = size; // support getEntrySize call + entrySize = (int)size; // support getEntrySize call entryBuf = ""; readText(key.getTestament(), start, size, entryBuf); @@ -164,6 +164,7 @@ bool RawText4::isLinked(const SWKey *k1, const SWKey *k2) const { findOffset(vk1->getTestament(), vk1->getTestamentIndex(), &start1, &size1); findOffset(vk2->getTestament(), vk2->getTestamentIndex(), &start2, &size2); + if (!size1 || !size2) return false; return start1 == start2; } diff --git a/src/modules/texts/ztext4/Makefile b/src/modules/texts/ztext4/Makefile new file mode 100644 index 0000000..35d6648 --- /dev/null +++ b/src/modules/texts/ztext4/Makefile @@ -0,0 +1,5 @@ + +root := ../../../.. + +all: + make -C ${root} diff --git a/src/modules/texts/ztext4/Makefile.am b/src/modules/texts/ztext4/Makefile.am new file mode 100644 index 0000000..ae7e544 --- /dev/null +++ b/src/modules/texts/ztext4/Makefile.am @@ -0,0 +1,2 @@ +ztext4dir = $(top_srcdir)/src/modules/texts/ztext4 +libsword_la_SOURCES += $(ztext4dir)/ztext4.cpp diff --git a/src/modules/texts/ztext4/ztext4.cpp b/src/modules/texts/ztext4/ztext4.cpp new file mode 100644 index 0000000..79665c9 --- /dev/null +++ b/src/modules/texts/ztext4/ztext4.cpp @@ -0,0 +1,223 @@ +/****************************************************************************** + * + * ztext4.cpp - code for class 'zText4'- a module that reads compressed + * text files + * + * $Id: ztext4.cpp 3439 2016-10-23 08:32:02Z scribe $ + * + * Copyright 1996-2014 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 <ctype.h> +#include <stdio.h> +#include <fcntl.h> +#include <sysdata.h> +#include <versekey.h> +#include <filemgr.h> + +#include <ztext4.h> + +SWORD_NAMESPACE_START + +/****************************************************************************** + * zText4 Constructor - Initializes data for instance of zText4 + * + * ENT: ipath - path to data files + * iname - Internal name for module + * idesc - Name to display to user for module + * iblockType - verse, chapter, book, etc. of index chunks + * icomp - Compressor object + * idisp - Display object to use for displaying + */ + +zText4::zText4(const char *ipath, const char *iname, const char *idesc, int iblockType, SWCompress *icomp, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char *ilang, const char *versification) + : zVerse4(ipath, FileMgr::RDWR, iblockType, icomp), SWText(iname, idesc, idisp, enc, dir, mark, ilang, versification) { + blockType = iblockType; + lastWriteKey = 0; +} + + +/****************************************************************************** + * zText4 Destructor - Cleans up instance of zText4 + */ + +zText4::~zText4() +{ + flushCache(); + + if (lastWriteKey) + delete lastWriteKey; + +} + + +bool zText4::isWritable() const { return ((idxfp[0]->getFd() > 0) && ((idxfp[0]->mode & FileMgr::RDWR) == FileMgr::RDWR)); } + + +/****************************************************************************** + * zText4::getRawEntry - Returns the current verse buffer + * + * RET: buffer with verse + */ + +SWBuf &zText4::getRawEntryBuf() const { + long start = 0; + unsigned long size = 0; + unsigned long buffnum = 0; + VerseKey &key = getVerseKey(); + + findOffset(key.getTestament(), key.getTestamentIndex(), &start, &size, &buffnum); + entrySize = (int)size; // support getEntrySize call + + entryBuf = ""; + + zReadText(key.getTestament(), start, size, buffnum, entryBuf); + rawFilter(entryBuf, &key); + +// if (!isUnicode()) + prepText(entryBuf); + + return entryBuf; +} + + +bool zText4::sameBlock(VerseKey *k1, VerseKey *k2) { + if (k1->getTestament() != k2->getTestament()) + return false; + + switch (blockType) { + case VERSEBLOCKS: + if (k1->getVerse() != k2->getVerse()) + return false; + case CHAPTERBLOCKS: + if (k1->getChapter() != k2->getChapter()) + return false; + case BOOKBLOCKS: + if (k1->getBook() != k2->getBook()) + return false; + } + return true; +} + + +void zText4::setEntry(const char *inbuf, long len) { + VerseKey &key = getVerseKey(); + + // see if we've jumped across blocks since last write + if (lastWriteKey) { + if (!sameBlock(lastWriteKey, &key)) { + flushCache(); + } + delete lastWriteKey; + } + + doSetText(key.getTestament(), key.getTestamentIndex(), inbuf, len); + + lastWriteKey = (VerseKey *)key.clone(); // must delete +} + + +void zText4::linkEntry(const SWKey *inkey) { + VerseKey &destkey = getVerseKey(); + const VerseKey *srckey = &getVerseKey(inkey); + doLinkEntry(destkey.getTestament(), destkey.getTestamentIndex(), srckey->getTestamentIndex()); +} + + +/****************************************************************************** + * zFiles::deleteEntry - deletes this entry + * + */ + +void zText4::deleteEntry() { + + VerseKey &key = getVerseKey(); + + doSetText(key.getTestament(), key.getTestamentIndex(), ""); +} + + +/****************************************************************************** + * zText4::increment - Increments module key a number of entries + * + * ENT: increment - Number of entries to jump forward + * + */ + +void zText4::increment(int steps) { + long start; + unsigned long size; + unsigned long buffnum; + VerseKey *tmpkey = &getVerseKey(); + + findOffset(tmpkey->getTestament(), tmpkey->getTestamentIndex(), &start, &size, &buffnum); + + SWKey lastgood = *tmpkey; + while (steps) { + long laststart = start; + unsigned long lastsize = size; + SWKey lasttry = *tmpkey; + (steps > 0) ? ++(*key) : --(*key); + tmpkey = &getVerseKey(); + + if ((error = key->popError())) { + *key = lastgood; + break; + } + long index = tmpkey->getTestamentIndex(); + findOffset(tmpkey->getTestament(), index, &start, &size, &buffnum); + + if ( + ( + ((laststart != start) || (lastsize != size)) // we're a different entry +// && (start > 0) + && (size) // and we actually have a size + ) + || !skipConsecutiveLinks + ) { // or we don't want to skip consecutive links + steps += (steps < 0) ? 1 : -1; + lastgood = *tmpkey; + } + } + error = (error) ? KEYERR_OUTOFBOUNDS : 0; +} + + +bool zText4::isLinked(const SWKey *k1, const SWKey *k2) const { + long start1, start2; + unsigned long size1, size2; + unsigned long buffnum1, buffnum2; + VerseKey *vk1 = &getVerseKey(k1); + VerseKey *vk2 = &getVerseKey(k2); + if (vk1->getTestament() != vk2->getTestament()) return false; + + findOffset(vk1->getTestament(), vk1->getTestamentIndex(), &start1, &size1, &buffnum1); + findOffset(vk2->getTestament(), vk2->getTestamentIndex(), &start2, &size2, &buffnum2); + return start1 == start2 && buffnum1 == buffnum2; +} + +bool zText4::hasEntry(const SWKey *k) const { + long start; + unsigned long size; + unsigned long buffnum; + VerseKey *vk = &getVerseKey(k); + + findOffset(vk->getTestament(), vk->getTestamentIndex(), &start, &size, &buffnum); + return size; +} + + +SWORD_NAMESPACE_END diff --git a/src/utilfuns/ftplib.c b/src/utilfuns/ftplib.c index a211973..cbafb01 100644 --- a/src/utilfuns/ftplib.c +++ b/src/utilfuns/ftplib.c @@ -249,7 +249,7 @@ static int readline(char *buf,int max,netbuf *ctl) x = (max >= ctl->cavail) ? ctl->cavail : max-1; end = mymemccpy(bp,ctl->cget,'\n',x); if (end != NULL) { - x = end - bp; + x = (int)(end - bp); } retval += x; bp += x; @@ -288,7 +288,7 @@ static int readline(char *buf,int max,netbuf *ctl) } if (!socket_wait(ctl)) return retval; - if ((x = net_read(ctl->handle,ctl->cput,ctl->cleft)) == -1) + if ((x = (int)net_read(ctl->handle,ctl->cput,ctl->cleft)) == -1) { perror("read"); retval = -1; @@ -326,7 +326,7 @@ static int writeline(char *buf, int len, netbuf *nData) { if (!socket_wait(nData)) return x; - w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ); + w = (int)net_write(nData->handle, nbp, FTPLIB_BUFSIZ); if (w != FTPLIB_BUFSIZ) { if (ftplib_debug > 1) @@ -341,7 +341,7 @@ static int writeline(char *buf, int len, netbuf *nData) { if (!socket_wait(nData)) return x; - w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ); + w = (int)net_write(nData->handle, nbp, FTPLIB_BUFSIZ); if (w != FTPLIB_BUFSIZ) { if (ftplib_debug > 1) @@ -356,7 +356,7 @@ static int writeline(char *buf, int len, netbuf *nData) { if (!socket_wait(nData)) return x; - w = net_write(nData->handle, nbp, nb); + w = (int)net_write(nData->handle, nbp, nb); if (w != nb) { if (ftplib_debug > 1) @@ -951,7 +951,7 @@ GLOBALDEF int FtpAccess(const char *path, int typ, int mode, netbuf *nControl, } if (path != NULL) { - int i = strlen(buf); + int i = (int)strlen(buf); buf[i++] = ' '; if ((strlen(path) + i) >= sizeof(buf)) return 0; @@ -995,7 +995,7 @@ GLOBALDEF int FtpRead(void *buf, int max, netbuf *nData) i = socket_wait(nData); if (i != 1) return 0; - i = net_read(nData->handle, buf, max); + i = (int)net_read(nData->handle, buf, max); } if (i == -1) return 0; @@ -1026,7 +1026,7 @@ GLOBALDEF int FtpWrite(void *buf, int len, netbuf *nData) else { socket_wait(nData); - i = net_write(nData->handle, buf, len); + i = (int)net_write(nData->handle, buf, len); } if (i == -1) return 0; @@ -1243,7 +1243,7 @@ static int FtpXfer(const char *localfile, const char *path, dbuf = malloc(FTPLIB_BUFSIZ); if (typ == FTPLIB_FILE_WRITE) { - while ((l = fread(dbuf, 1, FTPLIB_BUFSIZ, local)) > 0) + while ((l = (int)fread(dbuf, 1, FTPLIB_BUFSIZ, local)) > 0) if ((c = FtpWrite(dbuf, l, nData)) < l) { if (ftplib_debug > 1) @@ -1255,7 +1255,7 @@ static int FtpXfer(const char *localfile, const char *path, else { while ((l = FtpRead(dbuf, FTPLIB_BUFSIZ, nData)) > 0) { - writeResult = (nData->writercb) ? nData->writercb(nData, dbuf, l, nData->writerarg) : fwrite(dbuf, 1, l, local); + writeResult = (int)((nData->writercb) ? nData->writercb(nData, dbuf, l, nData->writerarg) : fwrite(dbuf, 1, l, local)); if (writeResult <= 0) { perror("localstore write"); diff --git a/src/utilfuns/roman.cpp b/src/utilfuns/roman.cpp index d436b19..031d58a 100644 --- a/src/utilfuns/roman.cpp +++ b/src/utilfuns/roman.cpp @@ -2,7 +2,7 @@ * * roman.cpp - * - * $Id: roman.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: roman.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 2002-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -37,7 +37,7 @@ char isroman (const char *str, int maxchars) { } int from_rom(const char* str) { - int i, n = strlen(str); + int i, n = (int)strlen(str); short * num= (short *) calloc(n, sizeof(short)); for (i = 0; str[i]; i++) { switch(str[i]) { diff --git a/src/utilfuns/swbuf.cpp b/src/utilfuns/swbuf.cpp index 9c4908b..e9a8109 100644 --- a/src/utilfuns/swbuf.cpp +++ b/src/utilfuns/swbuf.cpp @@ -2,7 +2,7 @@ * * swbuf.cpp - used as a transport and utility for data buffers * - * $Id: swbuf.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: swbuf.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 2003-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -32,38 +32,6 @@ SWORD_NAMESPACE_START char *SWBuf::nullStr = (char *)""; -/****************************************************************************** -* SWBuf Constructor - Creates an empty SWBuf object or an SWBuf initialized -* to a value from a const char * -* -*/ -SWBuf::SWBuf(const char *initVal, unsigned long initSize) { - init(initSize); - if (initVal) - set(initVal); -} - -/****************************************************************************** -* SWBuf Constructor - Creates an SWBuf initialized -* to a value from another SWBuf -* -*/ -SWBuf::SWBuf(const SWBuf &other, unsigned long initSize) { - init(initSize); - set(other); -} - -/****************************************************************************** -* SWBuf Constructor - Creates an SWBuf initialized -* to a value from a char -* -*/ -SWBuf::SWBuf(char initVal, unsigned long initSize) { - init(initSize+1); - *buf = initVal; - end = buf+1; - *end = 0; -} /* SWBuf::SWBuf(unsigned long initSize) { @@ -96,33 +64,6 @@ SWBuf &SWBuf::setFormatted(const char *format, ...) { return *this; } -/****************************************************************************** -* SWBuf::append - appends a value to the current value of this SWBuf -* -*/ -SWBuf &SWBuf::append(const char *str, long max) { -// if (!str) //A null string was passed -// return; - if (max < 0) - max = strlen(str); - assureMore(max+1); - for (;((max)&&(*str));max--) - *end++ = *str++; - *end = 0; - return *this; -} - -/****************************************************************************** -* SWBuf::setSize - Size this buffer to a specific length -*/ -void SWBuf::setSize(unsigned long len) { - assureSize(len+1); - if ((unsigned)(end - buf) < len) - memset(end, fillByte, len - (end-buf)); - end = buf + len; - *end = 0; -} - /****************************************************************************** * SWBuf::appendFormatted - appends formatted strings to the current value of this SWBuf * WARNING: This function can only write at most @@ -151,7 +92,7 @@ void SWBuf::insert(unsigned long pos, const char* str, unsigned long start, sign // return; str += start; - int len = (max > -1) ? max : strlen(str); + int len = (int)((max > -1) ? max : strlen(str)); if (!len || (pos > length())) //nothing to do, return return; diff --git a/src/utilfuns/url.cpp b/src/utilfuns/url.cpp index a909a04..89cea7f 100644 --- a/src/utilfuns/url.cpp +++ b/src/utilfuns/url.cpp @@ -2,7 +2,7 @@ * * url.cpp - code for an URL parser utility class * - * $Id: url.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: url.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 2004-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -233,8 +233,8 @@ const SWBuf URL::encode(const char *urlText) { url = urlText; SWBuf buf; - const int length = url.length(); - for (int i = 0; i < length; i++) { //fill "buf" + const long length = url.length(); + for (long i = 0; i < length; i++) { //fill "buf" const char& c = url[i]; buf.append( ((m[c].length()) ? m[c] : SWBuf(c)) ); } @@ -249,7 +249,7 @@ const SWBuf URL::decode(const char *encoded) { text = encoded; SWBuf decoded; - const int length = text.length(); + const long length = text.length(); int i = 0; while (i < length) { diff --git a/src/utilfuns/utilstr.cpp b/src/utilfuns/utilstr.cpp index cabd455..0f71c33 100644 --- a/src/utilfuns/utilstr.cpp +++ b/src/utilfuns/utilstr.cpp @@ -2,7 +2,7 @@ * * utilstr.cpp - String utility functions * - * $Id: utilstr.cpp 2982 2013-09-15 13:33:03Z scribe $ + * $Id: utilstr.cpp 3515 2017-11-01 11:38:09Z scribe $ * * Copyright 1997-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -67,28 +67,6 @@ const unsigned char SW_toupper_array[256] = { }; -/****************************************************************************** - * stdstr - clones a string - * - * ENT: ipstr - pointer to a string pointer to set if necessary - * istr - string to set to *ipstr - * 0 - only get - * - * RET: *ipstr - */ - -char *stdstr(char **ipstr, const char *istr, unsigned int memPadFactor) { - if (*ipstr) - delete [] *ipstr; - if (istr) { - int len = strlen(istr) + 1; - *ipstr = new char [ len * memPadFactor ]; - memcpy(*ipstr, istr, len); - } - else *ipstr = 0; - return *ipstr; -} - /****************************************************************************** * strstrip - Removes leading and trailing spaces from a string @@ -102,7 +80,7 @@ char *strstrip(char *istr) { char *tmp = istr; char *rtmp; - int len = strlen(istr); + int len = (int)strlen(istr); if (len < 1) return istr; rtmp = istr + (len - 1); @@ -126,8 +104,8 @@ char *strstrip(char *istr) { */ const char *stristr(const char *s1, const char *s2) { - int tLen = strlen(s2); - int cLen = strlen(s1); + int tLen = (int)strlen(s2); + int cLen = (int)strlen(s1); char *target = new char [ tLen + 1 ]; int i, j; const char *retVal = 0; @@ -161,8 +139,8 @@ const char *stristr(const char *s1, const char *s2) { */ int strnicmp(const char *s1, const char *s2, int len) { - int tLen = strlen(s2); - int cLen = strlen(s1); + int tLen = (int)strlen(s2); + int cLen = (int)strlen(s1); char diff; int i; for (i = 0; ((i < len) && (i < tLen) && (i < cLen)); i++) { @@ -187,163 +165,6 @@ int stricmp(const char *s1, const char *s2) { } -/****************************************************************************** - * getUniCharFromUTF8 - retrieves the next Unicode codepoint from a UTF8 string - * and increments buf to start of next codepoint - * - * ENT: buf - address of a utf8 buffer - * - * RET: buf - incremented past last byte used in computing the current codepoint - * unicode codepoint value (0 with buf incremented is invalid UTF8 byte - */ - -__u32 getUniCharFromUTF8(const unsigned char **buf) { - __u32 ch = 0; - unsigned char multibuf[7]; - - //case: We're at the end - if (!(**buf)) { - return ch; - } - - //case: ANSI - if (!(**buf & 128)) { - ch = **buf; - (*buf)++; - return ch; - } - - //case: Invalid UTF-8 (illegal continuing byte in initial position) - if ((**buf & 128) && (!(**buf & 64))) { - (*buf)++; - return ch; - } - - //case: 2+ byte codepoint - multibuf[0] = **buf; - multibuf[0] <<= 1; - int subsequent; - for (subsequent = 1; (multibuf[0] & 128) && (subsequent < 7); subsequent++) { - multibuf[0] <<= 1; - multibuf[subsequent] = (*buf)[subsequent]; - multibuf[subsequent] &= 63; - // subsequent byte did not begin with 10XXXXXX - // move our buffer to here and error out - if (((*buf)[subsequent] - multibuf[subsequent]) != 128) { - *buf += subsequent; - return 0; - } - ch <<= 6; - ch |= multibuf[subsequent]; - } - subsequent--; - multibuf[0] <<= 1; - char significantFirstBits = 8 - (2+subsequent); - - ch |= (((__s16)multibuf[0]) << (((6*subsequent)+significantFirstBits)-8)); - *buf += (subsequent+1); - return ch; -} - - -SWBuf getUTF8FromUniChar(__u32 uchar) { - SWBuf retVal("", 7); - unsigned int i; - - if (uchar < 0x80) { - retVal.append((unsigned char)uchar); - retVal.setSize(1); - } - else if (uchar < 0x800) { - retVal.setSize(2); - i = uchar & 0x3f; - retVal[1] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x1f; - retVal[0] = (unsigned char)(0xc0 | i); - } - else if (uchar < 0x10000) { - retVal.setSize(3); - i = uchar & 0x3f; - retVal[2] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x3f; - retVal[1] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x0f; - retVal[0] = (unsigned char)(0xe0 | i); - } - else if (uchar < 0x200000) { - retVal.setSize(4); - i = uchar & 0x3f; - retVal[3] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x3f; - retVal[2] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x3f; - retVal[1] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x07; - retVal[0] = (unsigned char)(0xf0 | i); - } - else if (uchar < 0x4000000) { - retVal.setSize(5); - i = uchar & 0x3f; - retVal[4] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x3f; - retVal[3] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x3f; - retVal[2] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x3f; - retVal[1] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x03; - retVal[0] = (unsigned char)(0xf8 | i); - } - else if (uchar < 0x80000000) { - retVal.setSize(6); - i = uchar & 0x3f; - retVal[5] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x3f; - retVal[4] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x3f; - retVal[3] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x3f; - retVal[2] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x3f; - retVal[1] = (unsigned char)(0x80 | i); - uchar >>= 6; - - i = uchar & 0x01; - retVal[0] = (unsigned char)(0xfc | i); - } - - return retVal; -} - - SWBuf assureValidUTF8(const char *buf) { SWBuf myCopy = buf; @@ -404,7 +225,7 @@ SWBuf wcharToUTF8(const wchar_t *buf) { SWBuf utf8Buf; while (*buf) { - utf8Buf.append(getUTF8FromUniChar(*buf++)); + getUTF8FromUniChar(*buf++, &utf8Buf); } return utf8Buf; } diff --git a/src/utilfuns/utilxml.cpp b/src/utilfuns/utilxml.cpp index 1537499..a4eeb2a 100644 --- a/src/utilfuns/utilxml.cpp +++ b/src/utilfuns/utilxml.cpp @@ -3,7 +3,7 @@ * utilxml.cpp - Implementaion of utility classes to handle * XML processing * - * $Id: utilxml.cpp 2980 2013-09-14 21:51:47Z scribe $ + * $Id: utilxml.cpp 3439 2016-10-23 08:32:02Z scribe $ * * Copyright 2003-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society @@ -85,16 +85,14 @@ void XMLTag::parse() const { for (; ((buf[i]) && (buf[i] != quoteChar)); i++); // Allow for empty quotes - //if (i-start) { - if (value) - delete [] value; - value = new char [ (i-start) + 1 ]; - if (i-start) { - strncpy(value, buf+start, i-start); - } - value[i-start] = 0; - attributes[name] = value; - //} + if (value) + delete [] value; + value = new char [ (i-start) + 1 ]; + if (i-start) { + strncpy(value, buf+start, i-start); + } + value[i-start] = 0; + attributes[name] = value; } } } @@ -130,12 +128,12 @@ XMLTag::XMLTag(const XMLTag& t) : attributes(t.attributes) { empty = t.empty; endTag = t.endTag; if (t.buf) { - int len = strlen(t.buf); + int len = (int)strlen(t.buf); buf = new char[len + 1]; memcpy(buf, t.buf, len + 1); } if (t.name) { - int len = strlen(t.name); + int len = (int)strlen(t.name); name = new char[len + 1]; memcpy(name, t.name, len + 1); } diff --git a/src/utilfuns/zlib/gzlib.c b/src/utilfuns/zlib/gzlib.c index fae202e..a089787 100644 --- a/src/utilfuns/zlib/gzlib.c +++ b/src/utilfuns/zlib/gzlib.c @@ -15,6 +15,14 @@ #endif #endif +#if !defined(__GNUC__) && !defined(_WIN32_WCE) +#include <io.h> +#include <direct.h> +#else +#include <unistd.h> +#endif + + /* Local functions */ local void gz_reset OF((gz_statep)); local gzFile gz_open OF((const void *, int, const char *)); diff --git a/src/utilfuns/zlib/gzread.c b/src/utilfuns/zlib/gzread.c index bf4538e..b6c99cd 100644 --- a/src/utilfuns/zlib/gzread.c +++ b/src/utilfuns/zlib/gzread.c @@ -5,6 +5,13 @@ #include "gzguts.h" +#if !defined(__GNUC__) && !defined(_WIN32_WCE) +#include <io.h> +#include <direct.h> +#else +#include <unistd.h> +#endif + /* Local functions */ local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); local int gz_avail OF((gz_statep)); @@ -27,7 +34,7 @@ local int gz_load(state, buf, len, have) *have = 0; do { - ret = read(state->fd, buf + *have, len - *have); + ret = (int)read(state->fd, buf + *have, len - *have); if (ret <= 0) break; *have += ret; diff --git a/src/utilfuns/zlib/gzwrite.c b/src/utilfuns/zlib/gzwrite.c index aa767fb..5b4c677 100644 --- a/src/utilfuns/zlib/gzwrite.c +++ b/src/utilfuns/zlib/gzwrite.c @@ -4,7 +4,12 @@ */ #include "gzguts.h" - +#if !defined(__GNUC__) && !defined(_WIN32_WCE) +#include <io.h> +#include <direct.h> +#else +#include <unistd.h> +#endif /* Local functions */ local int gz_init OF((gz_statep)); local int gz_comp OF((gz_statep, int)); @@ -81,7 +86,7 @@ local int gz_comp(state, flush) /* write directly if requested */ if (state->direct) { - got = write(state->fd, strm->next_in, strm->avail_in); + got = (int)write(state->fd, strm->next_in, strm->avail_in); if (got < 0 || (unsigned)got != strm->avail_in) { gz_error(state, Z_ERRNO, zstrerror()); return -1; @@ -98,7 +103,7 @@ local int gz_comp(state, flush) if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) { have = (unsigned)(strm->next_out - state->x.next); - if (have && ((got = write(state->fd, state->x.next, have)) < 0 || + if (have && ((got = (int)write(state->fd, state->x.next, have)) < 0 || (unsigned)got != have)) { gz_error(state, Z_ERRNO, zstrerror()); return -1; diff --git a/src/utilfuns/zlib/untgz.c b/src/utilfuns/zlib/untgz.c index a7b7164..5c95a90 100644 --- a/src/utilfuns/zlib/untgz.c +++ b/src/utilfuns/zlib/untgz.c @@ -201,7 +201,7 @@ int makedir (char *newdir) { char *buffer = strdup(newdir); char *p; - int len = strlen(buffer); + int len = (int)strlen(buffer); if (len <= 0) { free(buffer); -- cgit v1.2.3