summaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
authorTeus Benschop <teusjannette@gmail.com>2018-10-28 11:51:26 +0100
committerTeus Benschop <teusjannette@gmail.com>2018-10-28 11:51:26 +0100
commit1d0ff54794b5edea7cdf1d2d66710a0fa885bcc5 (patch)
tree8ece5f9ef437fbb151f2b22ed0c6e1a714879c7c /src/modules
parentc7dbdc9161a7c460526b80fe01af49d714856126 (diff)
New upstream version 1.8.1
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/comments/Makefile.am1
-rw-r--r--src/modules/comments/rawcom4/Makefile10
-rw-r--r--src/modules/comments/rawcom4/rawcom4.cpp4
-rw-r--r--src/modules/comments/zcom/zcom.cpp2
-rw-r--r--src/modules/comments/zcom4/Makefile5
-rw-r--r--src/modules/comments/zcom4/Makefile.am2
-rw-r--r--src/modules/comments/zcom4/zcom4.cpp220
-rw-r--r--src/modules/common/Makefile.am18
-rw-r--r--src/modules/common/bz2comprs.cpp57
-rw-r--r--src/modules/common/entriesblk.cpp6
-rw-r--r--src/modules/common/rawstr.cpp32
-rw-r--r--src/modules/common/rawstr4.cpp36
-rw-r--r--src/modules/common/rawverse.cpp4
-rw-r--r--src/modules/common/rawverse4.cpp6
-rw-r--r--src/modules/common/swcomprs.cpp3
-rw-r--r--src/modules/common/xzcomprs.cpp130
-rw-r--r--src/modules/common/zipcomprs.cpp34
-rw-r--r--src/modules/common/zstr.cpp42
-rw-r--r--src/modules/common/zverse.cpp19
-rw-r--r--src/modules/common/zverse4.cpp516
-rw-r--r--src/modules/filters/Makefile.am5
-rw-r--r--src/modules/filters/gbfheadings.cpp8
-rw-r--r--src/modules/filters/gbfhtmlhref.cpp12
-rw-r--r--src/modules/filters/gbflatex.cpp198
-rw-r--r--src/modules/filters/gbfmorph.cpp8
-rw-r--r--src/modules/filters/gbfplain.cpp6
-rw-r--r--src/modules/filters/gbfredletterwords.cpp7
-rw-r--r--src/modules/filters/gbfrtf.cpp6
-rw-r--r--src/modules/filters/gbfstrongs.cpp16
-rw-r--r--src/modules/filters/gbfthml.cpp13
-rw-r--r--src/modules/filters/gbfwordjs.cpp18
-rw-r--r--src/modules/filters/gbfxhtml.cpp12
-rw-r--r--src/modules/filters/greeklexattribs.cpp4
-rw-r--r--src/modules/filters/osisheadings.cpp11
-rw-r--r--src/modules/filters/osishtmlhref.cpp31
-rw-r--r--src/modules/filters/osislatex.cpp766
-rw-r--r--src/modules/filters/osislemma.cpp12
-rw-r--r--src/modules/filters/osismorph.cpp7
-rw-r--r--src/modules/filters/osismorphsegmentation.cpp2
-rw-r--r--src/modules/filters/osisosis.cpp53
-rw-r--r--src/modules/filters/osisplain.cpp56
-rw-r--r--src/modules/filters/osisreferencelinks.cpp2
-rw-r--r--src/modules/filters/osisrtf.cpp21
-rw-r--r--src/modules/filters/osisscripref.cpp2
-rw-r--r--src/modules/filters/osisstrongs.cpp55
-rw-r--r--src/modules/filters/osiswebif.cpp14
-rw-r--r--src/modules/filters/osiswordjs.cpp11
-rw-r--r--src/modules/filters/osisxhtml.cpp238
-rw-r--r--src/modules/filters/rtfhtml.cpp4
-rw-r--r--src/modules/filters/scsuutf8.cpp381
-rw-r--r--src/modules/filters/swbasicfilter.cpp20
-rw-r--r--src/modules/filters/teihtmlhref.cpp56
-rw-r--r--src/modules/filters/teilatex.cpp326
-rw-r--r--src/modules/filters/teirtf.cpp30
-rw-r--r--src/modules/filters/teixhtml.cpp149
-rw-r--r--src/modules/filters/thmlgbf.cpp6
-rw-r--r--src/modules/filters/thmlheadings.cpp2
-rw-r--r--src/modules/filters/thmlhtml.cpp10
-rw-r--r--src/modules/filters/thmlhtmlhref.cpp39
-rw-r--r--src/modules/filters/thmllatex.cpp396
-rw-r--r--src/modules/filters/thmlplain.cpp10
-rw-r--r--src/modules/filters/thmlrtf.cpp37
-rw-r--r--src/modules/filters/thmlscripref.cpp2
-rw-r--r--src/modules/filters/thmlstrongs.cpp16
-rw-r--r--src/modules/filters/thmlwordjs.cpp18
-rw-r--r--src/modules/filters/thmlxhtml.cpp41
-rw-r--r--src/modules/filters/unicodertf.cpp2
-rw-r--r--src/modules/filters/utf16utf8.cpp2
-rw-r--r--src/modules/filters/utf8arabicpoints.cpp4
-rw-r--r--src/modules/filters/utf8greekaccents.cpp521
-rw-r--r--src/modules/filters/utf8html.cpp2
-rw-r--r--src/modules/filters/utf8latin1.cpp2
-rw-r--r--src/modules/filters/utf8nfc.cpp2
-rw-r--r--src/modules/filters/utf8nfkd.cpp2
-rw-r--r--src/modules/filters/utf8scsu.cpp61
-rw-r--r--src/modules/filters/utf8utf16.cpp2
-rw-r--r--src/modules/genbook/rawgenbook/rawgenbook.cpp6
-rw-r--r--src/modules/lexdict/rawld/rawld.cpp31
-rw-r--r--src/modules/lexdict/rawld4/rawld4.cpp35
-rw-r--r--src/modules/lexdict/swld.cpp6
-rw-r--r--src/modules/lexdict/zld/zld.cpp33
-rw-r--r--src/modules/swmodule.cpp218
-rw-r--r--src/modules/texts/Makefile.am1
-rw-r--r--src/modules/texts/rawtext4/Makefile10
-rw-r--r--src/modules/texts/rawtext4/rawtext4.cpp5
-rw-r--r--src/modules/texts/ztext4/Makefile5
-rw-r--r--src/modules/texts/ztext4/Makefile.am2
-rw-r--r--src/modules/texts/ztext4/ztext4.cpp223
88 files changed, 4389 insertions, 1070 deletions
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 <ctype.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#include <swbuf.h>
+#include <zverse4.h>
+#include <versekey.h>
+#include <zcom4.h>
+#include <filemgr.h>
+
+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 <string.h>
#include <stdio.h>
#include <bz2comprs.h>
-#include <zlib.h>
+#include <bzlib.h>
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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <xzcomprs.h>
-#include <zlib.h>
+
+#define LZMA_API_STATIC
+#include <lzma.h>
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 <ctype.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <utilstr.h>
+#include <versekey.h>
+#include <zverse4.h>
+#include <sysdata.h>
+#include <swbuf.h>
+#include <filemgr.h>
+#include <swcomprs.h>
+
+
+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("<a href=\"passagestudy.jsp?action=showNote&type=n&value=%s&module=%s&passage=%s\"><small><sup class=\"n\">*n%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(): ""));
}
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 <stdlib.h>
+#include <gbflatex.h>
+#include <swmodule.h>
+#include <utilxml.h>
+#include <versekey.h>
+#include <ctype.h>
+#include <url.h>
+
+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", ")</small></font>");
+ 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 <!P> is a non showing comment that can be changed in the front end to <P> 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 += " <small><em>&lt;<a href=\"type=Strongs value=";
+ buf += " \\swordstrong[Greek]{";
+ for (tok = token+2; *tok; tok++)
+ //if(token[i] != '\"')
+ buf += *tok;
+ buf += ", ";
+ for (tok = token + 2; *tok; tok++)
+ //if(token[i] != '\"')
+ buf += *tok;
+ buf += "}";
+ }
+ else if (!strncmp(token, "WH", 2)) { // strong's numbers
+ buf += " \\swordstrong[Hebrew]{";
+ for (tok = token+2; *tok; tok++)
+ //if(token[i] != '\"')
+ buf += *tok;
+ buf += ", ";
+ for (tok = token + 2; *tok; tok++)
+ //if(token[i] != '\"')
+ buf += *tok;
+ buf += "}";
+ }
+ else if (!strncmp(token, "WTG", 3)) { // strong's numbers tense
+ buf += " \\swordstrong[Greektense]{";
+ for (tok = token + 3; *tok; tok++)
+ if(*tok != '\"')
+ buf += *tok;
+ buf += ", ";
+ for (tok = token + 3; *tok; tok++)
+ if(*tok != '\"')
+ buf += *tok;
+ buf += "}";
+ }
+ else if (!strncmp(token, "WTH", 3)) { // strong's numbers tense
+ buf += " \\swordstrong[Hebrewtense]{";
+ for (tok = token + 3; *tok; tok++)
+ if(*tok != '\"')
+ buf += *tok;
+ buf += ",";
+ for (tok = token + 3; *tok; tok++)
+ if(*tok != '\"')
+ buf += *tok;
+ buf += "}";
+ }
+
+ else if (!strncmp(token, "WT", 2) && strncmp(token, "WTH", 3) && strncmp(token, "WTG", 3)) { // morph tags
+ buf += " \\swordmorph{";
+
+ for (tok = token + 2; *tok; tok++)
+ if(*tok != '\"')
+ buf += *tok;
+ buf += ", >";
+ for (tok = token + 2; *tok; tok++)
+ if(*tok != '\"')
+ buf += *tok;
+ buf += "}";
+ }
+
+ else if (!strcmp(tag.getName(), "RX")) {
+ buf += "\\swordxref{";
+ for (tok = token + 3; *tok; tok++) {
+ if(*tok != '<' && *tok+1 != 'R' && *tok+2 != 'x') {
+ buf += *tok;
+ }
+ else {
+ break;
+ }
+ }
+ buf += "}";
+ }
+ else if (!strcmp(tag.getName(), "RF")) {
+ SWBuf type = tag.getAttribute("type");
+ SWBuf footnoteNumber = tag.getAttribute("swordFootnote");
+ SWBuf noteName = tag.getAttribute("n");
+ if (u->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("<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 {
+ 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("<a href=\"passagestudy.jsp?action=showNote&type=n&value=%s&module=%s&passage=%s\"><small><sup class=\"n\">*n%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(): ""));
}
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 <title> 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\">&lt;<a href=\"passagestudy.jsp?action=showStrongs&type=%s&value=%s\" class=\"strongs\">%s</a>&gt;</em></small>",
+ buf.appendFormatted("<small><em class=\"strongs\">&lt;<a class=\"strongs\" href=\"passagestudy.jsp?action=showStrongs&type=%s&value=%s\" class=\"strongs\">%s</a>&gt;</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")) { //&gt;
+ if (value.length())
+ buf.appendFormatted("\\swordmorph[Greek]{%s}",
+ value.c_str());
+ }
+ else if (tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "lemma")) { //&gt;
+ 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