aboutsummaryrefslogtreecommitdiffstats
path: root/src/modules/texts
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/texts')
-rw-r--r--src/modules/texts/Makefile5
-rw-r--r--src/modules/texts/Makefile.am7
-rw-r--r--src/modules/texts/rawgbf/Gbf.c485
-rw-r--r--src/modules/texts/rawgbf/Gbf.pas735
-rw-r--r--src/modules/texts/rawgbf/Gbfmain.pas1267
-rw-r--r--src/modules/texts/rawgbf/Makefile5
-rw-r--r--src/modules/texts/rawgbf/Makefile.am4
-rw-r--r--src/modules/texts/rawgbf/gbf.cpp735
-rw-r--r--src/modules/texts/rawgbf/gbf.h67
-rw-r--r--src/modules/texts/rawgbf/gbfidx.cpp294
-rw-r--r--src/modules/texts/rawgbf/rawgbf.cpp84
-rw-r--r--src/modules/texts/rawtext/Makefile5
-rw-r--r--src/modules/texts/rawtext/Makefile.am4
-rw-r--r--src/modules/texts/rawtext/kjvidx.cpp169
-rw-r--r--src/modules/texts/rawtext/makebnds.c86
-rw-r--r--src/modules/texts/rawtext/nuidx.cpp238
-rw-r--r--src/modules/texts/rawtext/ojbtxidx.c166
-rw-r--r--src/modules/texts/rawtext/rawtext.cpp580
-rw-r--r--src/modules/texts/rawtext/rawtxidx.c146
-rw-r--r--src/modules/texts/rawtext/rtfidx.cpp164
-rw-r--r--src/modules/texts/rawtext/svetxidx.c153
-rw-r--r--src/modules/texts/rawtext/vntidx.cpp185
-rw-r--r--src/modules/texts/swtext.cpp40
-rw-r--r--src/modules/texts/ztext/Makefile5
-rw-r--r--src/modules/texts/ztext/Makefile.am4
-rw-r--r--src/modules/texts/ztext/gbfidx.cpp661
-rw-r--r--src/modules/texts/ztext/makeidx.c146
-rw-r--r--src/modules/texts/ztext/nasb.cpp107
-rw-r--r--src/modules/texts/ztext/rawtxt2z.cpp457
-rw-r--r--src/modules/texts/ztext/ztext.cpp309
30 files changed, 7313 insertions, 0 deletions
diff --git a/src/modules/texts/Makefile b/src/modules/texts/Makefile
new file mode 100644
index 0000000..1a2d00d
--- /dev/null
+++ b/src/modules/texts/Makefile
@@ -0,0 +1,5 @@
+
+root := ../../..
+
+all:
+ make -C ${root}
diff --git a/src/modules/texts/Makefile.am b/src/modules/texts/Makefile.am
new file mode 100644
index 0000000..b48d93e
--- /dev/null
+++ b/src/modules/texts/Makefile.am
@@ -0,0 +1,7 @@
+textsdir = $(top_srcdir)/src/modules/texts
+
+libsword_la_SOURCES += $(textsdir)/swtext.cpp
+
+include ../src/modules/texts/rawtext/Makefile.am
+include ../src/modules/texts/ztext/Makefile.am
+include ../src/modules/texts/rawgbf/Makefile.am
diff --git a/src/modules/texts/rawgbf/Gbf.c b/src/modules/texts/rawgbf/Gbf.c
new file mode 100644
index 0000000..2b7f786
--- /dev/null
+++ b/src/modules/texts/rawgbf/Gbf.c
@@ -0,0 +1,485 @@
+/* Output from p2c, the Pascal-to-C translator */
+/* From input file "Gbf.pas" */
+
+
+#include <p2c/p2c.h>
+
+
+typedef enum {
+ tokNull, tokEOF, tokHeader, tokContent, tokTail, tokStyle, tokWord,
+ tokSpace, tokSync, tokControl, tokChar, tokFont
+} TToken;
+typedef enum {
+ caBold, caSmallCaps, caItalic, caOTQuote, caRed, caSuperscript, caUnderline,
+ caSubscript
+} TCharacterAttribute;
+typedef long TCharAttribs;
+
+
+
+typedef struct TBookNameRec {
+ Char Name[256], Abbr[256];
+ uchar Num;
+} TBookNameRec;
+
+typedef TBookNameRec TBookAbbr[116];
+
+
+typedef struct TReadGBF {
+ /* private*/
+ FILE *F;
+ Char FName[256], TokenLine[256];
+ long TokenPos;
+ boolean fFileIsOpen, fParagraphEnd, fInTitle, fInPsalmBookTitle,
+ fInHebrewTitle, fInSectionTitle;
+
+ /* public*/
+ Char sBook[256], sChapter[256], sVerse[256], sMode[256];
+ Char sContext[256]; /*// Last text type (header, body, or tail)*/
+ Char sTitle[256]; /*// Title of this book of the Bible*/
+ Char sPsalmBookTitle[256]; /*// Title of this Psalm book*/
+ Char sHebrewTitle[256]; /*// Psalm Hebrew title*/
+ Char sSectionTitle[256]; /*// Section headings*/
+ Char sDate[256], sFontName[256];
+ long iTotalWords;
+ Char chJustification, chDirection;
+ boolean fIndent, fPoetry;
+ TCharAttribs CharAttribs;
+ uchar bBk, bChap, bVs, bWd;
+ /*
+ function Init({const*/
+ /*sFileName: string): boolean;
+ procedure Done;
+ function GetToken(var TokenKind: TToken): string;
+ */
+} TReadGBF;
+
+typedef struct TWriteGBF {
+ /* private*/
+ FILE *F;
+ Char FName[256], LineOut[256];
+ boolean fFileIsOpen;
+ uchar bBk, bChap, bVs, bWd;
+
+ /* public*/
+ /*
+ function Init({const*/
+ /*sFileName: string): boolean;
+ function Done: boolean;
+ procedure Out({const*/
+ /*s: string);
+*/
+} TWriteGBF;
+
+/*implementation */
+
+
+/*//0*/
+/*//1*/
+/*//2*/
+/*//3*/
+/*//4*/
+/*//5*/
+/*//6*/
+/*//7*/
+/*//8*/
+/*//9*/
+/*//10*/
+/*//11*/
+/*//12*/
+/*//13*/
+/*//14*/
+/*//15*/
+/*//16*/
+/*//17*/
+/*//18*/
+/*//19*/
+/*//20*/
+/*//21*/
+/*//22*/
+/*//0*/
+/*//1*/
+/*//2*/
+/*//3*/
+/*//4*/
+/*//5*/
+/*//6*/
+/*//7*/
+/*//8*/
+/*//9*/
+/*//10*/
+/*//11*/
+/*//12*/
+/*//13*/
+/*//14*/
+/*//15*/
+/*//16*/
+/*//17*/
+/*//18*/
+/*//19*/
+/*//20*/
+/*//21*/
+/*//22*/
+/*//23*/
+/*//24*/
+/*//26*/
+/*//27*/
+/*//28*/
+/*//29*/
+/*//30*/
+/*//31*/
+/*//32*/
+/*//33*/
+/*//34*/
+/*//35*/
+/*//36*/
+/*//37*/
+/*//38*/
+/*//39*/
+/*//40*/
+/*//41*/
+/*//42*/
+/*//43*/
+/*//44*/
+/*//45*/
+/*//46*/
+/*//47*/
+/*//48*/
+/*//49*/
+/*//50*/
+/*//51*/
+/*//52*/
+/*//53*/
+/*//54*/
+/*//55*/
+/*//56*/
+/*//57*/
+/*//58*/
+/*//59*/
+/*//60*/
+/*//61*/
+/*//62*/
+/*//63*/
+/*//64*/
+/*//65*/
+/*//66*/
+/*//67*/
+/*//68*/
+/*//69*/
+/*//70*/
+/*//71*/
+/*//72*/
+/*//73*/
+/*//74*/
+/*//75*/
+/*//76*/
+/*//77*/
+/*//78*/
+/*//79*/
+/*//80*/
+/*//81*/
+/*//82*/
+/*//83*/
+/*//84*/
+/*//85*/
+/*//86*/
+/*//87*/
+/*//88*/
+/*//89*/
+/*//90*/
+/*//91*/
+/*//92*/
+
+Static TBookAbbr BookAbbr = {
+ { "1 Chronicles", "1CH", 13 },
+ { "1 Corinthians", "1CO", 70 },
+ { "1 Esdras", "1E", 52 },
+ { "1 John", "1J", 86 },
+ { "1 Kings", "1K", 11 },
+ { "1 Maccabees", "1M", 50 },
+ { "1 Peter", "1P", 84 },
+ { "1 Samuel", "1S", 9 },
+ { "1 Thessalonians", "1TH", 76 },
+ { "1 Timothy", "1TI", 78 },
+ { "2 Chronicles", "2CH", 14 },
+ { "2 Corinthians", "2CO", 71 },
+ { "2 Esdras", "2E", 56 },
+ { "2 John", "2J", 87 },
+ { "2 Kings", "2K", 12 },
+ { "2 Maccabees", "2M", 51 },
+ { "2 Peter", "2P", 85 },
+ { "2 Samuel", "2S", 10 },
+ { "2 Thessalonians", "2TH", 77 },
+ { "2 Timothy", "2TI", 79 },
+ { "3 John", "3J", 88 },
+ { "3 Maccabees", "3M", 55 },
+ { "4 Maccabees", "4M", 57 },
+ { "1 Chronicles", "1 CH", 13 },
+ { "1 Corinthians", "1 CO", 70 },
+ { "1 Esdras", "1 E", 52 },
+ { "1 John", "1 J", 86 },
+ { "1 Kings", "1 K", 11 },
+ { "1 Maccabees", "1 M", 50 },
+ { "1 Peter", "1 P", 84 },
+ { "1 Samuel", "1 S", 9 },
+ { "1 Thessalonians", "1 TH", 76 },
+ { "1 Timothy", "1 TI", 78 },
+ { "2 Chronicles", "2 CH", 14 },
+ { "2 Corinthians", "2 CO", 71 },
+ { "2 Esdras", "2 E", 56 },
+ { "2 John", "2 J", 87 },
+ { "2 Kings", "2 K", 12 },
+ { "2 Maccabees", "2 M", 51 },
+ { "2 Peter", "2 P", 85 },
+ { "2 Samuel", "2 S", 10 },
+ { "2 Thessalonians", "2 TH", 77 },
+ { "2 Timothy", "2 TI", 79 },
+ { "3 John", "3 J", 88 },
+ { "3 Maccabees", "3 M", 55 },
+ { "4 Maccabees", "4 M", 57 },
+ { "Acts", "AC", 68 },
+ { "Amos", "AM", 30 },
+ { "Prayer of Asariah and the Song of the Three Jews", "AZ", 47 },
+ { "Baruch", "BA", 45 },
+ { "Bel and the Dragon", "BE", 49 },
+ { "Colossians", "CO", 75 },
+ { "Daniel", "DA", 27 },
+ { "Deuteronomy", "DE", 5 },
+ { "Deuteronomy", "DT", 5 },
+ { "Ecclesiasties", "EC", 21 },
+ { "Esther", "ES", 17 },
+ { "Exodus", "EX", 2 },
+ { "Ezekiel", "EZE", 26 },
+ { "Ezra", "EZR", 15 },
+ { "Galatians", "GA", 72 },
+ { "Genesis", "GE", 1 },
+ { "Genesis", "GN", 1 },
+ { "Ephesians", "EP", 73 },
+ { "Esther (Greek)", "GR", 42 },
+ { "Habakkuk", "HAB", 35 },
+ { "Haggai", "HAG", 37 },
+ { "Hebrews", "HE", 82 },
+ { "Hosea", "HO", 28 },
+ { "Isaiah", "IS", 23 },
+ { "James", "JA", 83 },
+ { "Jeremiah", "JE", 24 },
+ { "Job", "JOB", 18 },
+ { "Joel", "JOE", 29 },
+ { "John", "JOH", 67 },
+ { "Jonah", "JON", 32 },
+ { "Joshua", "JOS", 6 },
+ { "Jude", "JUDE", 89 },
+ { "Judges", "JUDG", 7 },
+ { "Judith", "JUDI", 41 },
+ { "Lamentations", "LA", 25 },
+ { "Letter of Jeremiah", "LET", 46 },
+ { "Leviticus", "LEV", 3 },
+ { "Luke", "LK", 66 },
+ { "Leviticus", "LV", 3 },
+ { "Luke", "LU", 66 },
+ { "Malachi", "MAL", 39 },
+ { "Prayer of Manasseh", "MAN", 53 },
+ { "Mark", "MAR", 65 },
+ { "Matthew", "MAT", 64 },
+ { "Micah", "MI", 33 },
+ { "Nahum", "NA", 34 },
+ { "Nehemiah", "NE", 16 },
+ { "Numbers", "NU", 4 },
+ { "Obadiah", "OB", 31 },
+ { "Psalm 151", "P1", 54 },
+ { "Philemon", "PHILE", 81 },
+ { "Philippians", "PHILI", 74 },
+ { "Philemon", "PHM", 81 },
+ { "Philippians", "PHP", 74 },
+ { "Proverbs", "PR", 20 },
+ { "Psalms", "PS", 19 },
+ { "Revelation", "RE", 90 },
+ { "Romans", "RM", 69 },
+ { "Romans", "RO", 69 },
+ { "Ruth", "RU", 8 },
+ { "Sirach", "SI", 44 },
+ { "Song of Solomon", "SOL", 22 },
+ { "Song of Solomon", "SON", 22 },
+ { "Song of Solomon", "SS", 22 },
+ { "Susanna", "SU", 48 },
+ { "Titus", "TI", 80 },
+ { "Tobit", "TO", 40 },
+ { "Wisdom", "WI", 43 },
+ { "Zechariah", "ZEC", 38 },
+ { "Zephaniah", "ZEP", 36 }
+};
+
+/*// 0 - 7*/
+/*// 8 - 14*/
+/*// 15-20*/
+/*// 21-26*/
+/*// 27-33*/
+/*// 34-39*/
+/*// 40-45*/
+/*// 46-52*/
+/*// 53-63*/
+/*// 64-70*/
+/*// 71-78*/
+/*// 79-84*/
+
+Static Char BookFileName[91][256] = {
+ "", "Genesis", "Exodus", "Lev", "Num", "Deut", "Joshua", "Judges", "Ruth",
+ "1Sam", "2Sam", "1Kings", "2Kings", "1Chron", "2Chron", "Ezra", "Nehemiah",
+ "Esther", "Job", "Psalms", "Proverbs", "Eccl", "Song", "Isaiah", "Jeremiah",
+ "Lament", "Ezekiel", "Daniel", "Hosea", "Joel", "Amos", "Obadiah", "Jonah",
+ "Micah", "Nahum", "Habakkuk", "Zeph", "Haggai", "Zech", "Malachi", "Tobit",
+ "Judith", "Esther", "Wisdom", "Sirach", "Baruch", "Let", "Azar", "Susanna",
+ "Bel", "1Mac", "2Mac", "1Esdras", "Man", "P1", "3Mac", "2Esdras", "4Mac",
+ "", "", "", "", "", "", "Matthew", "Mark", "Luke", "John", "Acts", "Romans",
+ "1Cor", "2Cor", "Gal", "Eph", "Philip", "Col", "1Thes", "2Thes", "1Tim",
+ "2Tim", "Titus", "Philemon", "Hebrews", "James", "1Peter", "2Peter",
+ "1John", "2John", "3John", "Jude", "Rev"
+/* p2c: Gbf.pas, line 200:
+ * Note: Line breaker spent 0.0 seconds, 5000 tries on line 336 [251] */
+}; /*// 85-90*/
+
+
+Static boolean isletter(ch)
+Char ch;
+{
+ /*const*/
+ boolean Result;
+
+ if (isupper(ch)) {
+ Result = true;
+ return Result;
+ }
+ if (islower(ch))
+ Result = true;
+ else
+ Result = false;
+ return Result;
+}
+
+
+Static boolean isinword(ch)
+Char ch;
+{
+ /*const*/
+ boolean Result;
+
+ switch (ch) {
+
+ case '-':
+ Result = true;
+ break;
+
+ default:
+ if (isupper(ch))
+ Result = true;
+ else if (islower(ch))
+ Result = true;
+ else
+ Result = false;
+ break;
+ }
+ return Result;
+}
+
+
+Static boolean IsUpper(ch)
+Char ch;
+{
+ /*const*/
+ boolean Result;
+
+ if (isupper(ch))
+ Result = true;
+ else
+ Result = false;
+ return Result;
+}
+
+
+Static boolean IsDigit(ch)
+Char ch;
+{
+ /*const*/
+ boolean Result;
+
+ if (isdigit(ch))
+ Result = true;
+ else
+ Result = false;
+ return Result;
+}
+
+
+Static boolean MatchAbbrev(sName, sAbbrev)
+Char *sName, *sAbbrev;
+{
+ /*const*/
+ long i;
+ boolean Result;
+
+ if (strlen(sName) < strlen(sAbbrev)) {
+ Result = false;
+/* p2c: Gbf.pas, line 245: Warning: Symbol 'RESULT' is not defined [221] */
+ } else
+ Result = true;
+ i = 1;
+ while (i <= strlen(sAbbrev) && Result) {
+ if (toupper(sName[i - 1]) != sAbbrev[i - 1])
+ Result = false;
+ i++;
+ }
+}
+
+
+Static uchar BookNameToNumber(sBookName)
+Char *sBookName;
+{
+ /*const*/
+ long Result;
+
+ Result = 0;
+/* p2c: Gbf.pas, line 259: Warning: Symbol 'RESULT' is not defined [221] */
+ TRY(try1);
+ if (IsDigit(sBookName[strlen(sBookName) - 1]) & IsDigit(sBookName[0])) {
+ Result = StrToInt(sBookName);
+/* p2c: Gbf.pas, line 262:
+ * Warning: Symbol 'STRTOINT' is not defined [221] */
+ }
+ except();
+/* p2c: Gbf.pas, line 264: Warning: Symbol 'EXCEPT' is not defined [221] */
+/* p2c: Gbf.pas, line 264:
+ * Warning: Expected RECOVER, found 'Result' [227] */
+ RECOVER(try1);
+ ;
+ ENDTRY(try1);
+}
+
+
+main(argc, argv)
+int argc;
+Char *argv[];
+{ /*// Yuk! Linear search.*/
+ Char STR1[256];
+ uchar Result;
+
+/* p2c: Gbf.pas, line 266: Warning: Expected BEGIN, found 'i' [227] */
+ PASCAL_MAIN(argc, argv);
+ if (MatchAbbrev(sBookName, BookAbbr[i].Abbr)) {
+/* p2c: Gbf.pas, line 269:
+ * Warning: Symbol 'SBOOKNAME' is not defined [221] */
+/* p2c: Gbf.pas, line 269: Warning: Mixing non-strings with strings [170] */
+/* p2c: Gbf.pas, line 269: Warning: Symbol 'I' is not defined [221] */
+ Result = BookAbbr[i].Num;
+/* p2c: Gbf.pas, line 271: Warning: Symbol 'I' is not defined [221] */
+/* p2c: Gbf.pas, line 271: Warning: Symbol 'RESULT' is not defined [221] */
+ }
+/* p2c: Gbf.pas, line 273: Warning: Symbol 'I' is not defined [221] */
+ i++;
+ exit(EXIT_SUCCESS);
+}
+/* p2c: Gbf.pas, line 275:
+ * Warning: Junk at end of input file ignored [277] */
+
+
+
+/* End. */
diff --git a/src/modules/texts/rawgbf/Gbf.pas b/src/modules/texts/rawgbf/Gbf.pas
new file mode 100644
index 0000000..13826e3
--- /dev/null
+++ b/src/modules/texts/rawgbf/Gbf.pas
@@ -0,0 +1,735 @@
+type
+ TToken = (tokNull, tokEOF, tokHeader, tokContent, tokTail, tokStyle,
+ tokWord, tokSpace, tokSync, tokControl, tokChar, tokFont);
+ TCharacterAttribute = (caBold, caSmallCaps, caItalic, caOTQuote, caRed,
+ caSuperscript, caUnderline, caSubscript);
+ TCharAttribs = set of TCharacterAttribute;
+
+
+ TBookNameRec = record
+ Name,
+ Abbr: string;
+ Num: byte
+ end;
+
+ TBookAbbr = array[0..115] of TBookNameRec;
+
+const
+ BookAbbr: TBookAbbr = (
+ (Name: '1 Chronicles'; Abbr: '1CH'; Num: 13), {//0}
+ (Name: '1 Corinthians'; Abbr: '1CO'; Num: 70), {//1}
+ (Name: '1 Esdras'; Abbr: '1E'; Num: 52), {//2}
+ (Name: '1 John'; Abbr: '1J'; Num: 86), {//3}
+ (Name: '1 Kings'; Abbr: '1K'; Num: 11), {//4}
+ (Name: '1 Maccabees'; Abbr: '1M'; Num: 50), {//5}
+ (Name: '1 Peter'; Abbr: '1P'; Num: 84), {//6}
+ (Name: '1 Samuel'; Abbr: '1S'; Num: 9), {//7}
+ (Name: '1 Thessalonians'; Abbr: '1TH'; Num: 76), {//8}
+ (Name: '1 Timothy'; Abbr: '1TI'; Num: 78), {//9}
+ (Name: '2 Chronicles'; Abbr: '2CH'; Num: 14), {//10}
+ (Name: '2 Corinthians'; Abbr: '2CO'; Num: 71), {//11}
+ (Name: '2 Esdras'; Abbr: '2E'; Num: 56), {//12}
+ (Name: '2 John'; Abbr: '2J'; Num: 87), {//13}
+ (Name: '2 Kings'; Abbr: '2K'; Num: 12), {//14}
+ (Name: '2 Maccabees'; Abbr: '2M'; Num: 51), {//15}
+ (Name: '2 Peter'; Abbr: '2P'; Num: 85), {//16}
+ (Name: '2 Samuel'; Abbr: '2S'; Num: 10), {//17}
+ (Name: '2 Thessalonians'; Abbr: '2TH'; Num: 77), {//18}
+ (Name: '2 Timothy'; Abbr: '2TI'; Num: 79), {//19}
+ (Name: '3 John'; Abbr: '3J'; Num: 88), {//20}
+ (Name: '3 Maccabees'; Abbr: '3M'; Num: 55), {//21}
+ (Name: '4 Maccabees'; Abbr: '4M'; Num: 57), {//22}
+ (Name: '1 Chronicles'; Abbr: '1 CH'; Num: 13), {//0}
+ (Name: '1 Corinthians'; Abbr: '1 CO'; Num: 70), {//1}
+ (Name: '1 Esdras'; Abbr: '1 E'; Num: 52), {//2}
+ (Name: '1 John'; Abbr: '1 J'; Num: 86), {//3}
+ (Name: '1 Kings'; Abbr: '1 K'; Num: 11), {//4}
+ (Name: '1 Maccabees'; Abbr: '1 M'; Num: 50), {//5}
+ (Name: '1 Peter'; Abbr: '1 P'; Num: 84), {//6}
+ (Name: '1 Samuel'; Abbr: '1 S'; Num: 9), {//7}
+ (Name: '1 Thessalonians'; Abbr: '1 TH'; Num: 76), {//8}
+ (Name: '1 Timothy'; Abbr: '1 TI'; Num: 78), {//9}
+ (Name: '2 Chronicles'; Abbr: '2 CH'; Num: 14), {//10}
+ (Name: '2 Corinthians'; Abbr: '2 CO'; Num: 71), {//11}
+ (Name: '2 Esdras'; Abbr: '2 E'; Num: 56), {//12}
+ (Name: '2 John'; Abbr: '2 J'; Num: 87), {//13}
+ (Name: '2 Kings'; Abbr: '2 K'; Num: 12), {//14}
+ (Name: '2 Maccabees'; Abbr: '2 M'; Num: 51), {//15}
+ (Name: '2 Peter'; Abbr: '2 P'; Num: 85), {//16}
+ (Name: '2 Samuel'; Abbr: '2 S'; Num: 10), {//17}
+ (Name: '2 Thessalonians'; Abbr: '2 TH'; Num: 77), {//18}
+ (Name: '2 Timothy'; Abbr: '2 TI'; Num: 79), {//19}
+ (Name: '3 John'; Abbr: '3 J'; Num: 88), {//20}
+ (Name: '3 Maccabees'; Abbr: '3 M'; Num: 55), {//21}
+ (Name: '4 Maccabees'; Abbr: '4 M'; Num: 57), {//22}
+ (Name: 'Acts'; Abbr: 'AC'; Num: 68), {//23}
+ (Name: 'Amos'; Abbr: 'AM'; Num: 30), {//24}
+ (Name: 'Prayer of Asariah and the Song of the Three Jews'; Abbr: 'AZ'; Num: 47),
+ (Name: 'Baruch'; Abbr: 'BA'; Num: 45), {//26}
+ (Name: 'Bel and the Dragon';Abbr: 'BE'; Num: 49), {//27}
+ (Name: 'Colossians'; Abbr: 'CO'; Num: 75), {//28}
+ (Name: 'Daniel'; Abbr: 'DA'; Num: 27), {//29}
+ (Name: 'Deuteronomy'; Abbr: 'DE'; Num: 5), {//30}
+ (Name: 'Deuteronomy'; Abbr: 'DT'; Num: 5), {//31}
+ (Name: 'Ecclesiasties'; Abbr: 'EC'; Num: 21), {//32}
+ (Name: 'Esther'; Abbr: 'ES'; Num: 17), {//33}
+ (Name: 'Exodus'; Abbr: 'EX'; Num: 2), {//34}
+ (Name: 'Ezekiel'; Abbr: 'EZE'; Num: 26), {//35}
+ (Name: 'Ezra'; Abbr: 'EZR'; Num: 15), {//36}
+ (Name: 'Galatians'; Abbr: 'GA'; Num: 72), {//37}
+ (Name: 'Genesis'; Abbr: 'GE'; Num: 1), {//38}
+ (Name: 'Genesis'; Abbr: 'GN'; Num: 1), {//39}
+ (Name: 'Ephesians'; Abbr: 'EP'; Num: 73), {//40}
+ (Name: 'Esther (Greek)'; Abbr: 'GR'; Num: 42), {//41}
+ (Name: 'Habakkuk'; Abbr: 'HAB'; Num: 35), {//42}
+ (Name: 'Haggai'; Abbr: 'HAG'; Num: 37), {//43}
+ (Name: 'Hebrews'; Abbr: 'HE'; Num: 82), {//44}
+ (Name: 'Hosea'; Abbr: 'HO'; Num: 28), {//45}
+ (Name: 'Isaiah'; Abbr: 'IS'; Num: 23), {//46}
+ (Name: 'James'; Abbr: 'JA'; Num: 83), {//47}
+ (Name: 'Jeremiah'; Abbr: 'JE'; Num: 24), {//48}
+ (Name: 'Job'; Abbr: 'JOB'; Num: 18), {//49}
+ (Name: 'Joel'; Abbr: 'JOE'; Num: 29), {//50}
+ (Name: 'John'; Abbr: 'JOH'; Num: 67), {//51}
+ (Name: 'Jonah'; Abbr: 'JON'; Num: 32), {//52}
+ (Name: 'Joshua'; Abbr: 'JOS'; Num: 6), {//53}
+ (Name: 'Jude'; Abbr: 'JUDE'; Num: 89), {//54}
+ (Name: 'Judges'; Abbr: 'JUDG'; Num: 7), {//55}
+ (Name: 'Judith'; Abbr: 'JUDI'; Num: 41), {//56}
+ (Name: 'Lamentations'; Abbr: 'LA'; Num: 25), {//57}
+ (Name: 'Letter of Jeremiah';Abbr:'LET'; Num: 46), {//58}
+ (Name: 'Leviticus'; Abbr: 'LEV'; Num: 3), {//59}
+ (Name: 'Luke'; Abbr: 'LK'; Num: 66), {//60}
+ (Name: 'Leviticus'; Abbr: 'LV'; Num: 3), {//61}
+ (Name: 'Luke'; Abbr: 'LU'; Num: 66), {//62}
+ (Name: 'Malachi'; Abbr: 'MAL'; Num: 39), {//63}
+ (Name: 'Prayer of Manasseh';Abbr:'MAN'; Num: 53), {//64}
+ (Name: 'Mark'; Abbr: 'MAR'; Num: 65), {//65}
+ (Name: 'Matthew'; Abbr: 'MAT'; Num: 64), {//66}
+ (Name: 'Micah'; Abbr: 'MI'; Num: 33), {//67}
+ (Name: 'Nahum'; Abbr: 'NA'; Num: 34), {//68}
+ (Name: 'Nehemiah'; Abbr: 'NE'; Num: 16), {//69}
+ (Name: 'Numbers'; Abbr: 'NU'; Num: 4), {//70}
+ (Name: 'Obadiah'; Abbr: 'OB'; Num: 31), {//71}
+ (Name: 'Psalm 151'; Abbr: 'P1'; Num: 54), {//72}
+ (Name: 'Philemon'; Abbr: 'PHILE'; Num: 81), {//73}
+ (Name: 'Philippians'; Abbr: 'PHILI'; Num: 74), {//74}
+ (Name: 'Philemon'; Abbr: 'PHM'; Num: 81), {//75}
+ (Name: 'Philippians'; Abbr: 'PHP'; Num: 74), {//76}
+ (Name: 'Proverbs'; Abbr: 'PR'; Num: 20), {//77}
+ (Name: 'Psalms'; Abbr: 'PS'; Num: 19), {//78}
+ (Name: 'Revelation'; Abbr: 'RE'; Num: 90), {//79}
+ (Name: 'Romans'; Abbr: 'RM'; Num: 69), {//80}
+ (Name: 'Romans'; Abbr: 'RO'; Num: 69), {//81}
+ (Name: 'Ruth'; Abbr: 'RU'; Num: 8), {//82}
+ (Name: 'Sirach'; Abbr: 'SI'; Num: 44), {//83}
+ (Name: 'Song of Solomon'; Abbr: 'SOL'; Num: 22), {//84}
+ (Name: 'Song of Solomon'; Abbr: 'SON'; Num: 22), {//85}
+ (Name: 'Song of Solomon'; Abbr: 'SS'; Num: 22), {//86}
+ (Name: 'Susanna'; Abbr: 'SU'; Num: 48), {//87}
+ (Name: 'Titus'; Abbr: 'TI'; Num: 80), {//88}
+ (Name: 'Tobit'; Abbr: 'TO'; Num: 40), {//89}
+ (Name: 'Wisdom'; Abbr: 'WI'; Num: 43), {//90}
+ (Name: 'Zechariah'; Abbr: 'ZEC'; Num: 38), {//91}
+ (Name: 'Zephaniah'; Abbr: 'ZEP'; Num: 36) {//92}
+ );
+
+ BookFileName: array[0..90] of string = (
+ '','Genesis','Exodus','Lev','Num','Deut','Joshua','Judges', {// 0 - 7}
+ 'Ruth','1Sam','2Sam','1Kings','2Kings','1Chron','2Chron', {// 8 - 14}
+ 'Ezra','Nehemiah','Esther','Job','Psalms','Proverbs', {// 15-20}
+ 'Eccl','Song','Isaiah','Jeremiah','Lament','Ezekiel', {// 21-26}
+ 'Daniel','Hosea','Joel','Amos','Obadiah','Jonah','Micah', {// 27-33}
+ 'Nahum','Habakkuk','Zeph','Haggai','Zech','Malachi', {// 34-39}
+ 'Tobit','Judith','Esther','Wisdom','Sirach','Baruch', {// 40-45}
+ 'Let','Azar','Susanna','Bel','1Mac','2Mac','1Esdras', {// 46-52}
+ 'Man','P1','3Mac','2Esdras','4Mac','','','','','','', {// 53-63}
+ 'Matthew','Mark','Luke','John','Acts','Romans','1Cor', {// 64-70}
+ '2Cor','Gal','Eph','Philip','Col','1Thes','2Thes','1Tim', {// 71-78}
+ '2Tim','Titus','Philemon','Hebrews','James','1Peter', {// 79-84}
+ '2Peter','1John','2John','3John','Jude','Rev'); {// 85-90}
+
+type
+ TReadGBF = record
+{ private}
+ F: File;
+ FName, TokenLine: string;
+ TokenPos: integer;
+ fFileIsOpen, fParagraphEnd, fInTitle, fInPsalmBookTitle, fInHebrewTitle,
+ fInSectionTitle: boolean;
+
+{ public}
+ sBook, sChapter, sVerse, sMode: string;
+ sContext, {// Last text type (header, body, or tail)}
+ sTitle, {// Title of this book of the Bible}
+ sPsalmBookTitle, {// Title of this Psalm book}
+ sHebrewTitle, {// Psalm Hebrew title}
+ sSectionTitle, {// Section headings}
+ sDate,
+ sFontName: string;
+ iTotalWords: integer;
+ chJustification,
+ chDirection: char;
+ fIndent, fPoetry: boolean;
+ CharAttribs: TCharAttribs;
+ bBk, bChap, bVs, bWd: byte;
+{
+ function Init({const}{sFileName: string): boolean;
+ procedure Done;
+ function GetToken(var TokenKind: TToken): string;
+}
+ end;
+
+ TWriteGBF = record
+{ private}
+ F: File;
+ FName, LineOut: string;
+ fFileIsOpen: boolean;
+ bBk, bChap, bVs, bWd: byte;
+
+{ public}
+{
+ function Init({const}{sFileName: string): boolean;
+ function Done: boolean;
+ procedure Out({const}{s: string);
+}
+ end;
+
+{implementation }
+
+function isletter({const}ch: char): boolean;
+begin
+ case ch of
+ 'A'..'Z': isletter := true;
+ 'a'..'z': isletter := true;
+ else
+ isletter := false;
+ end;
+end;
+
+function isinword({const}ch: char): boolean;
+begin
+ case ch of
+ '-': isinword := true;
+ 'A'..'Z': isinword := true;
+ 'a'..'z': isinword := true;
+ else
+ isinword := false;
+ end;
+end;
+
+function IsUpper({const}ch: char): Boolean;
+begin
+ case ch of
+ 'A'..'Z': IsUpper := true;
+ else
+ IsUpper := false;
+ end;
+end;
+
+function IsDigit({const}ch: char): Boolean;
+begin
+ case ch of
+ '0'..'9': IsDigit := true;
+ else
+ IsDigit := false;
+ end;
+end;
+
+
+function MatchAbbrev({const}sName, sAbbrev: string): boolean;
+var i: integer;
+begin
+ if Length(sName) < Length(sAbbrev) then
+ Result := false
+ else
+ Result := true;
+ i := 1;
+ while (i <= Length(sAbbrev)) and Result do
+ begin
+ if UpCase(sName[i]) <> sAbbrev[i] then
+ Result := false;
+ inc(i);
+ end;
+end;
+
+function BookNameToNumber({const}sBookName: string): byte;
+var i: integer;
+begin
+ Result := 0;
+ try
+ if IsDigit(sBookName[Length(sBookName)]) and IsDigit(sBookName[1]) then
+ Result := StrToInt(sBookName);
+ except
+ Result := 0;
+ end;
+ i := 0;
+ while (Result = 0) and (i <= 115) do {// Yuk! Linear search.}
+ begin
+ if MatchAbbrev(sBookName,BookAbbr[i].Abbr) then
+ begin
+ Result := BookAbbr[i].Num;
+ end;
+ inc(i);
+ end;
+end;
+
+function BookNumberToName({const}bBookNum: byte): string;
+begin
+ if bBookNum <= 115 then
+ Result := BookAbbr[bBookNum].Name
+ else
+ Result := '';
+end;
+
+function ConformCase({const}sPat, sSrc: string): string;
+var i: integer;
+begin
+ Result := sSrc;
+ if (Length(sPat) > 0) and (Length(sSrc) > 0) then
+ begin
+ Result := LowerCase(sSrc);
+ if IsUpper(sPat[1]) then
+ Result[1] := UpCase(Result[1]);
+ if (Length(sPat) > 1) and (Length(sSrc) > 1) then
+ begin
+ if IsUpper(sPat[2]) then
+ begin
+ for i := 2 to Length(Result) do
+ Result[i] := UpCase(Result[i]);
+ end;
+ end;
+ end;
+end;
+
+function TReadGBF.Init({const}sFileName: string): boolean;
+var s: string;
+ tok: TToken;
+begin
+ try
+ fParagraphEnd := false;
+ bBk := 0;
+ bChap := 0;
+ bVs := 0;
+ bWd := 0;
+ iTotalWords := 0;
+ FName := sFileName;
+ Assign(F, FName);
+ reset(F);
+ readln(F, TokenLine);
+ TokenPos := 1;
+ fFileIsOpen := true;
+ repeat
+ s := GetToken(tok)
+ until (tok = tokEOF) or ((tok = tokHeader) and (s[3] = '0'));
+ Init := true;
+ except
+ Init := false;
+ fFileIsOpen := false;
+ end
+end;
+
+procedure TReadGBF.Done;
+begin
+ if fFileIsOpen then
+ begin
+ closefile(F);
+ fFileIsOpen := false;
+ end;
+end;
+
+function TReadGBF.GetToken(var TokenKind: TToken): string;
+var m: integer;
+begin
+ Result := '';
+ TokenKind := tokNull;
+ if TokenPos = 0 then
+ begin
+ if (not fFileIsOpen) or EOF(F) then
+ TokenKind := tokEOF
+ else
+ begin
+ ReadLn(F,TokenLine);
+ TokenPos := 1;
+ end;
+ end;
+ if TokenKind <> tokEOF then
+ begin
+ m := Length(TokenLine);
+ if TokenPos > m then
+ begin
+ TokenKind := tokSpace;
+ if fParagraphEnd then
+ fParagraphEnd := false
+ else
+ Result := ' ';
+ TokenPos := 0;
+ end
+ else
+ begin
+ if (TokenLine[TokenPos] = '<') then
+ begin
+ fParagraphEnd := false;
+ repeat
+ Result := Result + TokenLine[TokenPos];
+ inc(TokenPos);
+ until (TokenLine[TokenPos] = '>') or (TokenPos > m);
+ Result := Result + '>';
+ inc(TokenPos);
+ case result[2] of
+ 'B': begin {// File body text type}
+ TokenKind := tokContent;
+ sContext := Result;
+ end;
+ 'C': begin {// Special characters}
+ TokenKind := tokControl;
+ if (Result[3] = 'M') or (Result[3] = 'L') then
+ fParagraphEnd := true;
+ end;
+ 'D': begin {// Direction}
+ TokenKind := tokControl;
+ chDirection := Result[3];
+ end;
+ 'H': begin
+ TokenKind := tokHeader;
+ sContext := Result;
+ end;
+ 'F': begin {// Font attributes}
+ TokenKind := tokFont;
+ case Result[3] of
+ 'B': CharAttribs := CharAttribs + [caBold];
+ 'C': CharAttribs := CharAttribs + [caSmallCaps];
+ 'I': CharAttribs := CharAttribs + [caItalic];
+ 'N': sFontName := copy(Result,4,Length(Result)-4);
+ 'O': CharAttribs := CharAttribs + [caOTQuote];
+ 'R': CharAttribs := CharAttribs + [caRed];
+ 'S': CharAttribs := CharAttribs + [caSuperscript];
+ 'U': CharAttribs := CharAttribs + [caUnderline];
+ 'V': CharAttribs := CharAttribs + [caSubscript];
+ 'b': CharAttribs := CharAttribs - [caBold];
+ 'c': CharAttribs := CharAttribs - [caSmallCaps];
+ 'i': CharAttribs := CharAttribs - [caItalic];
+ 'n': sFontName := '';
+ 'o': CharAttribs := CharAttribs - [caOTQuote];
+ 'r': CharAttribs := CharAttribs - [caRed];
+ 's': CharAttribs := CharAttribs - [caSuperscript];
+ 'u': CharAttribs := CharAttribs - [caUnderline];
+ 'v': CharAttribs := CharAttribs - [caSubscript];
+
+ end;
+ end;
+ 'J': begin {// Justification}
+ TokenKind := tokStyle;
+ chJustification := Result[3];
+ end;
+ 'P': begin {// Poetry/prose, indent}
+ TokenKind := tokControl;
+ case Result[3] of
+ 'I': fIndent := true;
+ 'P': fPoetry := true;
+ 'i': fIndent := false;
+ 'p': fPoetry := false;
+ end;
+ end;
+ 'R': begin {// References and footnotes}
+ TokenKind := tokControl;
+ end;
+ 'S': begin {// sync mark}
+ TokenKind := TokSync;
+ case Result[3] of
+ 'B': begin {// Book}
+ sBook := system.copy(Result, 4, length(Result)-4);
+ sPsalmBookTitle := '';
+ if sBook = '' then
+ begin
+ inc(bBk);
+ sBook := BookNumberToName(bBk);
+ end
+ else
+ bBk := BookNameToNumber(sBook);
+ sTitle := sBook;
+ end;
+ 'C': begin {//chapter}
+ sChapter := system.copy(Result, 4, length(Result)-4);
+ if sChapter = '' then
+ begin
+ inc(bChap);
+ sChapter := IntToStr(bChap);
+ end
+ else
+ begin
+ try
+ bChap := StrToInt(sChapter);
+ except
+ showmessage('Non-numeric chapter: '+sBook+' '+sChapter);
+ end;
+ end;
+ sHebrewTitle := '';
+ end;
+ 'V': begin {// Verse}
+ bWd := 0;
+ sVerse := system.copy(Result, 4, length(Result)-4);
+ if sVerse = '' then
+ begin
+ inc(bVs);
+ sVerse := IntToStr(bVs);
+ end
+ else
+ begin
+ try
+ bVs := StrToInt(sVerse);
+ except
+ showmessage('Non-numeric verse: '+sBook+' '+sChapter+':'+sVerse);
+ end;
+ end;
+ end;
+ 'D': begin {// Date}
+ sDate := system.copy(Result, 3, length(Result)-4);
+ end;
+ end;
+ end;
+ 'T': begin {// Titles}
+ TokenKind := TokContent;
+ case Result[3] of
+ 'B':
+ begin
+ sPsalmBookTitle := '';
+ fInPsalmBookTitle := true;
+ end;
+ 'b': fInPsalmBookTitle := true;
+ 'H':
+ begin
+ sHebrewTitle := '';
+ fInHebrewTitle := true;
+ end;
+ 'h': fInHebrewTitle := false;
+ 'S':
+ begin
+ sSectionTitle := '';
+ fInSectionTitle := true;
+ end;
+ 's': fInSectionTitle := false;
+ 'T':
+ begin
+ sTitle := '';
+ fInTitle := true;
+ end;
+ 't': fInTitle := false;
+ end;
+ end;
+ 'Z': begin {// File tail}
+ TokenKind := tokTail;
+ sContext := Result;
+ if Result[3] = 'Z' then
+ done;
+ end;
+ else
+ TokenKind := TokControl;
+
+ end;
+ end
+ else if isletter(TokenLine[TokenPos]) then
+ begin {Word}
+ fParagraphEnd := false;
+ TokenKind := tokWord;
+ repeat
+ Result := Result + TokenLine[TokenPos];
+ inc(TokenPos);
+ until (TokenPos > m) or (not isinword(TokenLine[TokenPos]));
+ inc(bWd);
+ inc(iTotalWords);
+ end
+ else if ((TokenLine[TokenPos] = ' ') or (TokenLine[TokenPos] = #9)) then
+ begin
+ fParagraphEnd := false;
+ TokenKind := tokSpace;
+ Result := Result + TokenLine[TokenPos];
+ inc(TokenPos);
+ end
+ else
+ begin
+ fParagraphEnd := false;
+ TokenKind := tokChar;
+ Result := Result + TokenLine[TokenPos];
+ inc(TokenPos);
+ end
+ end;
+ end;
+ if ((TokenKind = tokWord) or (TokenKind = tokSpace) or
+ (TokenKind = tokChar)) then
+ begin
+ if fInTitle then
+ sTitle := sTitle + Result
+ else if fInPsalmBookTitle then
+ sPsalmBookTitle := sPsalmBookTitle + Result
+ else if fInHebrewTitle then
+ sHebrewTitle := sHebrewTitle + Result
+ else if fInSectionTitle then
+ sSectionTitle := sSectionTitle + Result;
+ end;
+end;
+
+function TWriteGBF.Init({const}sFileName: string): boolean;
+begin
+ try
+ bBk := 0;
+ bChap := 0;
+ bVs := 0;
+ bWd := 0;
+ LineOut := '';
+ FName := sFileName;
+ Assign(F, FName);
+ filemode := 1;
+ rewrite(F);
+ fFileIsOpen := true;
+ Init := true;
+ except
+ Init := false;
+ fFileIsOpen := false;
+ end
+end;
+
+function TWriteGBF.Done: boolean;
+begin
+ try
+ if fFileIsOpen then
+ begin
+ if LineOut <> '' then
+ begin
+ WriteLn(F, LineOut);
+ LineOut := '';
+ end;
+ CloseFile(F);
+ end;
+ Done := true;
+ except
+ Done := false;
+ end;
+end;
+
+procedure TWriteGBF.Out({const}s: string);
+var sPrint, sSave, sBook, sChapter, sVerse: string;
+ i: integer;
+ b: byte;
+begin
+ if (Length(s) > 0) and IsLetter(s[1]) then
+ begin
+ inc(bWd);
+ LineOut := LineOut + s;
+ end
+ else if Length(s) > 3 then
+ begin
+ if (s[1] = '<') and (s[2] = 'S') then
+ begin
+ case s[3] of
+ 'B': begin {// Book}
+ sBook := system.copy(s, 4, length(s)-4);
+ if sBook = '' then
+ begin
+ inc(bBk);
+ LineOut := LineOut + s;
+ end
+ else
+ begin
+ b := bBk;
+ bBk := BookNameToNumber(sBook);
+ if b <> bBk then
+ LineOut := LineOut + s;
+ end;
+ end;
+ 'C': begin {//chapter}
+ sChapter := system.copy(s, 4, length(s)-4);
+ if sChapter = '' then
+ begin
+ inc(bChap);
+ LineOut := LineOut + s;
+ end
+ else
+ begin
+ try
+{// b := bChap;}
+ bChap := StrToInt(sChapter);
+{// if b <> bChap then}
+ LineOut := LineOut + s;
+ except
+ showmessage('Non-numeric chapter: '+sBook+' '+sChapter);
+ end;
+ end;
+ end;
+ 'V': begin {// Verse}
+ bWd := 0;
+ sVerse := system.copy(s, 4, length(s)-4);
+ if sVerse = '' then
+ begin
+ inc(bVs);
+ LineOut := LineOut + s;
+ end
+ else
+ begin
+ try
+{// b := bVs;}
+ bVs := StrToInt(sVerse);
+{// if b <> bVs then}
+ LineOut := LineOut + s;
+ except
+ showmessage('Non-numeric verse: '+sBook+' '+sChapter+':'+sVerse);
+ end;
+ end;
+ end;
+ else
+ LineOut := LineOut + s;
+ end
+ end
+ else
+ LineOut := LineOut + s; {// Not a sync mark}
+ end
+ else {// other token, space, or punctuation}
+ LineOut := LineOut + s; {// Length <= 3}
+ if ((s = '<CM>') or (s = '<CL>')) then
+ begin
+ if (Length(LineOut) > 78) then
+ begin
+ i := 78;
+ while (i > 0) and (LineOut[i] <> ' ') do
+ dec(i);
+ if i < 1 then
+ begin
+ WriteLn(F,LineOut);
+ LineOut := '';
+ end
+ else
+ begin
+ sPrint := system.copy(LineOut,1,i-1);
+ sSave := system.copy(LineOut,i+1,Length(LineOut)-i);
+ WriteLn(F,sPrint);
+ WriteLn(F, sSave);
+ LineOut := '';
+ end
+ end
+ else
+ begin
+ WriteLn(F, LineOut);
+ LineOut := '';
+ end
+ end
+ else if (Length(LineOut) > 78) then
+ begin
+ i := 78;
+ while (i > 0) and (LineOut[i] <> ' ') do
+ dec(i);
+ if i < 1 then
+ begin
+ WriteLn(F,LineOut);
+ LineOut := '';
+ end
+ else
+ begin
+ sPrint := system.copy(LineOut,1,i-1);
+ sSave := system.copy(LineOut,i+1,Length(LineOut)-i);
+ WriteLn(F,sPrint);
+ LineOut := sSave;
+ end
+ end
+end;
+
+end.
diff --git a/src/modules/texts/rawgbf/Gbfmain.pas b/src/modules/texts/rawgbf/Gbfmain.pas
new file mode 100644
index 0000000..4377622
--- /dev/null
+++ b/src/modules/texts/rawgbf/Gbfmain.pas
@@ -0,0 +1,1267 @@
+unit GBFMain;
+
+interface
+
+uses
+ Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+ Buttons, StdCtrls, ExtCtrls, GBF;
+
+const
+ sTitlePar = '\pard\plain \s1\fi432\sb240\sa60\keepn\widctlpar \b\f5\fs28\kerning28 ';
+ sNormalPar = '\pard\plain \fi432\widctlpar \f4 ';
+ sNormalQuotePar = '\pard\plain \s20\fi432\li432\widctlpar \f4 ';
+ sPoetryPar = '\pard\plain \s18\fi-432\li432\widctlpar \f4 ';
+ sPoetryQuotePar = '\pard\plain \s21\fi-432\li864\widctlpar \f4 ';
+ sHebrewTitlePar = '\pard\plain \s16\fi432\keep\keepn\widctlpar \f4\fs20 ';
+ sSelahPar = '\pard\plain \s19\qr\widctlpar \f4 ';
+ ANSI2OEM: array[0..255] of char =
+ ( #0, #1, #2, #3, #4, #5, #6, #7,
+ #8, #9, #10, #11, #12, #13, #14, #15,
+ #16, #17, #18, #19, #20, #21, #22, #23,
+ #24, #25, #26, #27, #28, #29, #30, #31,
+ #32, #33, #34, #35, #36, #37, #38, #39,
+ #40, #41, #42, #43, #44, #45, #46, #47,
+ #48, #49, #50, #51, #52, #53, #54, #55,
+ #56, #57, #58, #59, #60, #61, #62, #63,
+ #64, #65, #66, #67, #68, #69, #70, #71,
+ #72, #73, #74, #75, #76, #77, #78, #79,
+ #80, #81, #82, #83, #84, #85, #86, #87,
+ #88, #89, #90, #91, #92, #93, #94, #95,
+ #96, #97, #98, #99,#100,#101,#102,#103,
+ #104,#105,#106,#107,#108,#109,#110,#111,
+ #112,#113,#114,#115,#116,#117,#118,#119,
+ #120,#121,#122,#123,#124,#125,#126,#127,
+ #128,#129, ',', 'a', '"',#133,#197,#216,
+ '^', '%', 'S', '<',#140,#141,#142,#143,
+ #144, #96, #97, '"', '"',#249,#150,#151,
+ '~',#153, 's', '>',#156,#157,#158, 'Y',
+ ' ',#173,#155,#156,#232,#157,#124, #21,
+ #168,#169, 'a',#174,#170, '-',#174, '_',
+ #167,#241,#253, '3', #39,#230, #20,#254,
+ ',', '1', 'o',#175,#172,#171,#190,#168,
+ 'A', 'A', 'A', 'A',#142,#143,#198,#128,
+ 'E',#144, 'E',#142, 'I', 'I', 'I', 'I',
+ 'D',#165, 'O', 'O', 'O', 'O',#153, 'x',
+ '0', 'U', 'U', 'U',#154, 'Y', 'b',#225,
+ #133,#130,#131, 'a',#132,#134,#230,#135,
+ #138,#130,#136,#137,#141,#161,#140,#139,
+ #148,#164,#149,#162,#147, 'o',#148,#246,
+ 'o',#151,#163,#150,#129, 'y', 'b',#152);
+
+type
+ TGBFConverterMainForm = class(TForm)
+ SourceEdit: TEdit;
+ Label1: TLabel;
+ BrowseButton: TButton;
+ SaveDialog1: TSaveDialog;
+ OpenDialog1: TOpenDialog;
+ DestEdit: TEdit;
+ Label2: TLabel;
+ BrowseDestButton: TButton;
+ FormatRadioGroup: TRadioGroup;
+ GoBitBtn: TBitBtn;
+ CloseBitBtn: TBitBtn;
+ Timer1: TTimer;
+ VerseLabel: TLabel;
+ ApocryphaCheckBox: TCheckBox;
+ WdLabel: TLabel;
+ Label3: TLabel;
+ Label4: TLabel;
+ WEBDraftCheckBox: TCheckBox;
+ QuickButton: TButton;
+ procedure CloseBitBtnClick(Sender: TObject);
+ procedure GoBitBtnClick(Sender: TObject);
+ procedure Timer1Timer(Sender: TObject);
+ procedure FormShow(Sender: TObject);
+ procedure FormatRadioGroupClick(Sender: TObject);
+ procedure QuickConversion;
+ procedure DoConversion;
+ procedure QuickButtonClick(Sender: TObject);
+ procedure FormActivate(Sender: TObject);
+ private
+ { Private declarations }
+ public
+ { Public declarations }
+ end;
+
+var
+ GBFConverterMainForm: TGBFConverterMainForm;
+
+implementation
+
+{$R *.DFM}
+
+var InFile: TReadGBF;
+ OutGBF: TWriteGBF;
+ OutFile: TextFile;
+
+function ANSIToOEM(s: string): string;
+var i, j: integer;
+begin
+ Result := s;
+ j := 1;
+ for i := 1 to length(s) do
+ begin
+ case s[i] of
+ #133:
+ begin
+ Result[j] := '.';
+ inc(j);
+ Insert('..', Result, j);
+ inc(j);
+ end;
+ #140:
+ begin
+ Result[j] := 'O';
+ inc(j);
+ Insert('E', Result, j);
+ end;
+ #150:
+ begin
+ Result[j] := '-';
+ inc(j);
+ Insert('-', Result, j);
+ end;
+ #151:
+ begin
+ Result[j] := '-';
+ inc(j);
+ Insert('-', Result, j);
+ end;
+ #153:
+ begin
+ Result[j] := '(';
+ inc(j);
+ Insert('TM)', Result, j);
+ inc(j,2);
+ end;
+ #156:
+ begin
+ Result[j] := 'o';
+ inc(j);
+ Insert('e', Result, j);
+ end;
+ #169:
+ begin
+ Result[j] := '(';
+ inc(j);
+ Insert('C)',Result, j);
+ inc(j);
+ end;
+ #174:
+ begin
+ Result[j] := '(';
+ inc(j);
+ Insert('R)',Result, j);
+ inc(j);
+ end;
+ #198:
+ begin
+ Result[j] := 'A';
+ inc(j);
+ Insert('E', Result, j);
+ end;
+ #230:
+ begin
+ Result[j] := 'a';
+ inc(j);
+ Insert('e', Result, j);
+ end;
+ else
+ Result[j] := ANSI2OEM[ord(s[i])];
+ end;
+ inc(j);
+ end;
+end;
+
+procedure TGBFConverterMainForm.CloseBitBtnClick(Sender: TObject);
+begin
+ Close;
+end;
+
+procedure TGBFConverterMainForm.DoConversion;
+var LastBook, wd, ParagraphAttributes, s, sLine, sPrint, sSave,
+ OutFileName: string;
+ LinePos, i, iFileNumber: integer;
+ tok: TToken;
+ fInclude, fProse, fSkip, fHTMLisOpen, fRed, fASCIIisOpen: boolean;
+ bLastBook, bChap: byte;
+
+ procedure CheckEOL;
+ begin
+ if Length(sLine) > 65 then
+ begin
+ i := 65;
+ while (i > 0) and (sLine[i] <> ' ') do
+ dec(i);
+ if i < 1 then
+ begin
+ if fASCIIisOpen then WriteLn(OutFile,sLine);
+ if fProse then
+ sLine := ''
+ else
+ sLine := ' ';
+ end
+ else
+ begin
+ sPrint := system.copy(sLine,1,i-1);
+ if fProse then
+ sSave := system.copy(sLine,i+1,Length(sLine)-i)
+ else
+ sSave := ' '+system.copy(sLine,i+1,Length(sLine)-i);
+ if fASCIIisOpen then WriteLn(OutFile,sPrint);
+ sLine := sSave;
+ end
+ end;
+ end;
+
+ procedure StartNewLine;
+ begin
+ if fInclude then
+ begin
+ CheckEol;
+ if fASCIIisOpen then WriteLn(OutFile, sLine);
+ sLine := '';
+ end;
+ end;
+
+ procedure CloseHTML;
+ begin
+ if fHTMLisOpen then
+ begin
+ WriteLn(OutFile,sLine);
+ sLine := '';
+ WriteLn(OutFile,'</P>');
+ WriteLn(OutFile,'<P></P><HR><A HREF="index.htm">[Index]</A> &nbsp;');
+ WriteLn(OutFile,'<A HREF="http://www.ebible.net/bible/">[Home]</A>');
+ WriteLn(OutFile,'</BODY></HTML>');
+ CloseFile(OutFile);
+ fHTMLisOpen := false;
+ end;
+ end;
+
+ procedure CloseASCII;
+ begin
+ if fASCIIisOpen then
+ begin
+ WriteLn(OutFile,sLine);
+ sLine := '';
+ WriteLn(OutFile);
+ if WEBDraftCheckBox.Checked then
+ begin
+ WriteLn(OutFile,'______________________________________________________________');
+ WriteLn(OutFile);
+ WriteLn(OutFile,'The above is from the public domain World English Bible (WEB).');
+ WriteLn(OutFile,'See http://www.ebible.org/bible/WEB for more about this Bible.');
+ WriteLn(OutFile,'Please report typos to mpj@ebible.org.');
+ end;
+ CloseFile(OutFile);
+ fASCIIisOpen := false;
+ end;
+ end;
+
+ procedure OpenHTML;
+ begin
+ if fHTMLisOpen then CloseHTML;
+ sLine := '';
+ OutFileName := ExtractFilePath(DestEdit.Text)+BookFileName[InFile.bBk]+'.htm';
+ AssignFile(OutFile,OutFileName);
+ Rewrite(OutFile);
+ WriteLn(OutFile,'<HTML>');
+ WriteLn(OutFile,'<HEAD>');
+ WriteLn(OutFile,'<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">');
+ WriteLn(OutFile,'<META http-equiv="PICS-Label" content=''(PICS-1.1 "http://www.rsac.org/ratingsv01.html"');
+ WriteLn(OutFile,' l gen true comment "RSACi North America Server" by "mpj@csn.net" for "http://www.csn.net/~mpj"');
+ WriteLn(OutFile,' on "1996.08.29T12:42-0500" r (n 0 s 0 v 0 l 0))''>');
+ WriteLn(OutFile,'<META NAME="description" CONTENT="'+InFile.sTitle+' from the World English Bible -- a Public Domain Modern English translation of the Holy Bible.">');
+ WriteLn(OutFile,'<META NAME="keywords" CONTENT="'+BookFileName[InFile.bBk]+', '+InFile.sTitle+', Bible, Christian, Holy Bible, Bible search, WEB, World English Bible, Scriptures, Scripture, Bibles, Gospel, Gospels, bible">');
+ WriteLn(OutFile,'<TITLE>'+InFile.sTitle+'</TITLE>');
+ WriteLn(OutFile,'<LINK REL=Home HREF="http://www.ebible.org/bible">');
+ WriteLn(OutFile,'<LINK REL=Glossary HREF="glossary.htm">');
+ WriteLn(OutFile,'</HEAD>');
+ WriteLn(OutFile,'<BODY BGCOLOR="#80ffff">');
+ WriteLn(OutFile,'<H1>');
+ WriteLn(OutFile,InFile.sTitle);
+ WriteLn(OutFile,'</H1><P>');
+ fHTMLisOpen := true;
+ end;
+
+ procedure OpenASCII;
+ begin
+ if fASCIIisOpen then CloseASCII;
+ if fProse then
+ sLine := ' '
+ else
+ sLine := '';
+ OutFileName := ExtractFilePath(DestEdit.Text)+BookFileName[InFile.bBk]+'.txt';
+ AssignFile(OutFile,OutFileName);
+ Rewrite(OutFile);
+ WriteLn(OutFile);
+ WriteLn(OutFile,InFile.sTitle);
+ WriteLn(OutFile);
+ fASCIIisOpen := true;
+ end;
+
+ procedure OpenNTChapter;
+ var s: string;
+ begin
+ if InFile.bBk >= 64 then
+ begin
+ if fASCIIisOpen then CloseASCII;
+ inc(iFileNumber);
+ s := IntToStr(iFileNumber);
+ if Length(s) < 3 then s := '0'+s;
+ if Length(s) < 3 then s := '0'+s;
+ OutFileName := ExtractFilePath(DestEdit.Text)+'n'+s+'.txt';
+ AssignFile(OutFile,OutFileName);
+ Rewrite(OutFile);
+ WriteLn(OutFile,'Subject: '+BookFileName[InFile.bBk]+' '+InFile.sChapter+', World English Bible');
+ if iFileNumber = 260 then
+ WriteLn(OutFile,'X-Reset: 1');
+ WriteLn(OutFile);
+ WriteLn(OutFile);
+ WriteLn(OutFile,InFile.sTitle+', Chapter '+InFile.sChapter);
+ WriteLn(OutFile);
+ fASCIIisOpen := true;
+ if fProse then
+ sLine := ' '
+ else
+ sLine := '';
+ end
+ else
+ begin
+ inc(bChap);
+ if (bLastBook <> Infile.bBk) or ((bChap mod 3) = 1) then
+ begin
+ if (bLastBook <> Infile.bBk) then
+ begin
+ bLastBook := Infile.bBk;
+ bChap := 1;
+ end;
+ if fASCIIisOpen then CloseASCII;
+ inc(iFileNumber);
+ s := IntToStr(iFileNumber);
+ if Length(s) < 3 then s := '0'+s;
+ if Length(s) < 3 then s := '0'+s;
+ OutFileName := ExtractFilePath(DestEdit.Text)+s+'.txt';
+ AssignFile(OutFile,OutFileName);
+ Rewrite(OutFile);
+ WriteLn(OutFile,'Subject: '+BookFileName[InFile.bBk]+' '+InFile.sChapter+', World English Bible');
+ if (Infile.bBk = 39) and (bChap = 4) then
+ WriteLn(OutFile,'X-Reset: 1');
+ WriteLn(OutFile);
+ WriteLn(OutFile);
+ WriteLn(OutFile,InFile.sTitle+', starting at chapter '+InFile.sChapter);
+ WriteLn(OutFile);
+ fASCIIisOpen := true;
+ if fProse then
+ sLine := ' '
+ else
+ sLine := '';
+ end;
+ end;
+ end;
+
+ procedure CheckHTMLEOL;
+ begin
+ if Length(sLine) > 75 then
+ begin
+ i := 75;
+ while (i > 0) and (sLine[i] <> ' ') do
+ dec(i);
+ if i < 1 then
+ begin
+ if fHTMLisOpen then WriteLn(OutFile,sLine);
+ sLine := ''
+ end
+ else
+ begin
+ sPrint := system.copy(sLine,1,i-1);
+ sSave := system.copy(sLine,i+1,Length(sLine)-i);
+ if fHTMLisOpen then WriteLn(OutFile,sPrint);
+ sLine := sSave;
+ end
+ end;
+ end;
+
+ procedure StartNewHTMLLine;
+ begin
+ if fInclude then
+ begin
+ CheckHTMLEOL;
+ if fHTMLisOpen then WriteLn(OutFile, sLine+'</P>');
+ sLine := '<P>';
+ end;
+ end;
+
+
+begin
+ QuickButton.Enabled := false;
+ GoBitBtn.Enabled := false;
+ fInclude := false;
+ fSkip := false;
+ fProse := true;
+ fRed := false;
+ LastBook := '';
+ ParagraphAttributes := sNormalPar;
+ try
+ InFile := TReadGBF.Create;
+ if InFile.Init(Trim(SourceEdit.Text)) then
+ begin
+ LinePos := 0;
+ case FormatRadioGroup.ItemIndex of
+ -1: showmessage('No destination format selected!');
+ 0: begin
+ Label3.Caption := 'Converting to ASCII';
+ AssignFile(OutFile, DestEdit.Text);
+ FileMode := 1;
+ Rewrite(OutFile);
+ fASCIIisOpen := true;
+ sLine := '';
+ repeat
+ wd := ANSIToOEM(InFile.GetToken(tok));
+ Application.ProcessMessages;
+ case tok of
+ tokWord:
+ begin
+ if fInclude and (not fSkip) then
+ begin
+ sLine := sLine + wd;
+ CheckEOL;
+ end;
+ end;
+ tokSpace:
+ begin
+ if fInclude and (not fSkip) then
+ begin
+ sLine := sLine + wd;
+ CheckEOL;
+ end;
+ end;
+ tokSync:
+ begin
+ if fInclude and (length(wd) > 3) then
+ begin
+ if wd[3] = 'V' then
+ begin
+ sLine := sLine + '{' + InFile.sChapter+':'+
+ InFile.sVerse+'} ';
+ CheckEOL
+ end
+ else if (wd[3] = 'C') and (InFile.bBk = 19) then
+ begin
+ StartNewLine;
+ WriteLn(OutFile, 'Psalm '+InFile.sChapter);
+ WriteLn(OutFile);
+ end;
+ if wd[3] = 'B' then
+ fProse := true;
+ end;
+ end;
+ tokContent:
+ begin
+ if wd = '<BO>' then
+ fInclude := true
+ else if wd = '<BN>' then
+ fInclude := true
+ else if wd = '<BO>' then
+ fInclude := ApocryphaCheckBox.Checked
+ end;
+ tokControl:
+ begin
+ if wd = '<CM>' then
+ begin
+ StartNewLine;
+ if fProse then
+ begin
+ WriteLn(OutFile);
+ sLine := ' '
+ end
+ end
+ else if wd = '<CL>' then
+ begin
+ StartNewLine;
+ sLine := ' ';
+ end
+ else if wd = '<Pp>' then
+ fProse := true
+ else if wd = '<PP>' then
+ fProse := false
+ else if wd = '<RF>' then
+ fSkip := true
+ else if wd = '<Rf>' then
+ fSkip := false
+ else if wd = '<RN>' then
+ fSkip := true
+ else if wd = '<Rn>' then
+ fSkip := false
+ else if wd = '<ZZ>' then
+ fInclude := false
+ end;
+ tokChar:
+ begin
+ if fInclude and (not fSkip) then
+ begin
+ sLine := sLine + wd;
+ CheckEOL;
+ end;
+ end;
+ tokFont:
+ begin
+ if wd = '<FI>' then
+ begin
+ if fInclude then
+ sLine := sLine + '[';
+ end
+ else if wd = '<Fi>' then
+ begin
+ if fInclude then
+ sLine := sLine + ']';
+ end
+ end;
+ end
+ until tok = tokEOF;
+ writeln(OutFile, sLine);
+ CloseFile(OutFile);
+ fASCIIisOpen := false;
+ Label3.Caption := '';
+ end;
+ 1: begin
+ Label3.Caption := 'Converting to ASCII (one file/book)';
+ FileMode := 1;
+ fASCIIisOpen := false;
+ sLine := '';
+ repeat
+ Application.ProcessMessages;
+ wd := ANSIToOEM(InFile.GetToken(tok));
+ case tok of
+ tokEOF:
+ CloseASCII;
+ tokWord:
+ begin
+ if fInclude and (not fSkip) then
+ begin
+ sLine := sLine + wd;
+ CheckEOL;
+ end;
+ end;
+ tokSpace:
+ begin
+ if fInclude and (not fSkip) then
+ begin
+ sLine := sLine + wd;
+ CheckEOL;
+ end;
+ end;
+ tokSync:
+ begin
+ if fInclude and (length(wd) > 3) then
+ begin
+ if wd[3] = 'V' then
+ begin
+ sLine := sLine + '{' + InFile.sChapter+':'+
+ InFile.sVerse+'} ';
+ CheckEOL
+ end
+ else if (wd[3] = 'C') and (InFile.bBk = 19) then
+ begin
+ StartNewLine;
+ WriteLn(OutFile, 'Psalm '+InFile.sChapter);
+ WriteLn(OutFile);
+ end;
+ if wd[3] = 'B' then
+ begin
+ fProse := true;
+ CloseASCII;
+ end;
+ end;
+ end;
+ tokContent:
+ begin
+ if wd = '<BO>' then
+ fInclude := true
+ else if wd = '<BN>' then
+ fInclude := true
+ else if wd = '<BO>' then
+ fInclude := ApocryphaCheckBox.Checked
+ else if wd = '<Tt>' then
+ OpenASCII;
+ end;
+ tokControl:
+ begin
+ if wd = '<CM>' then
+ begin
+ StartNewLine;
+ if fProse then
+ begin
+ if fASCIIisOpen then WriteLn(OutFile);
+ sLine := ' '
+ end
+ end
+ else if wd = '<CL>' then
+ begin
+ StartNewLine;
+ sLine := ' ';
+ end
+ else if wd = '<Pp>' then
+ fProse := true
+ else if wd = '<PP>' then
+ fProse := false
+ else if wd = '<RF>' then
+ fSkip := true
+ else if wd = '<Rf>' then
+ fSkip := false
+ else if wd = '<RN>' then
+ fSkip := true
+ else if wd = '<Rn>' then
+ fSkip := false
+ else if wd = '<ZZ>' then
+ fInclude := false
+ end;
+ tokChar:
+ begin
+ if fInclude and (not fSkip) then
+ begin
+ sLine := sLine + wd;
+ CheckEOL;
+ end;
+ end;
+ tokFont:
+ begin
+ if wd = '<FI>' then
+ begin
+ if fInclude then
+ sLine := sLine + '[';
+ end
+ else if wd = '<Fi>' then
+ begin
+ if fInclude then
+ sLine := sLine + ']';
+ end
+ end;
+ end
+ until tok = tokEOF;
+ if fASCIIisOpen then writeln(OutFile, sLine);
+ CloseASCII;
+ Label3.Caption := '';
+ end;
+ 2: begin
+ Label3.Caption := 'Converting ASCII postings';
+ bLastBook := 255;
+ bChap := 0;
+ FileMode := 1;
+ iFileNumber := 0;
+ fASCIIisOpen := false;
+ sLine := '';
+ repeat
+ Application.ProcessMessages;
+ wd := ANSIToOEM(InFile.GetToken(tok));
+ case tok of
+ tokEOF:
+ CloseASCII;
+ tokWord:
+ begin
+ if fInclude and (not fSkip) then
+ begin
+ sLine := sLine + wd;
+ CheckEOL;
+ end;
+ end;
+ tokSpace:
+ begin
+ if fInclude and (not fSkip) then
+ begin
+ sLine := sLine + wd;
+ CheckEOL;
+ end;
+ end;
+ tokSync:
+ begin
+ if fInclude and (length(wd) > 3) then
+ begin
+ if wd[3] = 'V' then
+ begin
+ sLine := sLine + '{' + InFile.sChapter+':'+
+ InFile.sVerse+'} ';
+ CheckEOL
+ end
+ else if (wd[3] = 'C') then
+ begin
+ OpenNTChapter;
+ if (InFile.bBk = 19) then
+ begin
+ StartNewLine;
+ if fASCIIisOpen then
+ begin
+ WriteLn(OutFile, 'Psalm '+InFile.sChapter);
+ WriteLn(OutFile);
+ end;
+ end;
+ end;
+ if wd[3] = 'B' then
+ begin
+ fProse := true;
+ CloseASCII;
+ end;
+ end;
+ end;
+ tokContent:
+ begin
+ if wd = '<BO>' then
+ fInclude := true
+ else if wd = '<BN>' then
+ begin
+ fInclude := true;
+ iFileNumber := 0;
+ end
+ else if wd = '<BO>' then
+ fInclude := ApocryphaCheckBox.Checked
+ end;
+ tokControl:
+ begin
+ if wd = '<CM>' then
+ begin
+ StartNewLine;
+ if fProse then
+ begin
+ if fASCIIisOpen then WriteLn(OutFile);
+ sLine := ' '
+ end
+ end
+ else if wd = '<CL>' then
+ begin
+ StartNewLine;
+ sLine := ' ';
+ end
+ else if wd = '<Pp>' then
+ fProse := true
+ else if wd = '<PP>' then
+ fProse := false
+ else if wd = '<RF>' then
+ fSkip := true
+ else if wd = '<Rf>' then
+ fSkip := false
+ else if wd = '<RN>' then
+ fSkip := true
+ else if wd = '<Rn>' then
+ fSkip := false
+ else if wd = '<ZZ>' then
+ fInclude := false
+ end;
+ tokChar:
+ begin
+ if fInclude and (not fSkip) then
+ begin
+ sLine := sLine + wd;
+ CheckEOL;
+ end;
+ end;
+ tokFont:
+ begin
+ if wd = '<FI>' then
+ begin
+ if fInclude then
+ sLine := sLine + '[';
+ end
+ else if wd = '<Fi>' then
+ begin
+ if fInclude then
+ sLine := sLine + ']';
+ end
+ end;
+ end
+ until tok = tokEOF;
+ if fASCIIisOpen then writeln(OutFile, sLine);
+ CloseASCII;
+ Label3.Caption := '';
+ end;
+ 3: begin
+ Label3.Caption := 'Converting to RTF';
+ AssignFile(OutFile, DestEdit.Text);
+ FileMode := 1;
+ Rewrite(OutFile);
+ repeat
+ Application.ProcessMessages;
+ wd := InFile.GetToken(tok);
+ case tok of
+ tokWord:
+ begin
+ if fInclude then
+ begin
+ LinePos := LinePos + Length(wd);
+ write(OutFile,wd);
+ end;
+ end;
+ tokSpace:
+ begin
+ if fInclude then
+ begin
+ LinePos := LinePos + Length(wd);
+ if LinePos > 78 then
+ begin
+ WriteLn(OutFile,wd);
+ LinePos := 0;
+ end
+ else
+ write(OutFile,wd);
+ end
+ end;
+ tokSync:
+ begin
+ if length(wd) > 1 then
+ begin
+ case wd[2] of
+ 'B': begin
+ if InFile.sBook <> LastBook then
+ begin
+ LastBook := InFile.sBook;
+ WriteLn(OutFile,'\par '+sTitlePar+
+ LastBook+'\par '+ParagraphAttributes);
+ LinePos := 0;
+ end;
+ end;
+ 'V': begin
+ s := '{\f5\super '+InFile.sChapter+':'+
+ InFile.sVerse+'}';
+ Write(OutFile,s);
+ LinePos := LinePos+Length(s);
+ end;
+ end;
+ end;
+ end;
+ tokControl:
+ begin
+ if length(wd) > 1 then
+ begin
+ case wd[2] of
+ 'A': fInclude := false;
+ 'E': begin
+ Write(OutFile,'{\b\cf1 ');
+ LinePos := LinePos + 8;
+ end;
+ 'F': fInclude := false;
+ 'H': begin
+ fInclude := true;
+ ParagraphAttributes := sHebrewTitlePar;
+ Write(OutFile,ParagraphAttributes);
+ LinePos := LinePos + Length(ParagraphAttributes);
+ end;
+ 'I' : begin
+ Write(OutFile,'{\i\cf1 ');
+ LinePos := LinePos + 7;
+ end;
+ 'J' : begin
+ Write(OutFile,'{\scaps ');
+ LinePos := LinePos + 8;
+ end;
+ 'K': fInclude := false;
+ 'M': begin
+ if fInclude then
+ begin
+ writeln(OutFile);
+ write(OutFile,'\par '+ParagraphAttributes);
+ LinePos := Length(ParagraphAttributes) + 5;
+ end;
+ end;
+ 'N': begin
+ fInclude := true;
+ ParagraphAttributes := sNormalPar;
+ Write(OutFile,ParagraphAttributes);
+ LinePos := LinePos + Length(ParagraphAttributes);
+ end;
+ 'P': begin
+ fInclude := true;
+ ParagraphAttributes := sPoetryPar;
+ Write(OutFile,ParagraphAttributes);
+ LinePos := LinePos + Length(ParagraphAttributes);
+ end;
+ 'Q': begin
+ fInclude := true;
+ ParagraphAttributes := sTitlePar;
+ Write(OutFile,ParagraphAttributes);
+ LinePos := LinePos + Length(ParagraphAttributes);
+ end;
+ 'R' : begin
+ Write(OutFile,'\cf6 ');
+ LinePos := LinePos + 4;
+ end;
+ 'S': begin
+ fInclude := true;
+ ParagraphAttributes := sSelahPar;
+ Write(OutFile,ParagraphAttributes);
+ LinePos := LinePos + Length(ParagraphAttributes);
+ end;
+ 'T': begin
+ fInclude := true;
+ ParagraphAttributes := sTitlePar;
+ Write(OutFile,ParagraphAttributes);
+ LinePos := LinePos + Length(ParagraphAttributes);
+ end;
+ 'U' : begin
+ Write(OutFile,'{\ul ');
+ LinePos := LinePos + 4;
+ end;
+ 'W': begin
+ fInclude := true;
+ ParagraphAttributes := sNormalQuotePar;
+ Write(OutFile,ParagraphAttributes);
+ LinePos := LinePos + Length(ParagraphAttributes);
+ end;
+ 'X': fInclude := false;
+ 'Y': begin
+ fInclude := true;
+ ParagraphAttributes := sPoetryQuotePar;
+ Write(OutFile,ParagraphAttributes);
+ LinePos := LinePos + Length(ParagraphAttributes);
+ end;
+ 'Z': fInclude := false;
+ 'a': fInclude := false;
+ 'c': fInclude := false;
+ 'e': begin
+ Write(OutFile,'}');
+ inc(LinePos);
+ end;
+ 'h': fInclude := false;
+ 'i': begin
+ Write(OutFile,'}');
+ inc(LinePos);
+ end;
+ 'j': begin
+ Write(OutFile,'}');
+ inc(LinePos);
+ end;
+ 'n': fInclude := false;
+ 'p': fInclude := false;
+ 'r': begin
+ Write(OutFile,'}');
+ inc(LinePos);
+ end;
+ 'u': begin
+ Write(OutFile,'}');
+ inc(LinePos);
+ end;
+
+ end;
+ end;
+ end;
+ tokChar:
+ begin
+ if fInclude then
+ begin
+ write(OutFile,wd);
+ LinePos := LinePos + length(wd);
+ end;
+ end;
+ end;
+ until tok = tokEOF;
+ writeln(OutFile,'\par }');
+ CloseFile(OutFile);
+ Label3.Caption := '';
+ end;
+ 4: begin // GBF
+ Label3.Caption := 'Converting to GBF';
+ OutGBF := TWriteGBF.Create;
+ OutGBF.Init(Trim(DestEdit.Text));
+ OutGBF.Out('<H000>');
+ repeat
+ Application.ProcessMessages;
+ wd := InFile.GetToken(tok);
+ if tok <> tokEOF then OutGBF.Out(wd);
+ until tok = tokEOF;
+ OutGBF.Done;
+ OutGBF.Free;
+ Label3.Caption := '';
+ end;
+ 5: begin // HTML
+ Label3.Caption := 'Converting to HTML';
+ fHTMLisOpen := false;
+ repeat
+ Application.ProcessMessages;
+ wd := Infile.GetToken(tok);
+ case tok of
+ tokEOF:
+ CloseHTML;
+ tokWord:
+ begin
+ if fInclude and (not fSkip) then
+ begin
+ sLine := sLine + wd;
+ CheckHTMLEOL;
+ end;
+ end;
+ tokSpace:
+ begin
+ if fInclude and (not fSkip) then
+ begin
+ sLine := sLine + wd;
+ CheckHTMLEOL;
+ end;
+ end;
+ tokSync:
+ begin
+ if fInclude and (length(wd) > 3) then
+ begin
+ if wd[3] = 'V' then
+ begin
+ if fRed then
+ sLine := sLine + '</FONT>';
+ sLine := sLine + '<FONT COLOR="#0000ff"><FONT SIZE=-1><SUP>'+
+ InFile.sChapter+':'+
+ InFile.sVerse+'</SUP></FONT></FONT>';
+ if fRed then
+ sLine := sLine + '<FONT COLOR="#ff0000">';
+ CheckHTMLEOL
+ end
+ else if (wd[3] = 'C') and (InFile.bBk = 19) then
+ begin
+ StartNewHTMLLine;
+ if fHTMLisOpen then
+ begin
+ WriteLn(OutFile, '<P><H2>Psalm '+
+ InFile.sChapter+'</H2>');
+ WriteLn(OutFile);
+ end;
+ end;
+ if wd[3] = 'B' then
+ begin
+ fProse := true;
+ CloseHTML;
+ end;
+ end;
+ end;
+ tokContent:
+ begin
+ if wd = '<BO>' then
+ fInclude := true
+ else if wd = '<BN>' then
+ fInclude := true
+ else if wd = '<BO>' then
+ fInclude := ApocryphaCheckBox.Checked
+ else if wd = '<Tt>' then
+ OpenHTML;
+ end;
+ tokControl:
+ begin
+ if wd = '<CM>' then
+ begin
+ StartNewHTMLLine;
+ if not fProse then
+ begin
+ sLine := sLine + ' &nbsp;';
+ end
+ end
+ else if wd = '<CL>' then
+ begin
+ StartNewHTMLLine;
+ sLine := sLine + ' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'
+ end
+ else if wd = '<Pp>' then
+ fProse := true
+ else if wd = '<PP>' then
+ fProse := false
+ else if wd = '<RF>' then
+ fSkip := true
+ else if wd = '<Rf>' then
+ fSkip := false
+ else if wd = '<RN>' then
+ fSkip := true
+ else if wd = '<Rn>' then
+ fSkip := false
+ else if wd = '<ZZ>' then
+ fInclude := false
+ end;
+ tokChar:
+ begin
+ if fInclude and (not fSkip) then
+ begin
+ if wd = '"' then
+ sLine := sLine + '&quot;'
+ else
+ sLine := sLine + wd;
+ CheckHTMLEOL;
+ end;
+ end;
+ tokFont:
+ begin
+ if fInclude then
+ begin
+ if wd = '<FI>' then
+ sLine := sLine + '<I>'
+ else if wd = '<Fi>' then
+ sLine := sLine + '</I>'
+ else if wd = '<FR>' then
+ begin
+ if not fRed then
+ begin
+ sLine := sLine + '<FONT COLOR="#ff0000">';
+ fRed := true
+ end
+ end
+ else if wd = '<Fr>' then
+ begin
+ if fRed then
+ begin
+ sLine := sLine + '</FONT>';
+ fRed := false
+ end
+ end
+ end;
+ end;
+ end;
+ until tok = tokEOF;
+ Label3.Caption := '';
+ end;
+ end;
+ InFile.Done;
+ end;
+ InFile.Free;
+ except
+ showmessage('Error!');
+ end;
+ GoBitBtn.Enabled := true;
+ QuickButton.Enabled := true;
+end;
+
+procedure TGBFConverterMainForm.GoBitBtnClick(Sender: TObject);
+begin
+ DoConversion;
+end;
+
+procedure TGBFConverterMainForm.Timer1Timer(Sender: TObject);
+begin
+ If InFile <> nil then
+ VerseLabel.Caption := InFile.sBook+' ['+IntToStr(InFile.bBk)+'] '+
+ InFile.sChapter+':'+InFile.sVerse
+ else
+ VerseLabel.Caption := '';
+end;
+
+procedure TGBFConverterMainForm.QuickConversion;
+begin
+ FormatRadioGroup.ItemIndex := 1;
+ DoConversion;
+ FormatRadioGroup.ItemIndex := 2;
+ DoConversion;
+ FormatRadioGroup.ItemIndex := 5;
+ DoConversion;
+end;
+
+procedure TGBFConverterMainForm.FormShow(Sender: TObject);
+begin
+ VerseLabel.Caption := '';
+ WdLabel.Caption := '';
+end;
+
+(*
+procedure TGBFConverterMainForm.TransformButtonClick(Sender: TObject);
+var apoc: textfile;
+ last, s, sBook, sChap, sVs: string;
+ blankcount, i: integer;
+begin
+ TransformButton.Enabled := false;
+ blankcount := 0;
+ assignfile(apoc, trim(sourceedit.text));
+ reset(apoc);
+ assignfile(outfile, trim(destedit.text));
+ rewrite(outfile);
+ last := '';
+ while not eof(apoc) do
+ begin
+ readln(apoc, s);
+ if s = '' then
+ begin
+ inc(blankcount);
+ if last <> '' then
+ begin
+ writeln(outfile, last, '~M');
+ last := '';
+ end;
+ end
+ else
+ begin
+ if blankcount >= 2 then
+ writeln(outfile, '~T',s,'~N~M') // book title
+ else if blankcount = 1 then
+ begin
+ sBook := '';
+ sChap := '';
+ sVs := '';
+ i := 1;
+ while (s[i] <> ' ') and (i <= Length(s)) do
+ begin
+ sBook := sBook + s[i];
+ inc(i);
+ end;
+ while (s[i] = ' ') and (i <= Length(s)) do
+ inc(i);
+ while (s[i] <> ':') and (i <= Length(s)) do
+ begin
+ sChap := sChap + s[i];
+ inc(i);
+ end;
+ inc(i);
+ while IsDigit(s[i]) and (i <= Length(s)) do
+ begin
+ sVs := sVs + s[i];
+ inc(i);
+ end;
+ write(outfile, '~B'+sBook+';~C'+sChap+';');
+ if sVs <> '' then
+ write(outfile, '~V'+sVs+';');
+ end
+ else
+ begin
+ if last <> '' then
+ begin
+ writeln(outfile, last);
+ end;
+ last := s;
+ end;
+ blankcount := 0;
+ end;
+ end;
+ if last <> '' then
+ begin
+ writeln(outfile, last);
+ last := s;
+ end;
+ closefile(outfile);
+ closefile(apoc);
+ TransformButton.Enabled := true;
+end;
+*)
+
+procedure TGBFConverterMainForm.FormatRadioGroupClick(Sender: TObject);
+begin
+ Case FormatRadioGroup.ItemIndex of
+ 0: // Plain ASCII (one file)
+ DestEdit.Text := 'pub\web.txt';
+ 1: // Plain ASCII (one file per book)
+ DestEdit.Text := 'pub\web.htm';
+ 2: // Daily posts
+ DestEdit.Text := 'pub\queue\web.txt';
+ 3: // RTF
+ DestEdit.Text := 'pub\web.rtf';
+ 4: // GBF
+ DestEdit.Text := 'pub\web.gbf';
+ 5: // HTML
+ DestEdit.Text := 'pub\htm\web.htm';
+ end;
+end;
+
+procedure TGBFConverterMainForm.QuickButtonClick(Sender: TObject);
+begin
+ QuickConversion;
+end;
+
+procedure TGBFConverterMainForm.FormActivate(Sender: TObject);
+begin
+ if ParamCount > 0 then
+ if ParamStr(1) = 'quick' then
+ begin
+ QuickConversion;
+ close;
+ end;
+end;
+
+end.
diff --git a/src/modules/texts/rawgbf/Makefile b/src/modules/texts/rawgbf/Makefile
new file mode 100644
index 0000000..35d6648
--- /dev/null
+++ b/src/modules/texts/rawgbf/Makefile
@@ -0,0 +1,5 @@
+
+root := ../../../..
+
+all:
+ make -C ${root}
diff --git a/src/modules/texts/rawgbf/Makefile.am b/src/modules/texts/rawgbf/Makefile.am
new file mode 100644
index 0000000..ab6aa2e
--- /dev/null
+++ b/src/modules/texts/rawgbf/Makefile.am
@@ -0,0 +1,4 @@
+rawgbfdir = $(top_srcdir)/src/modules/texts/rawgbf
+
+libsword_la_SOURCES += $(rawgbfdir)/rawgbf.cpp
+
diff --git a/src/modules/texts/rawgbf/gbf.cpp b/src/modules/texts/rawgbf/gbf.cpp
new file mode 100644
index 0000000..dc67a1c
--- /dev/null
+++ b/src/modules/texts/rawgbf/gbf.cpp
@@ -0,0 +1,735 @@
+enum TToken {
+tokNull, tokEOF, tokHeader, tokContent, tokTail, tokStyle,
+ tokWord, tokSpace, tokSync, tokControl, tokChar, tokFont};
+
+enum TCharacterAttribute { caBold, caSmallCaps, caItalic, caOTQuote, caRed,
+ caSuperscript, caUnderline, caSubscript};
+
+// TCharAttribs = set of TCharacterAttribute;
+
+
+struct TBookNameRec {
+ string Name, Abbr;
+ char Num;
+}
+
+const struct TBookNameRec TBookAbbr[116] = {
+ {"1 Chronicles", "1CH", 13}, //0
+ {"1 Corinthians", "1CO", 70}, //1
+ {"1 Esdras", "1E", 52}, //2
+ {"1 John", "1J", 86}, //3
+ {"1 Kings", "1K", 11}, //4
+ {"1 Maccabees", "1M", 50}, //5
+ {"1 Peter", "1P", 84}, //6
+ {"1 Samuel", "1S", 9}, //7
+ {"1 Thessalonians", "1TH", 76}, //8
+ {"1 Timothy", "1TI", 78}, //9
+ {"2 Chronicles", "2CH", 14}, //10
+ {"2 Corinthians", "2CO", 71}, //11
+ {"2 Esdras", "2E", 56}, //12
+ {"2 John", "2J", 87}, //13
+ {"2 Kings", "2K", 12}, //14
+ {"2 Maccabees", "2M", 51}, //15
+ {"2 Peter", "2P", 85}, //16
+ {"2 Samuel", "2S", 10}, //17
+ {"2 Thessalonians", "2TH", 77}, //18
+ {"2 Timothy", "2TI", 79}, //19
+ {"3 John", "3J", 88}, //20
+ {"3 Maccabees", "3M", 55}, //21
+ {"4 Maccabees", "4M", 57}, //22
+ {"1 Chronicles", "1 CH", 13}, //0
+ {"1 Corinthians", "1 CO", 70}, //1
+ {"1 Esdras", "1 E", 52}, //2
+ {"1 John", "1 J", 86}, //3
+ {"1 Kings", "1 K", 11}, //4
+ {"1 Maccabees", "1 M", 50}, //5
+ {"1 Peter", "1 P", 84}, //6
+ {"1 Samuel", "1 S", 9}, //7
+ {"1 Thessalonians", "1 TH", 76}, //8
+ {"1 Timothy", "1 TI", 78}, //9
+ {"2 Chronicles", "2 CH", 14}, //10
+ {"2 Corinthians", "2 CO", 71}, //11
+ {"2 Esdras", "2 E", 56}, //12
+ {"2 John", "2 J", 87}, //13
+ {"2 Kings", "2 K", 12}, //14
+ {"2 Maccabees", "2 M", 51}, //15
+ {"2 Peter", "2 P", 85}, //16
+ {"2 Samuel", "2 S", 10}, //17
+ {"2 Thessalonians", "2 TH", 77}, //18
+ {"2 Timothy", "2 TI", 79}, //19
+ {"3 John", "3 J", 88}, //20
+ {"3 Maccabees", "3 M", 55}, //21
+ {"4 Maccabees", "4 M", 57}, //22
+ {"Acts", "AC", 68}, //23
+ {"Amos", "AM", 30}, //24
+ {"Prayer of Asariah and the Song of the Three Jews", "AZ", 47},
+ {"Baruch", "BA", 45}, //26
+ {"Bel and the Dragon","BE", 49}, //27
+ {"Colossians", "CO", 75}, //28
+ {"Daniel", "DA", 27}, //29
+ {"Deuteronomy", "DE", 5}, //30
+ {"Deuteronomy", "DT", 5}, //31
+ {"Ecclesiasties", "EC", 21}, //32
+ {"Esther", "ES", 17}, //33
+ {"Exodus", "EX", 2}, //34
+ {"Ezekiel", "EZE", 26}, //35
+ {"Ezra", "EZR", 15}, //36
+ {"Galatians", "GA", 72}, //37
+ {"Genesis", "GE", 1}, //38
+ {"Genesis", "GN", 1}, //39
+ {"Ephesians", "EP", 73}, //40
+ {"Esther (Greek}", "GR", 42), //41
+ {"Habakkuk", "HAB", 35}, //42
+ {"Haggai", "HAG", 37}, //43
+ {"Hebrews", "HE", 82}, //44
+ {"Hosea", "HO", 28}, //45
+ {"Isaiah", "IS", 23}, //46
+ {"James", "JA", 83}, //47
+ {"Jeremiah", "JE", 24}, //48
+ {"Job", "JOB", 18}, //49
+ {"Joel", "JOE", 29}, //50
+ {"John", "JOH", 67}, //51
+ {"Jonah", "JON", 32}, //52
+ {"Joshua", "JOS", 6}, //53
+ {"Jude", "JUDE", 89}, //54
+ {"Judges", "JUDG", 7}, //55
+ {"Judith", "JUDI", 41}, //56
+ {"Lamentations", "LA", 25}, //57
+ {"Letter of Jeremiah",Abbr:"LET", 46}, //58
+ {"Leviticus", "LEV", 3}, //59
+ {"Luke", "LK", 66}, //60
+ {"Leviticus", "LV", 3}, //61
+ {"Luke", "LU", 66}, //62
+ {"Malachi", "MAL", 39}, //63
+ {"Prayer of Manasseh",Abbr:"MAN", 53}, //64
+ {"Mark", "MAR", 65}, //65
+ {"Matthew", "MAT", 64}, //66
+ {"Micah", "MI", 33}, //67
+ {"Nahum", "NA", 34}, //68
+ {"Nehemiah", "NE", 16}, //69
+ {"Numbers", "NU", 4}, //70
+ {"Obadiah", "OB", 31}, //71
+ {"Psalm 151", "P1", 54}, //72
+ {"Philemon", "PHILE", 81}, //73
+ {"Philippians", "PHILI", 74}, //74
+ {"Philemon", "PHM", 81}, //75
+ {"Philippians", "PHP", 74}, //76
+ {"Proverbs", "PR", 20}, //77
+ {"Psalms", "PS", 19}, //78
+ {"Revelation", "RE", 90}, //79
+ {"Romans", "RM", 69}, //80
+ {"Romans", "RO", 69}, //81
+ {"Ruth", "RU", 8}, //82
+ {"Sirach", "SI", 44}, //83
+ {"Song of Solomon", "SOL", 22}, //84
+ {"Song of Solomon", "SON", 22}, //85
+ {"Song of Solomon", "SS", 22}, //86
+ {"Susanna", "SU", 48}, //87
+ {"Titus", "TI", 80}, //88
+ {"Tobit", "TO", 40}, //89
+ {"Wisdom", "WI", 43}, //90
+ {"Zechariah", "ZEC", 38}, //91
+ {"Zephaniah", "ZEP", 36} //92
+ },
+
+string BookFileName[91] = {
+ "","Genesis","Exodus","Lev","Num","Deut","Joshua","Judges", // 0 - 7
+ "Ruth","1Sam","2Sam","1Kings","2Kings","1Chron","2Chron", // 8 - 14
+ "Ezra","Nehemiah","Esther","Job","Psalms","Proverbs", // 15-20
+ "Eccl","Song","Isaiah","Jeremiah","Lament","Ezekiel", // 21-26
+ "Daniel","Hosea","Joel","Amos","Obadiah","Jonah","Micah", // 27-33
+ "Nahum","Habakkuk","Zeph","Haggai","Zech","Malachi", // 34-39
+ "Tobit","Judith","Esther","Wisdom","Sirach","Baruch", // 40-45
+ "Let","Azar","Susanna","Bel","1Mac","2Mac","1Esdras", // 46-52
+ "Man","P1","3Mac","2Esdras","4Mac","","","","","","", // 53-63
+ "Matthew","Mark","Luke","John","Acts","Romans","1Cor", // 64-70
+ "2Cor","Gal","Eph","Philip","Col","1Thes","2Thes","1Tim", // 71-78
+ "2Tim","Titus","Philemon","Hebrews","James","1Peter", // 79-84
+ "2Peter","1John","2John","3John","Jude","Rev"}; // 85-90
+
+class TReadGBF {
+private:
+ FILE *fp;
+ string FName, TokenLine;
+ int TokenPos;
+ bool fFileIsOpen, fParagraphEnd, fInTitle, fInPsalmBookTitle, fInHebrewTitle, fInSectionTitle;
+
+public:
+ string sBook, sChapter, sVerse, sMode;
+ string sContext; // Last text type (header, body, or tail)
+ string sTitle; // Title of this book of the Bible
+ string sPsalmBookTitle; // Title of this Psalm book
+ string sHebrewTitle; // Psalm Hebrew title
+ string sSectionTitle; // Section headings
+ string sDate;
+ string sFontName;
+ int iTotalWords;
+ char chJustification, chDirection;
+ bool fIndent, fPoetry;
+ int CharAttribs;
+ char bBk, bChap, bVs, bWd;
+
+ bool Init(const string sFileName);
+ void Done();
+ string GetToken(TToken &TokenKind);
+ end;
+
+class TWriteGBF {
+ private:
+ F: TextFile;
+ FName, LineOut: string;
+ fFileIsOpen: boolean;
+ bBk, bChap, bVs, bWd: byte;
+
+ public
+
+ function Init(const sFileName: string): boolean;
+ function Done: boolean;
+ procedure Out(const s: string);
+ end;
+
+function isletter(const ch: char): boolean;
+function isinword(const ch: char): boolean;
+function IsDigit(const ch: char): Boolean;
+function IsUpper(const ch: char): Boolean;
+function ConformCase(const sPat, sSrc: string): string;
+function BookNameToNumber(const sBookName: string): byte;
+
+implementation
+
+function isletter(const ch: char): boolean;
+begin
+ case ch of
+ 'A'..'Z': isletter := true;
+ 'a'..'z': isletter := true;
+ else
+ isletter := false;
+ end;
+end;
+
+function isinword(const ch: char): boolean;
+begin
+ case ch of
+ '-': isinword := true;
+ 'A'..'Z': isinword := true;
+ 'a'..'z': isinword := true;
+ else
+ isinword := false;
+ end;
+end;
+
+function IsUpper(const ch: char): Boolean;
+begin
+ case ch of
+ 'A'..'Z': IsUpper := true;
+ else
+ IsUpper := false;
+ end;
+end;
+
+function IsDigit(const ch: char): Boolean;
+begin
+ case ch of
+ '0'..'9': IsDigit := true;
+ else
+ IsDigit := false;
+ end;
+end;
+
+
+function MatchAbbrev(const sName, sAbbrev: string): boolean;
+var i: integer;
+begin
+ if Length(sName) < Length(sAbbrev) then
+ Result := false
+ else
+ Result := true;
+ i := 1;
+ while (i <= Length(sAbbrev)) and Result do
+ begin
+ if UpCase(sName[i]) <> sAbbrev[i] then
+ Result := false;
+ inc(i);
+ end;
+end;
+
+function BookNameToNumber(const sBookName: string): byte;
+var i: integer;
+begin
+ Result := 0;
+ try
+ if IsDigit(sBookName[Length(sBookName)]) and IsDigit(sBookName[1]) then
+ Result := StrToInt(sBookName);
+ except
+ Result := 0;
+ end;
+ i := 0;
+ while (Result = 0) and (i <= 115) do // Yuk! Linear search.
+ begin
+ if MatchAbbrev(sBookName,BookAbbr[i].Abbr) then
+ begin
+ Result := BookAbbr[i].Num;
+ end;
+ inc(i);
+ end;
+end;
+
+function BookNumberToName(const bBookNum: byte): string;
+begin
+ if bBookNum <= 115 then
+ Result := BookAbbr[bBookNum].Name
+ else
+ Result := '';
+end;
+
+function ConformCase(const sPat, sSrc: string): string;
+var i: integer;
+begin
+ Result := sSrc;
+ if (Length(sPat) > 0) and (Length(sSrc) > 0) then
+ begin
+ Result := LowerCase(sSrc);
+ if IsUpper(sPat[1]) then
+ Result[1] := UpCase(Result[1]);
+ if (Length(sPat) > 1) and (Length(sSrc) > 1) then
+ begin
+ if IsUpper(sPat[2]) then
+ begin
+ for i := 2 to Length(Result) do
+ Result[i] := UpCase(Result[i]);
+ end;
+ end;
+ end;
+end;
+
+function TReadGBF.Init(const sFileName: string): boolean;
+var s: string;
+ tok: TToken;
+begin
+ try
+ fParagraphEnd := false;
+ bBk := 0;
+ bChap := 0;
+ bVs := 0;
+ bWd := 0;
+ iTotalWords := 0;
+ FName := sFileName;
+ Assign(F, FName);
+ reset(F);
+ readln(F, TokenLine);
+ TokenPos := 1;
+ fFileIsOpen := true;
+ repeat
+ s := GetToken(tok)
+ until (tok = tokEOF) or ((tok = tokHeader) and (s[3] = '0'));
+ Init := true;
+ except
+ Init := false;
+ fFileIsOpen := false;
+ end
+end;
+
+procedure TReadGBF.Done;
+begin
+ if fFileIsOpen then
+ begin
+ closefile(F);
+ fFileIsOpen := false;
+ end;
+end;
+
+function TReadGBF.GetToken(var TokenKind: TToken): string;
+var m: integer;
+begin
+ Result := '';
+ TokenKind := tokNull;
+ if TokenPos = 0 then
+ begin
+ if (not fFileIsOpen) or EOF(F) then
+ TokenKind := tokEOF
+ else
+ begin
+ ReadLn(F,TokenLine);
+ TokenPos := 1;
+ end;
+ end;
+ if TokenKind <> tokEOF then
+ begin
+ m := Length(TokenLine);
+ if TokenPos > m then
+ begin
+ TokenKind := tokSpace;
+ if fParagraphEnd then
+ fParagraphEnd := false
+ else
+ Result := ' ';
+ TokenPos := 0;
+ end
+ else
+ begin
+ if (TokenLine[TokenPos] = '<') then
+ begin
+ fParagraphEnd := false;
+ repeat
+ Result := Result + TokenLine[TokenPos];
+ inc(TokenPos);
+ until (TokenLine[TokenPos] = '>') or (TokenPos > m);
+ Result := Result + '>';
+ inc(TokenPos);
+ case result[2] of
+ 'B': begin // File body text type
+ TokenKind := tokContent;
+ sContext := Result;
+ end;
+ 'C': begin // Special characters
+ TokenKind := tokControl;
+ if (Result[3] = 'M') or (Result[3] = 'L') then
+ fParagraphEnd := true;
+ end;
+ 'D': begin // Direction
+ TokenKind := tokControl;
+ chDirection := Result[3];
+ end;
+ 'H': begin
+ TokenKind := tokHeader;
+ sContext := Result;
+ end;
+ 'F': begin // Font attributes
+ TokenKind := tokFont;
+ case Result[3] of
+ 'B': CharAttribs := CharAttribs + [caBold];
+ 'C': CharAttribs := CharAttribs + [caSmallCaps];
+ 'I': CharAttribs := CharAttribs + [caItalic];
+ 'N': sFontName := copy(Result,4,Length(Result)-4);
+ 'O': CharAttribs := CharAttribs + [caOTQuote];
+ 'R': CharAttribs := CharAttribs + [caRed];
+ 'S': CharAttribs := CharAttribs + [caSuperscript];
+ 'U': CharAttribs := CharAttribs + [caUnderline];
+ 'V': CharAttribs := CharAttribs + [caSubscript];
+ 'b': CharAttribs := CharAttribs - [caBold];
+ 'c': CharAttribs := CharAttribs - [caSmallCaps];
+ 'i': CharAttribs := CharAttribs - [caItalic];
+ 'n': sFontName := '';
+ 'o': CharAttribs := CharAttribs - [caOTQuote];
+ 'r': CharAttribs := CharAttribs - [caRed];
+ 's': CharAttribs := CharAttribs - [caSuperscript];
+ 'u': CharAttribs := CharAttribs - [caUnderline];
+ 'v': CharAttribs := CharAttribs - [caSubscript];
+
+ end;
+ end;
+ 'J': begin // Justification
+ TokenKind := tokStyle;
+ chJustification := Result[3];
+ end;
+ 'P': begin // Poetry/prose, indent
+ TokenKind := tokControl;
+ case Result[3] of
+ 'I': fIndent := true;
+ 'P': fPoetry := true;
+ 'i': fIndent := false;
+ 'p': fPoetry := false;
+ end;
+ end;
+ 'R': begin // References and footnotes
+ TokenKind := tokControl;
+ end;
+ 'S': begin // sync mark
+ TokenKind := TokSync;
+ case Result[3] of
+ 'B': begin // Book
+ sBook := system.copy(Result, 4, length(Result)-4);
+ sPsalmBookTitle := '';
+ if sBook = '' then
+ begin
+ inc(bBk);
+ sBook := BookNumberToName(bBk);
+ end
+ else
+ bBk := BookNameToNumber(sBook);
+ sTitle := sBook;
+ end;
+ 'C': begin //chapter
+ sChapter := system.copy(Result, 4, length(Result)-4);
+ if sChapter = '' then
+ begin
+ inc(bChap);
+ sChapter := IntToStr(bChap);
+ end
+ else
+ begin
+ try
+ bChap := StrToInt(sChapter);
+ except
+ showmessage('Non-numeric chapter: '+sBook+' '+sChapter);
+ end;
+ end;
+ sHebrewTitle := '';
+ end;
+ 'V': begin // Verse
+ bWd := 0;
+ sVerse := system.copy(Result, 4, length(Result)-4);
+ if sVerse = '' then
+ begin
+ inc(bVs);
+ sVerse := IntToStr(bVs);
+ end
+ else
+ begin
+ try
+ bVs := StrToInt(sVerse);
+ except
+ showmessage('Non-numeric verse: '+sBook+' '+sChapter+':'+sVerse);
+ end;
+ end;
+ end;
+ 'D': begin // Date
+ sDate := system.copy(Result, 3, length(Result)-4);
+ end;
+ end;
+ end;
+ 'T': begin // Titles
+ TokenKind := TokContent;
+ case Result[3] of
+ 'B':
+ begin
+ sPsalmBookTitle := '';
+ fInPsalmBookTitle := true;
+ end;
+ 'b': fInPsalmBookTitle := true;
+ 'H':
+ begin
+ sHebrewTitle := '';
+ fInHebrewTitle := true;
+ end;
+ 'h': fInHebrewTitle := false;
+ 'S':
+ begin
+ sSectionTitle := '';
+ fInSectionTitle := true;
+ end;
+ 's': fInSectionTitle := false;
+ 'T':
+ begin
+ sTitle := '';
+ fInTitle := true;
+ end;
+ 't': fInTitle := false;
+ end;
+ end;
+ 'Z': begin // File tail
+ TokenKind := tokTail;
+ sContext := Result;
+ if Result[3] = 'Z' then
+ done;
+ end;
+ else
+ TokenKind := TokControl;
+
+ end;
+ end
+ else if isletter(TokenLine[TokenPos]) then
+ begin {Word}
+ fParagraphEnd := false;
+ TokenKind := tokWord;
+ repeat
+ Result := Result + TokenLine[TokenPos];
+ inc(TokenPos);
+ until (TokenPos > m) or (not isinword(TokenLine[TokenPos]));
+ inc(bWd);
+ inc(iTotalWords);
+ end
+ else if ((TokenLine[TokenPos] = ' ') or (TokenLine[TokenPos] = #9)) then
+ begin
+ fParagraphEnd := false;
+ TokenKind := tokSpace;
+ Result := Result + TokenLine[TokenPos];
+ inc(TokenPos);
+ end
+ else
+ begin
+ fParagraphEnd := false;
+ TokenKind := tokChar;
+ Result := Result + TokenLine[TokenPos];
+ inc(TokenPos);
+ end
+ end;
+ end;
+ if ((TokenKind = tokWord) or (TokenKind = tokSpace) or
+ (TokenKind = tokChar)) then
+ begin
+ if fInTitle then
+ sTitle := sTitle + Result
+ else if fInPsalmBookTitle then
+ sPsalmBookTitle := sPsalmBookTitle + Result
+ else if fInHebrewTitle then
+ sHebrewTitle := sHebrewTitle + Result
+ else if fInSectionTitle then
+ sSectionTitle := sSectionTitle + Result;
+ end;
+end;
+
+function TWriteGBF.Init(const sFileName: string): boolean;
+begin
+ try
+ bBk := 0;
+ bChap := 0;
+ bVs := 0;
+ bWd := 0;
+ LineOut := '';
+ FName := sFileName;
+ Assign(F, FName);
+ filemode := 1;
+ rewrite(F);
+ fFileIsOpen := true;
+ Init := true;
+ except
+ Init := false;
+ fFileIsOpen := false;
+ end
+end;
+
+function TWriteGBF.Done: boolean;
+begin
+ try
+ if fFileIsOpen then
+ begin
+ if LineOut <> '' then
+ begin
+ WriteLn(F, LineOut);
+ LineOut := '';
+ end;
+ CloseFile(F);
+ end;
+ Done := true;
+ except
+ Done := false;
+ end;
+end;
+
+procedure TWriteGBF.Out(const s: string);
+var sPrint, sSave, sBook, sChapter, sVerse: string;
+ i: integer;
+ b: byte;
+begin
+ if (Length(s) > 0) and IsLetter(s[1]) then
+ begin
+ inc(bWd);
+ LineOut := LineOut + s;
+ end
+ else if Length(s) > 3 then
+ begin
+ if (s[1] = '<') and (s[2] = 'S') then
+ begin
+ case s[3] of
+ 'B': begin // Book
+ sBook := system.copy(s, 4, length(s)-4);
+ if sBook = '' then
+ begin
+ inc(bBk);
+ LineOut := LineOut + s;
+ end
+ else
+ begin
+ b := bBk;
+ bBk := BookNameToNumber(sBook);
+ if b <> bBk then
+ LineOut := LineOut + s;
+ end;
+ end;
+ 'C': begin //chapter
+ sChapter := system.copy(s, 4, length(s)-4);
+ if sChapter = '' then
+ begin
+ inc(bChap);
+ LineOut := LineOut + s;
+ end
+ else
+ begin
+ try
+// b := bChap;
+ bChap := StrToInt(sChapter);
+// if b <> bChap then
+ LineOut := LineOut + s;
+ except
+ showmessage('Non-numeric chapter: '+sBook+' '+sChapter);
+ end;
+ end;
+ end;
+ 'V': begin // Verse
+ bWd := 0;
+ sVerse := system.copy(s, 4, length(s)-4);
+ if sVerse = '' then
+ begin
+ inc(bVs);
+ LineOut := LineOut + s;
+ end
+ else
+ begin
+ try
+// b := bVs;
+ bVs := StrToInt(sVerse);
+// if b <> bVs then
+ LineOut := LineOut + s;
+ except
+ showmessage('Non-numeric verse: '+sBook+' '+sChapter+':'+sVerse);
+ end;
+ end;
+ end;
+ else
+ LineOut := LineOut + s;
+ end
+ end
+ else
+ LineOut := LineOut + s; // Not a sync mark
+ end
+ else // other token, space, or punctuation
+ LineOut := LineOut + s; // Length <= 3
+ if ((s = '<CM>') or (s = '<CL>')) then
+ begin
+ if (Length(LineOut) > 78) then
+ begin
+ i := 78;
+ while (i > 0) and (LineOut[i] <> ' ') do
+ dec(i);
+ if i < 1 then
+ begin
+ WriteLn(F,LineOut);
+ LineOut := '';
+ end
+ else
+ begin
+ sPrint := system.copy(LineOut,1,i-1);
+ sSave := system.copy(LineOut,i+1,Length(LineOut)-i);
+ WriteLn(F,sPrint);
+ WriteLn(F, sSave);
+ LineOut := '';
+ end
+ end
+ else
+ begin
+ WriteLn(F, LineOut);
+ LineOut := '';
+ end
+ end
+ else if (Length(LineOut) > 78) then
+ begin
+ i := 78;
+ while (i > 0) and (LineOut[i] <> ' ') do
+ dec(i);
+ if i < 1 then
+ begin
+ WriteLn(F,LineOut);
+ LineOut := '';
+ end
+ else
+ begin
+ sPrint := system.copy(LineOut,1,i-1);
+ sSave := system.copy(LineOut,i+1,Length(LineOut)-i);
+ WriteLn(F,sPrint);
+ LineOut := sSave;
+ end
+ end
+end;
+
+end.
diff --git a/src/modules/texts/rawgbf/gbf.h b/src/modules/texts/rawgbf/gbf.h
new file mode 100644
index 0000000..b695759
--- /dev/null
+++ b/src/modules/texts/rawgbf/gbf.h
@@ -0,0 +1,67 @@
+/* Header for module GBF, generated by p2c */
+#ifndef GBF_H
+#define GBF_H
+/* p2c: Gbf.pas, line 5: Warning: Could not find module SYSUTILS [271] */
+
+
+#include "sysutils.h"
+/* p2c: Gbf.pas, line 5: Warning: Could not find module DIALOGS [271] */
+#include "dialogs.h"
+
+
+#ifdef GBF_G
+# define vextern
+#else
+# define vextern extern
+#endif
+
+
+
+typedef enum {
+ tokNull, tokEOF, tokHeader, tokContent, tokTail, tokStyle, tokWord,
+ tokSpace, tokSync, tokControl, tokChar, tokFont
+} TToken;
+typedef enum {
+ caBold, caSmallCaps, caItalic, caOTQuote, caRed, caSuperscript, caUnderline,
+ caSubscript
+} TCharacterAttribute;
+typedef long TCharAttribs;
+
+
+
+typedef struct TBookNameRec {
+ Char Name[256], Abbr[256];
+ uchar Num;
+} TBookNameRec;
+
+typedef TBookNameRec TBookAbbr[116];
+/* p2c: Gbf.pas, line 25:
+ * Warning: Expected an expression, found a '/' [227] */
+/* p2c: Gbf.pas, line 25:
+ * Warning: Expected an expression, found a '/' [227] */
+/* p2c: Gbf.pas, line 25: Warning: Division by zero [163] */
+/* p2c: Gbf.pas, line 26: Warning: Division by zero [163] */
+/* p2c: Gbf.pas, line 26: Warning: Expected a ')', found a '(' [227] */
+/* p2c: Gbf.pas, line 144:
+ * Warning: Expected an expression, found a '/' [227] */
+/* p2c: Gbf.pas, line 144:
+ * Warning: Expected an expression, found a '/' [227] */
+/* p2c: Gbf.pas, line 144: Warning: Division by zero [163] */
+/* p2c: Gbf.pas, line 144: Warning: Division by zero [163] */
+/* p2c: Gbf.pas, line 145: Warning: Mixing non-strings with strings [170] */
+/* p2c: Gbf.pas, line 145:
+ * Warning: Expected a ')', found a string literal [227] */
+
+
+extern TBookAbbr BookAbbr;
+
+extern Char BookFileName[91][256];
+
+vextern Char STR1[256];
+
+
+#undef vextern
+
+#endif /*GBF_H*/
+
+/* End. */
diff --git a/src/modules/texts/rawgbf/gbfidx.cpp b/src/modules/texts/rawgbf/gbfidx.cpp
new file mode 100644
index 0000000..8337d62
--- /dev/null
+++ b/src/modules/texts/rawgbf/gbfidx.cpp
@@ -0,0 +1,294 @@
+/*****************************************************************************
+ *
+ * This code wreaks but works (at least for WEB). Good luck!
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifndef __GNUC__
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <versekey.h>
+
+
+void writeidx(VerseKey &key1, VerseKey &key2, VerseKey &key3, long offset, short size);
+char findbreak(int fp, long *offset, int *num1, int *num2, int *rangemax, short *size);
+void openfiles(char *fname);
+void checkparams(int argc, char **argv);
+
+
+VerseKey key1, key2, key3;
+int fp, vfp, cfp, bfp;
+long chapoffset;
+short chapsize;
+char testmnt;
+
+
+main(int argc, char **argv)
+{
+ long pos, offset;
+ int num1, num2, rangemax, curbook = 0, curchap = 0, curverse = 0;
+ char buf[127], startflag = 0;
+ short size, tmp;
+
+ checkparams(argc, argv);
+
+ openfiles(argv[1]);
+
+ testmnt = key1.Testament();
+ num1 = key1.Chapter();
+ num2 = key1.Verse();
+ pos = 0;
+ write(bfp, &pos, 4); /* Book offset for testament intros */
+ pos = 4;
+ write(cfp, &pos, 4); /* Chapter offset for testament intro */
+
+
+/* Right now just zero out intros until parsing correctly */
+ pos = 0;
+ size = 0;
+ write(vfp, &pos, 4); /* Module intro */
+ write(vfp, &size, 2);
+ write(vfp, &pos, 4); /* Testament intro */
+ write(vfp, &size, 2);
+
+ while(!findbreak(fp, &offset, &num1, &num2, &rangemax, &size)) {
+ if (!startflag) {
+ startflag = 1;
+ }
+ else {
+ if (num2 < key2.Verse()) { // new chapter
+ if (num1 <= key2.Chapter()) { // new book
+ key2.Verse(1);
+ key2.Chapter(1);
+ key2.Book(key2.Book()+1);
+ }
+ printf("Found Chapter Break: %d ('%s')\n", num1, (const char *)key2);
+ chapoffset = offset;
+ chapsize = size;
+// continue;
+ }
+ }
+ key2.Verse(1);
+ key2.Chapter(num1);
+ key2.Verse(num2);
+
+ key3 = key2;
+// key3 += (rangemax - key3.Verse());
+
+ writeidx(key1, key2, key3, offset, size);
+ }
+ close(vfp);
+ close(cfp);
+ close(bfp);
+ close(fp);
+}
+
+
+/**************************************************************************
+ * ENT: key1 - current location of index
+ * key2 - minimum keyval for which this offset is valid
+ * key3 - maximum keyval for which this offset is valid
+ */
+
+void writeidx(VerseKey &key1, VerseKey &key2, VerseKey &key3, long offset, short size)
+{
+ long pos;
+ short tmp;
+
+ for (; ((key1 <= key3) && (key1.Error() != KEYERR_OUTOFBOUNDS) && (key1.Testament() == testmnt)); key1+=1) {
+ if (key1.Verse() == 1) { // new chapter
+ if (key1.Chapter() == 1) { // new book
+ pos = lseek(cfp, 0, SEEK_CUR);
+ write(bfp, &pos, 4);
+ pos = lseek(vfp, 0, SEEK_CUR); /* Book intro (cps) */
+ write(cfp, &pos, 4);
+ write(vfp, &chapoffset, 4); /* Book intro (vss) set to same as chap for now(it should be chap 1 which usually contains the book into anyway)*/
+ write(vfp, &chapsize, 2);
+ }
+ pos = lseek(vfp, 0, SEEK_CUR);
+ write(cfp, &pos, 4);
+ write(vfp, &chapoffset, 4); /* Chapter intro */
+ write(vfp, &chapsize, 2);
+ }
+ if (key1 >= key2) {
+ write(vfp, &offset, 4);
+ write(vfp, &size, 2);
+ }
+ else {
+ pos = 0;
+ tmp = 0;
+ write(vfp, &pos, 4);
+ write(vfp, &tmp, 2);
+ }
+ }
+}
+
+
+char startchap(char *buf)
+{
+ char loop;
+
+ if (buf[0] != '<')
+ return 0;
+ if (buf[1] != 'S')
+ return 0;
+ if (buf[2] != 'C')
+ return 0;
+/*
+ if (!isdigit(buf[2]))
+ return 0;
+ for (loop = 3; loop < 7; loop++) {
+ if (buf[loop] == ' ')
+ break;
+ if ((!isdigit(buf[loop])) && (buf[loop] != ',') && (buf[loop] != '-'))
+ return 0;
+ }
+*/
+ return 1;
+}
+
+
+char startentry(char *buf)
+{
+ char loop;
+
+ if (buf[0] != '<')
+ return 0;
+ if (buf[1] != 'S')
+ return 0;
+ if (buf[2] != 'V')
+ return 0;
+/*
+ if (!isdigit(buf[2]))
+ return 0;
+ for (loop = 3; loop < 7; loop++) {
+ if (buf[loop] == ' ')
+ break;
+ if ((!isdigit(buf[loop])) && (buf[loop] != ',') && (buf[loop] != '-'))
+ return 0;
+ }
+*/
+ return 1;
+}
+
+
+char findbreak(int fp, long *offset, int *num1, int *num2, int *rangemax, short *size)
+{
+ char buf[7];
+ char buf2[20];
+ char ch;
+ char loop;
+ long offset2;
+ int ch2, vs2, rm2;
+ bool flag;
+ long chapstart = 0;
+
+ memset(buf, ' ', 7);
+
+ while (1) {
+ if (startchap(buf)) {
+ chapstart = lseek(fp, 0, SEEK_CUR) - 7;
+ memset(buf, ' ', 3);
+ flag = false;
+ for (loop = 3; loop < 6; loop++) {
+ if (isdigit(buf[loop]))
+ flag = true;
+ else {
+ buf[loop] = 0;
+ break;
+ }
+ }
+ if (flag)
+ *num1 = atoi(buf);
+ else (*num1)++;
+ }
+ if (startentry(buf)) {
+ memset(buf, ' ', 3);
+ flag = false;
+ for (loop = 3; loop < 6; loop++) {
+ if (isdigit(buf[loop]))
+ flag = true;
+ else {
+ buf[loop] = 0;
+ break;
+ }
+ if (flag)
+ *num2 = atoi(buf);
+ else (*num2)++;
+ }
+ loop++;
+ if (size)
+ *offset = lseek(fp, 0, SEEK_CUR) - (7 - loop);
+ else *offset = (chapstart) ? chapstart : lseek(fp, 0, SEEK_CUR) - 7;
+ if (size) {
+ ch2 = *num1;
+ vs2 = *num2;
+ if (findbreak(fp, &offset2, &ch2, &vs2, &rm2, 0)) {
+ *size = (short) (lseek(fp, 0, SEEK_END) - (*offset));
+ }
+ else {
+ if (vs2) {
+ *size = (offset2 - (*offset));
+ }
+ }
+ lseek(fp, *offset, SEEK_SET);
+ }
+ return 0;
+ }
+ memmove(buf, &buf[1], 6);
+ if (read(fp, &buf[6], 1) != 1)
+ return 1;
+ }
+}
+
+
+void openfiles(char *fname)
+{
+#ifndef O_BINARY // O_BINARY is needed in Borland C++ 4.53
+#define O_BINARY 0 // If it hasn't been defined than we probably
+#endif // don't need it.
+ char buf[255];
+
+ if ((fp = open(fname, O_RDONLY|O_BINARY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", fname);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.vss", fname);
+ if ((vfp = open(buf, O_CREAT|O_WRONLY|O_BINARY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.cps", fname);
+ if ((cfp = open(buf, O_CREAT|O_WRONLY|O_BINARY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.bks", fname);
+ if ((bfp = open(buf, O_CREAT|O_WRONLY|O_BINARY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+}
+
+
+void checkparams(int argc, char **argv)
+{
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s <file to process> [nt - for new testmt file]\n", argv[0]);
+ exit(1);
+ }
+ if (argc == 3)
+ key1 = key2 = key3 = "Matthew 1:1";
+ else key1 = key2 = key3 = "Genesis 1:1";
+}
diff --git a/src/modules/texts/rawgbf/rawgbf.cpp b/src/modules/texts/rawgbf/rawgbf.cpp
new file mode 100644
index 0000000..dd2fd47
--- /dev/null
+++ b/src/modules/texts/rawgbf/rawgbf.cpp
@@ -0,0 +1,84 @@
+/******************************************************************************
+ * rawgbf.cpp - code for class 'RawGBF'- a module that reads raw text files:
+ * ot and nt using indexs ??.bks ??.cps ??.vss
+ */
+
+
+#include <ctype.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#ifndef __GNUC__
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <string.h>
+#include <utilfuns.h>
+#include <rawverse.h>
+#include <rawgbf.h>
+
+
+/******************************************************************************
+ * RawGBF Constructor - Initializes data for instance of RawGBF
+ *
+ * ENT: iname - Internal name for module
+ * idesc - Name to display to user for module
+ * idisp - Display object to use for displaying
+ */
+
+RawGBF::RawGBF(const char *ipath, const char *iname, const char *idesc, SWDisplay *idisp) : SWText(iname, idesc, idisp), RawVerse(ipath)
+{
+}
+
+
+/******************************************************************************
+ * RawGBF Destructor - Cleans up instance of RawGBF
+ */
+
+RawGBF::~RawGBF()
+{
+}
+
+
+/******************************************************************************
+ * RawGBF::operator char * - Returns the correct verse when char * cast
+ * is requested
+ *
+ * RET: string buffer with verse
+ */
+
+RawGBF::operator char*()
+{
+ long start;
+ unsigned short size;
+ VerseKey *key = 0;
+
+#ifndef _WIN32_WCE
+ try {
+#endif
+ key = SWDYNAMIC_CAST(VerseKey, this->key);
+#ifndef _WIN32_WCE
+ }
+ catch ( ... ) {}
+#endif
+ if (!key)
+ key = new VerseKey(this->key);
+
+
+ findoffset(key->Testament(), key->Index(), &start, &size);
+
+ if (entrybuf)
+ delete [] entrybuf;
+ entrybuf = new char [ size * 3 ]; // extra for conversion to RTF or other.
+
+ readtext(key->Testament(), start, size + 1, entrybuf);
+ preptext(entrybuf);
+ RenderText(entrybuf, size * 3);
+
+ if (key != this->key)
+ delete key;
+
+ return entrybuf;
+}
diff --git a/src/modules/texts/rawtext/Makefile b/src/modules/texts/rawtext/Makefile
new file mode 100644
index 0000000..35d6648
--- /dev/null
+++ b/src/modules/texts/rawtext/Makefile
@@ -0,0 +1,5 @@
+
+root := ../../../..
+
+all:
+ make -C ${root}
diff --git a/src/modules/texts/rawtext/Makefile.am b/src/modules/texts/rawtext/Makefile.am
new file mode 100644
index 0000000..d0e1d7e
--- /dev/null
+++ b/src/modules/texts/rawtext/Makefile.am
@@ -0,0 +1,4 @@
+rawtextdir = $(top_srcdir)/src/modules/texts/rawtext
+
+libsword_la_SOURCES += $(rawtextdir)/rawtext.cpp
+
diff --git a/src/modules/texts/rawtext/kjvidx.cpp b/src/modules/texts/rawtext/kjvidx.cpp
new file mode 100644
index 0000000..708a9e6
--- /dev/null
+++ b/src/modules/texts/rawtext/kjvidx.cpp
@@ -0,0 +1,169 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <versekey.h>
+
+
+char findbreak(int fp, int *offset, int *num1, int *num2, short *size);
+
+
+main(int argc, char **argv)
+{
+ int fp, vfp, cfp, bfp;
+ long pos;
+ short size, tmp;
+ int num1, num2, offset, curbook = 0, curchap = 0, curverse = 0;
+ char buf[127];
+ VerseKey mykey;
+
+ if ((argc < 2) || (argc > 3)) {
+ fprintf(stderr, "usage: %s <file to process> [nt]\n", argv[0]);
+ exit(1);
+ }
+
+ if ((fp = open(argv[1], O_RDONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.vss", argv[1]);
+ if ((vfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.cps", argv[1]);
+ if ((cfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.bks", argv[1]);
+ if ((bfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ pos = 0;
+ write(bfp, &pos, 4); /* Book offset for testament intros */
+ pos = 4;
+ write(cfp, &pos, 4); /* Chapter offset for testament intro */
+
+
+/* Right now just zero out intros until parsing correctly */
+ pos = 0;
+ size = 0;
+ write(vfp, &pos, 4); /* Module intro */
+ write(vfp, &size, 2);
+ write(vfp, &pos, 4); /* Testament intro */
+ write(vfp, &size, 2);
+
+ mykey = (argc == 3) ? "Matthew 1:1" : "Genesis 1:1";
+
+ while (!findbreak(fp, &offset, &num1, &num2, &size)) {
+ num1 = mykey.Chapter();
+ num2 = mykey.Verse();
+ if (num2 == 1) { /* if we're at a new chapter */
+ if (num1 == 1) { /* if we're at a new book */
+ pos = lseek(cfp, 0, SEEK_CUR);
+ write(bfp, &pos, 4);
+ pos = lseek(vfp, 0, SEEK_CUR); /* Book intro (cps) */
+ write(cfp, &pos, 4);
+ pos = 0;
+ tmp = 0;
+ write(vfp, &pos, 4); /* Book intro (vss) */
+ write(vfp, &tmp, 2);
+ curbook++;
+ curchap = 0;
+ }
+ pos = lseek(vfp, 0, SEEK_CUR);
+ write(cfp, &pos, 4);
+ curverse = 1;
+ pos = 0;
+ tmp = 0;
+ write(vfp, &pos, 4); /* Chapter intro */
+ write(vfp, &tmp, 2);
+ curchap++;
+ }
+ else curverse++;
+
+ printf("%2d:%3d:%3d found at offset: %7d\n", curbook, num1, num2, offset);
+
+ if (num1 != curchap) {
+ fprintf(stderr, "Error: Found chaptures out of sequence\n");
+ break;
+ }
+ if (num2 != curverse) {
+ fprintf(stderr, "Error: Found verses out of sequence\n");
+ break;
+ }
+ write(vfp, &offset, 4);
+ write(vfp, &size, 2);
+ mykey++;
+ }
+
+ close(vfp);
+ close(cfp);
+ close(bfp);
+ close(fp);
+}
+
+
+char findbreak(int fp, int *offset, int *num1, int *num2, short *size)
+{
+ char buf[17];
+ char buf2[7];
+ char loop;
+ char offadj, inquotes, sizeadj;
+ int offset2, ch2, vs2;
+
+ memset(buf, ' ', 17);
+
+ while (1) {
+ offadj = -10;
+ inquotes = 0;
+ sizeadj = 0;
+ if ((!memcmp(buf, "\\widctlpar {\\b\\f0\\cf2 ", 16)) && (!size)) {
+ offadj = -1;
+// inquotes = 1;
+ sizeadj = -18;
+ }
+ if (!memcmp(&buf[1], "\\f0\\fs16\\cf2\\up6", 15)) {
+ offadj = 0;
+ inquotes = 1;
+ sizeadj = (*buf == 10) ? -18:-17;
+ }
+ if (!memcmp(buf, "\\fi200\\widctlpar", 16)) {
+ offadj = -1;
+// inquotes = 1;
+ sizeadj = -18;
+ }
+ if (offadj > -10) {
+ *offset = lseek(fp, 0, SEEK_CUR) + offadj;
+ if (size) {
+ (*offset)++;
+ while (inquotes) {
+ while (read(fp, buf2, 1) == 1) {
+ if (*buf2 == '}')
+ break;
+ (*offset)++;
+ }
+ inquotes--;
+ }
+ if (findbreak(fp, &offset2, &ch2, &vs2, 0)) {
+ *size = (short) (lseek(fp, 0, SEEK_END) - (*offset));
+ }
+ else {
+ sprintf(buf2, "%d:%d", ch2, vs2);
+ *size = (offset2 - (*offset));
+ }
+ lseek(fp, *offset+17, SEEK_SET);
+ }
+ else (*offset) += sizeadj;
+ return 0;
+ }
+ memmove(buf, &buf[1], 16);
+ if (read(fp, &buf[16], 1) != 1)
+ return 1;
+ }
+}
+
diff --git a/src/modules/texts/rawtext/makebnds.c b/src/modules/texts/rawtext/makebnds.c
new file mode 100644
index 0000000..44da447
--- /dev/null
+++ b/src/modules/texts/rawtext/makebnds.c
@@ -0,0 +1,86 @@
+#include <stdio.h>
+#include <fcntl.h>
+
+
+char *bnames[] = {
+ "Genesis", "Exodus", "Leviticus", "Numbers", "Deuteronomy",
+ "Joshua", "Judges", "Ruth", "I Samual", "II Samuel",
+ "I Kings", "II Kings", "I Chronicles", "II Chronicles", "Ezra",
+ "Nehemiah", "Esther", "Job", "Psalms", "Proverbs",
+ "Ecclesiastes", "Song of Solomon", "Isaiah", "Jeremiah", "Lamentations",
+ "Ezekiel", "Daniel", "Hosea", "Joel", "Amos",
+ "Obadiah", "Jonah", "Micah", "Nahum", "Habakkuk",
+ "Zephaniah", "Haggai", "Zechariah", "Malachi",
+ "Matthew", "Mark", "Luke", "John", "Acts",
+ "Romans", "I Corinthians", "II Corinthians", "Galatians", "Ephesians",
+ "Philippians", "Colossians", "I Thessalonians", "II Thessalonians", "I Timothy",
+ "II Timothy", "Titus", "Philemon", "Hebrews", "James",
+ "I Peter", "II Peter", "I John", "II John", "III John",
+ "Jude", "Revelation of John"};
+
+
+
+main(int argc, char **argv)
+{
+ int fp, vfp, cfp, bfp;
+ long pos;
+ int num1, num2, offset, offset2, chapmax, chapoff, chapoff2, curbook = 0, curchap = 0, curverse = 0;
+ char buf[127];
+
+ if (argc > 3) {
+ fprintf(stderr, "usage: %s <file to process> [NT?]\n", argv[0]);
+ exit(1);
+ }
+
+ if (argc > 2)
+ curbook = 39;
+ sprintf(buf, "%s.vss", argv[1]);
+ if ((vfp = open(buf, O_RDONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.cps", argv[1]);
+ if ((cfp = open(buf, O_RDONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.bks", argv[1]);
+ if ((bfp = open(buf, O_RDONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ read(bfp, &offset2, sizeof(offset2));
+ read(cfp, &chapoff2, sizeof(chapoff2));
+ while (read(bfp, &offset, sizeof(offset)) == sizeof(offset)) {
+ chapmax = (offset - offset2) / sizeof(offset);
+ printf("\n\{\"%s\", %d}, \n// %s\n", bnames[curbook], chapmax, bnames[curbook]);
+ curbook++;
+ for (curchap = 0; curchap < chapmax; curchap++) {
+ read(cfp, &chapoff, sizeof(chapoff));
+ printf("%d, ", (chapoff - chapoff2) / sizeof(chapoff));
+ chapoff2 = chapoff;
+ }
+ offset2 = offset;
+ }
+ pos = lseek(cfp, 0, SEEK_CUR);
+ offset = (int) lseek(cfp, 0, SEEK_END);
+ chapmax = (offset - offset2) / sizeof(offset);
+ printf("\n\{\"%s\", %d}, \n// %s\n", bnames[curbook], chapmax, bnames[curbook]);
+ curbook++;
+ lseek(cfp, pos, SEEK_SET);
+ for (curchap = 0; curchap < chapmax - 1; curchap++) {
+ read(cfp, &chapoff, sizeof(chapoff));
+ printf("%d, ", (chapoff - chapoff2) / sizeof(chapoff));
+ chapoff2 = chapoff;
+ }
+ chapoff = (int) lseek(vfp, 0, SEEK_END);
+ printf("%d, ", (chapoff - chapoff2) / sizeof(chapoff));
+
+ close(vfp);
+ close(cfp);
+ close(bfp);
+ close(fp);
+}
diff --git a/src/modules/texts/rawtext/nuidx.cpp b/src/modules/texts/rawtext/nuidx.cpp
new file mode 100644
index 0000000..edf298d
--- /dev/null
+++ b/src/modules/texts/rawtext/nuidx.cpp
@@ -0,0 +1,238 @@
+/*****************************************************************************
+ *
+ * This code wreaks but works (at least for MHC). Good luck!
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifndef __GNUC__
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <versekey.h>
+
+
+void writeidx(VerseKey &key1, VerseKey &key2, VerseKey &key3, long offset, short size);
+char findbreak(int fp, long *offset, int *num1, int *num2, int *rangemax, short *size);
+void openfiles(char *fname);
+void checkparams(int argc, char **argv);
+
+
+VerseKey key1, key2, key3;
+int fp, vfp, cfp, bfp;
+long chapoffset;
+short chapsize;
+char testmnt;
+
+
+main(int argc, char **argv)
+{
+ long pos, offset;
+ int num1, num2, rangemax, curbook = 0, curchap = 0, curverse = 0;
+ char buf[127], startflag = 0;
+ short size, tmp;
+
+ checkparams(argc, argv);
+
+ openfiles(argv[1]);
+
+ testmnt = key1.Testament();
+ num1 = key1.Chapter();
+ num2 = key1.Verse();
+ pos = 0;
+ write(bfp, &pos, 4); /* Book offset for testament intros */
+ pos = 4;
+ write(cfp, &pos, 4); /* Chapter offset for testament intro */
+
+
+/* Right now just zero out intros until parsing correctly */
+ pos = 0;
+ size = 0;
+ write(vfp, &pos, 4); /* Module intro */
+ write(vfp, &size, 2);
+ write(vfp, &pos, 4); /* Testament intro */
+ write(vfp, &size, 2);
+
+ while(!findbreak(fp, &offset, &num1, &num2, &rangemax, &size)) {
+ writeidx(key1, key2, key3, offset, size);
+ key2++;
+ key3 = key2;
+ }
+ close(vfp);
+ close(cfp);
+ close(bfp);
+ close(fp);
+}
+
+
+/**************************************************************************
+ * ENT: key1 - current location of index
+ * key2 - minimum keyval for which this offset is valid
+ * key3 - maximum keyval for which this offset is valid
+ */
+
+void writeidx(VerseKey &key1, VerseKey &key2, VerseKey &key3, long offset, short size)
+{
+ long pos;
+ short tmp;
+
+ for (; ((key1 <= key3) && (key1.Error() != KEYERR_OUTOFBOUNDS) && (key1.Testament() == testmnt)); key1+=1) {
+ if (key1.Verse() == 1) { // new chapter
+ if (key1.Chapter() == 1) { // new book
+ pos = lseek(cfp, 0, SEEK_CUR);
+ write(bfp, &pos, 4);
+ pos = lseek(vfp, 0, SEEK_CUR); /* Book intro (cps) */
+ write(cfp, &pos, 4);
+ write(vfp, &chapoffset, 4); /* Book intro (vss) set to same as chap for now(it should be chap 1 which usually contains the book into anyway)*/
+ write(vfp, &chapsize, 2);
+ }
+ pos = lseek(vfp, 0, SEEK_CUR);
+ write(cfp, &pos, 4);
+ write(vfp, &chapoffset, 4); /* Chapter intro */
+ write(vfp, &chapsize, 2);
+ }
+ if (key1 >= key2) {
+ write(vfp, &offset, 4);
+ write(vfp, &size, 2);
+ }
+ else {
+ pos = 0;
+ tmp = 0;
+ write(vfp, &pos, 4);
+ write(vfp, &tmp, 2);
+ }
+ }
+}
+
+
+char startchap(char *buf)
+{
+ char loop;
+
+ if (buf[0] != '<')
+ return 0;
+ if (buf[1] != 'S')
+ return 0;
+ if (buf[2] != 'C')
+ return 0;
+/*
+ if (!isdigit(buf[2]))
+ return 0;
+ for (loop = 3; loop < 7; loop++) {
+ if (buf[loop] == ' ')
+ break;
+ if ((!isdigit(buf[loop])) && (buf[loop] != ',') && (buf[loop] != '-'))
+ return 0;
+ }
+*/
+ return 1;
+}
+
+
+char startentry(char *buf)
+{
+ char loop;
+
+ if (buf[0] != '<')
+ return 0;
+ if (buf[1] != 'S')
+ return 0;
+ if (buf[2] != 'V')
+ return 0;
+/*
+ if (!isdigit(buf[2]))
+ return 0;
+ for (loop = 3; loop < 7; loop++) {
+ if (buf[loop] == ' ')
+ break;
+ if ((!isdigit(buf[loop])) && (buf[loop] != ',') && (buf[loop] != '-'))
+ return 0;
+ }
+*/
+ return 1;
+}
+
+
+char findbreak(int fp, long *offset, int *num1, int *num2, int *rangemax, short *size)
+{
+ char buf[7];
+ char buf2[20];
+ char ch;
+ char loop;
+ long offset2;
+ int ch2, vs2, rm2;
+ bool flag;
+ long chapstart = 0;
+
+ memset(buf, ' ', 7);
+
+ while (1) {
+ if (startentry(buf)) {
+ if (size)
+ *offset = lseek(fp, 0, SEEK_CUR) - 3;
+ else *offset = lseek(fp, 0, SEEK_CUR) - 7;
+ if (size) {
+ ch2 = *num1;
+ vs2 = *num2;
+ if (findbreak(fp, &offset2, &ch2, &vs2, &rm2, 0)) {
+ *size = (short) (lseek(fp, 0, SEEK_END) - (*offset));
+ }
+ else {
+ *size = (offset2 - (*offset));
+ }
+ lseek(fp, *offset, SEEK_SET);
+ }
+ return 0;
+ }
+ memmove(buf, &buf[1], 6);
+ if (read(fp, &buf[6], 1) != 1)
+ return 1;
+ }
+}
+
+
+void openfiles(char *fname)
+{
+ char buf[255];
+
+ if ((fp = open(fname, O_RDONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", fname);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.vss", fname);
+ if ((vfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.cps", fname);
+ if ((cfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.bks", fname);
+ if ((bfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+}
+
+
+void checkparams(int argc, char **argv)
+{
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s <file to process> [nt - for new testmt file]\n", argv[0]);
+ exit(1);
+ }
+ if (argc == 3)
+ key1 = key2 = key3 = "Matthew 1:1";
+ else key1 = key2 = key3 = "Genesis 1:1";
+}
diff --git a/src/modules/texts/rawtext/ojbtxidx.c b/src/modules/texts/rawtext/ojbtxidx.c
new file mode 100644
index 0000000..f70cc01
--- /dev/null
+++ b/src/modules/texts/rawtext/ojbtxidx.c
@@ -0,0 +1,166 @@
+#include <stdio.h>
+#include <fcntl.h>
+#ifndef __GNUC__
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+
+char findbreak(int fd, long *offset, int *num1, int *num2, short *size);
+
+
+main(int argc, char **argv)
+{
+ int fd, vfd, cfd, bfd;
+ long pos, offset;
+ short size, tmp;
+ int num1, num2, curbook = 0, curchap = 0, curverse = 0;
+ char buf[127];
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <file to process>\n", argv[0]);
+ exit(1);
+ }
+#ifndef O_BINARY // O_BINARY is for Borland to be happy. If we're in GNU, just define it to a NULL mask
+#define O_BINARY 0
+#endif
+ if ((fd = open(argv[1], O_RDONLY|O_BINARY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.vss", argv[1]);
+ if ((vfd = open(buf, O_CREAT|O_WRONLY|O_BINARY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.cps", argv[1]);
+ if ((cfd = open(buf, O_CREAT|O_WRONLY|O_BINARY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.bks", argv[1]);
+ if ((bfd = open(buf, O_CREAT|O_WRONLY|O_BINARY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ pos = 0;
+ write(bfd, &pos, 4); /* Book offset for testament intros */
+ pos = 4;
+ write(cfd, &pos, 4); /* Chapter offset for testament intro */
+
+
+/* Right now just zero out intros until parsing correctly */
+ pos = 0;
+ size = 0;
+ write(vfd, &pos, 4); /* Module intro */
+ write(vfd, &size, 2);
+ write(vfd, &pos, 4); /* Testament intro */
+ write(vfd, &size, 2);
+
+ while (!findbreak(fd, &offset, &num1, &num2, &size)) {
+
+ if (num2 == 1) { /* if we're at a new chapter */
+ if (num1 == 1) { /* if we're at a new book */
+ pos = lseek(cfd, 0, SEEK_CUR);
+ write(bfd, &pos, 4);
+ pos = lseek(vfd, 0, SEEK_CUR); /* Book intro (cps) */
+ write(cfd, &pos, 4);
+ pos = 0;
+ tmp = 0;
+ write(vfd, &pos, 4); /* Book intro (vss) */
+ write(vfd, &tmp, 2);
+ curbook++;
+ curchap = 0;
+ }
+ pos = lseek(vfd, 0, SEEK_CUR);
+ write(cfd, &pos, 4);
+ curverse = 1;
+ pos = 0;
+ tmp = 0;
+ write(vfd, &pos, 4); /* Chapter intro */
+ write(vfd, &tmp, 2);
+ curchap++;
+ }
+ else curverse++;
+
+ printf("%2d:%3d:%3d found at offset: %7ld\n", curbook, num1, num2, offset);
+
+ if (num1 != curchap) {
+ fprintf(stderr, "Error: Found chaptures out of sequence (%2d:%3d:%3d)\n", curbook, num1-1, num2);
+ curchap = num1;
+// break;
+ }
+ if (num2 != curverse) {
+ fprintf(stderr, "Error: Found verses out of sequence (%2d:%3d:%3d)\n", curbook, num1, num2-1);
+// break;
+ tmp = 0;
+ curverse = num2;
+ write(vfd, &offset, 4);
+ write(vfd, &tmp, 2);
+ }
+ write(vfd, &offset, 4);
+ write(vfd, &size, 2);
+ }
+
+ close(vfd);
+ close(cfd);
+ close(bfd);
+ close(fd);
+ return 0;
+}
+
+
+char findbreak(int fd, long *offset, int *num1, int *num2, short *size)
+{
+ char buf[8];
+ char buf2[7];
+ char loop, len, star;
+
+ memset(buf, ' ', 7);
+ buf[7] = 0;
+
+ while (1) {
+
+ memmove(buf, &buf[1], 6);
+ if (read(fd, &buf[6], 1) != 1)
+ return 1;
+
+ if ((buf[0] == 10) && ((buf[2] == '*') || (buf[3] == '*') || (buf[4] == '*'))) {
+ star = 0;
+ for (loop = 0; loop < 7; loop++) {
+ if (buf[loop] == '*')
+ star = 1;
+ if (isdigit(buf[loop])&&star)
+ break;
+ else buf[loop] = ' ';
+ }
+ if (loop < 7) {
+ sscanf(buf, "%d", num1);
+ continue;
+ }
+ }
+
+ if ((buf[0] == '|') && (isdigit(buf[1]))) {
+ sscanf(&buf[1], "%d", num2);
+ sprintf(buf, "%d", *num2);
+ (*offset) = lseek(fd, 0, SEEK_CUR);
+ (*offset) -= (4-strlen(buf));
+
+ for (len = 1; len == 1; len = read(fd, &loop, 1)) {
+ if (loop == '|')
+ break;
+ }
+
+ *size = (short)(lseek(fd, 0, SEEK_CUR) - *offset) - 1;
+ lseek(fd, -1, SEEK_CUR);
+ break;
+ }
+ }
+ return 0;
+}
+
diff --git a/src/modules/texts/rawtext/rawtext.cpp b/src/modules/texts/rawtext/rawtext.cpp
new file mode 100644
index 0000000..c2214f8
--- /dev/null
+++ b/src/modules/texts/rawtext/rawtext.cpp
@@ -0,0 +1,580 @@
+/******************************************************************************
+ * rawtext.cpp - code for class 'RawText'- a module that reads raw text files:
+ * ot and nt using indexs ??.bks ??.cps ??.vss
+ */
+
+
+#include <stdio.h>
+#include <fcntl.h>
+
+#ifndef __GNUC__
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <string.h>
+#include <utilfuns.h>
+#include <rawverse.h>
+#include <rawtext.h>
+
+#include <map>
+#include <list>
+#include <algorithm>
+#include <regex.h> // GNU
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/******************************************************************************
+ * RawText Constructor - Initializes data for instance of RawText
+ *
+ * ENT: iname - Internal name for module
+ * idesc - Name to display to user for module
+ * idisp - Display object to use for displaying
+ */
+
+RawText::RawText(const char *ipath, const char *iname, const char *idesc, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang)
+ : SWText(iname, idesc, idisp, enc, dir, mark, ilang),
+ RawVerse(ipath) {
+
+ string fname;
+ fname = path;
+ char ch = fname.c_str()[strlen(fname.c_str())-1];
+ if ((ch != '/') && (ch != '\\'))
+ fname += "/";
+
+ for (int loop = 0; loop < 2; loop++) {
+ fastSearch[loop] = 0;
+ string fastidxname =(fname + ((loop)?"ntwords.dat":"otwords.dat"));
+ if (!access(fastidxname.c_str(), 04)) {
+ fastidxname = (fname + ((loop)?"ntwords.idx":"otwords.idx"));
+ if (!access(fastidxname.c_str(), 04))
+ fastSearch[loop] = new RawStr((fname + ((loop)?"ntwords":"otwords")).c_str());
+ }
+ }
+}
+
+
+/******************************************************************************
+ * RawText Destructor - Cleans up instance of RawText
+ */
+
+RawText::~RawText()
+{
+ if (fastSearch[0])
+ delete fastSearch[0];
+
+ if (fastSearch[1])
+ delete fastSearch[1];
+}
+
+
+/******************************************************************************
+ * RawText::getRawEntry - Returns the correct verse when char * cast
+ * is requested
+ *
+ * RET: string buffer with verse
+ */
+
+char *RawText::getRawEntry() {
+ long start = 0;
+ unsigned short size = 0;
+ VerseKey *key = 0;
+
+ // see if we have a VerseKey * or decendant
+ try {
+ key = SWDYNAMIC_CAST(VerseKey, this->key);
+ }
+ catch ( ... ) { }
+ // if we don't have a VerseKey * decendant, create our own
+ if (!key)
+ key = new VerseKey(this->key);
+
+ findoffset(key->Testament(), key->Index(), &start, &size);
+ entrySize = size; // support getEntrySize call
+
+ unsigned long newsize = (size + 2) * FILTERPAD;
+ if (newsize > entrybufallocsize) {
+ if (entrybuf)
+ delete [] entrybuf;
+ entrybuf = new char [ newsize ];
+ entrybufallocsize = newsize;
+ }
+ *entrybuf = 0;
+
+ readtext(key->Testament(), start, (size + 2), entrybuf);
+
+ rawFilter(entrybuf, size, key);
+
+ if (!isUnicode())
+ preptext(entrybuf);
+
+ if (this->key != key) // free our key if we created a VerseKey
+ delete key;
+
+ return entrybuf;
+}
+
+
+signed char RawText::createSearchFramework() {
+ SWKey *savekey = 0;
+ SWKey *searchkey = 0;
+ SWKey textkey;
+ char *word = 0;
+ char *wordBuf = 0;
+
+ // dictionary holds words associated with a list
+ // containing every module position that contains
+ // the word. [0] Old Testament; [1] NT
+ map < string, list<long> > dictionary[2];
+
+
+ // save key information so as not to disrupt original
+ // module position
+ if (!key->Persist()) {
+ savekey = CreateKey();
+ *savekey = *key;
+ }
+ else savekey = key;
+
+ searchkey = (key->Persist())?key->clone():0;
+ if (searchkey) {
+ searchkey->Persist(1);
+ SetKey(*searchkey);
+ }
+
+ // position module at the beginning
+ *this = TOP;
+
+ VerseKey *lkey = (VerseKey *)key;
+
+ // iterate thru each entry in module
+ while (!Error()) {
+ long index = lkey->Index();
+ wordBuf = (char *)calloc(sizeof(char), strlen(StripText()) + 1);
+ strcpy(wordBuf, StripText());
+
+ // grab each word from the text
+ word = strtok(wordBuf, " !.,?;:()-=+/\\|{}[]\"<>");
+ while (word) {
+
+ // make word upper case
+ toupperstr(word);
+
+ // lookup word in dictionary (or make entry in dictionary
+ // for this word) and add this module position (index) to
+ // the word's associated list of module positions
+ dictionary[lkey->Testament()-1][word].push_back(index);
+ word = strtok(NULL, " !.,?;:()-=+/\\|{}[]\"<>");
+ }
+ free(wordBuf);
+ (*this)++;
+ }
+
+ // reposition module back to where it was before we were called
+ SetKey(*savekey);
+
+ if (!savekey->Persist())
+ delete savekey;
+
+ if (searchkey)
+ delete searchkey;
+
+
+ // --------- Let's output an index from our dictionary -----------
+ int datfd;
+ int idxfd;
+ map < string, list<long> >::iterator it;
+ list<long>::iterator it2;
+ unsigned long offset, entryoff;
+ unsigned short size;
+
+ string fname;
+ fname = path;
+ char ch = fname.c_str()[strlen(fname.c_str())-1];
+ if ((ch != '/') && (ch != '\\'))
+ fname += "/";
+
+ // for old and new testament do...
+ for (int loop = 0; loop < 2; loop++) {
+ if ((datfd = open((fname + ((loop)?"ntwords.dat":"otwords.dat")).c_str(), O_CREAT|O_WRONLY|O_BINARY, 00644 )) == -1)
+ return -1;
+ if ((idxfd = open((fname + ((loop)?"ntwords.idx":"otwords.idx")).c_str(), O_CREAT|O_WRONLY|O_BINARY, 00644 )) == -1) {
+ close(datfd);
+ return -1;
+ }
+
+ // iterate thru each word in the dictionary
+ for (it = dictionary[loop].begin(); it != dictionary[loop].end(); it++) {
+ printf("%s: ", it->first.c_str());
+
+ // get our current offset in our word.dat file and write this as the start
+ // of the next entry in our database
+ offset = lseek(datfd, 0, SEEK_CUR);
+ write(idxfd, &offset, 4);
+
+ // write our word out to the word.dat file, delineating with a \n
+ write(datfd, it->first.c_str(), strlen(it->first.c_str()));
+ write(datfd, "\n", 1);
+
+ // force our mod position list for this word to be unique (remove
+ // duplicates that may exist if the word was found more than once
+ // in the verse
+ it->second.unique();
+
+ // iterate thru each mod position for this word and output it to
+ // our database
+ unsigned short count = 0;
+ for (it2 = it->second.begin(); it2 != it->second.end(); it2++) {
+ entryoff= *it2;
+ write(datfd, &entryoff, 4);
+ count++;
+ }
+
+ // now see what our new position is in our word.dat file and
+ // determine the size of this database entry
+ size = lseek(datfd, 0, SEEK_CUR) - offset;
+
+ // store the size of this database entry
+ write(idxfd, &size, 2);
+ printf("%d entries (size: %d)\n", count, size);
+ }
+ close(datfd);
+ close(idxfd);
+ }
+ return 0;
+}
+
+
+/******************************************************************************
+ * SWModule::Search - Searches a module for a string
+ *
+ * ENT: istr - string for which to search
+ * searchType - type of search to perform
+ * >=0 - regex
+ * -1 - phrase
+ * -2 - multiword
+ * flags - options flags for search
+ * justCheckIfSupported - if set, don't search, only tell if this
+ * function supports requested search.
+ *
+ * RET: listkey set to verses that contain istr
+ */
+
+ListKey &RawText::Search(const char *istr, int searchType, int flags, SWKey *scope, bool *justCheckIfSupported, void (*percent)(char, void *), void *percentUserData)
+{
+ listkey.ClearList();
+
+ if ((fastSearch[0]) && (fastSearch[1])) {
+
+ switch (searchType) {
+ case -2: {
+
+ if ((flags & REG_ICASE) != REG_ICASE) // if haven't chosen to
+ // ignore case
+ break; // can't handle fast case sensitive searches
+
+ // test to see if our scope for this search is bounded by a
+ // VerseKey
+ VerseKey *testKeyType = 0;
+ try {
+ testKeyType = SWDYNAMIC_CAST(VerseKey, ((scope)?scope:key));
+ }
+ catch ( ... ) {}
+ // if we don't have a VerseKey * decendant we can't handle
+ // because of scope.
+ // In the future, add bool SWKey::isValid(const char *tryString);
+ if (!testKeyType)
+ break;
+
+
+ // check if we just want to see if search is supported.
+ // If we've gotten this far, then it is supported.
+ if (justCheckIfSupported) {
+ *justCheckIfSupported = true;
+ return listkey;
+ }
+
+ SWKey saveKey = *testKeyType; // save current place
+
+ char error = 0;
+ char **words = 0;
+ char *wordBuf = 0;
+ int wordCount = 0;
+ long start;
+ unsigned short size;
+ char *idxbuf = 0;
+ char *datbuf = 0;
+ list <long> indexes;
+ list <long> indexes2;
+ VerseKey vk;
+ vk = TOP;
+
+ (*percent)(10, percentUserData);
+
+ // toupper our copy of search string
+ stdstr(&wordBuf, istr);
+ toupperstr(wordBuf);
+
+ // get list of individual words
+ words = (char **)calloc(sizeof(char *), 10);
+ int allocWords = 10;
+ words[wordCount] = strtok(wordBuf, " ");
+ while (words[wordCount]) {
+ wordCount++;
+ if (wordCount == allocWords) {
+ allocWords+=10;
+ words = (char **)realloc(words, sizeof(char *)*allocWords);
+ }
+ words[wordCount] = strtok(NULL, " ");
+ }
+
+ (*percent)(20, percentUserData);
+
+ // clear our result set
+ indexes.erase(indexes.begin(), indexes.end());
+
+ // search both old and new testament indexes
+ for (int j = 0; j < 2; j++) {
+ // iterate thru each word the user passed to us.
+ for (int i = 0; i < wordCount; i++) {
+
+ // clear this word's result set
+ indexes2.erase(indexes2.begin(), indexes2.end());
+ error = 0;
+
+ // iterate thru every word in the database that starts
+ // with our search word
+ for (int away = 0; !error; away++) {
+ idxbuf = 0;
+
+ // find our word in the database and jump ahead _away_
+ error = fastSearch[j]->findoffset(words[i], &start, &size, away);
+
+ // get the word from the database
+ fastSearch[j]->getidxbufdat(start, &idxbuf);
+
+ // check to see if it starts with our target word
+ if (strlen(idxbuf) > strlen(words[i]))
+ idxbuf[strlen(words[i])] = 0;
+// else words[i][strlen(idxbuf)] = 0;
+ if (!strcmp(idxbuf, words[i])) {
+
+ // get data for this word from database
+ free(idxbuf);
+ idxbuf = 0;
+ datbuf = 0;
+ fastSearch[j]->readtext(start, &size, &idxbuf, &datbuf);
+
+ // we know that the data consists of sizof(long)
+ // records each a valid module position that constains
+ // this word
+ //
+ // iterate thru each of these module positions
+ long *keyindex = (long *)datbuf;
+ while (keyindex < (long *)(datbuf + size - (strlen(idxbuf) + 1))) {
+ if (i) { // if we're not on our first word
+
+ // check to see if this word is already in the result set.
+ // This is our AND functionality
+ if (find(indexes.begin(), indexes.end(), *keyindex) != indexes.end())
+ // add to new result set
+ indexes2.push_back(*keyindex);
+ }
+ else indexes2.push_back(*keyindex);
+ keyindex++;
+ }
+ free(datbuf);
+ }
+ else error = 1; // no more matches
+ free(idxbuf);
+ }
+
+ // make new result set final result set
+ indexes = indexes2;
+
+ percent((char)(20 + (float)((j*wordCount)+i)/(wordCount * 2) * 78), percentUserData);
+ }
+
+ // indexes contains our good verses, lets return them in a listkey
+ indexes.sort();
+
+ // iterate thru each good module position that meets the search
+ for (list <long>::iterator it = indexes.begin(); it != indexes.end(); it++) {
+
+ // set a temporary verse key to this module position
+ vk.Testament(j+1);
+ vk.Error();
+ vk.Index(*it);
+
+ // check scope
+ // Try to set our scope key to this verse key
+ if (scope) {
+ *testKeyType = vk;
+
+ // check to see if it set ok and if so, add to our return list
+ if (*testKeyType == vk)
+ listkey << (const char *) vk;
+ }
+ else listkey << (const char*) vk;
+ }
+ }
+ (*percent)(98, percentUserData);
+
+ free(words);
+ free(wordBuf);
+
+ *testKeyType = saveKey; // set current place back to original
+
+ listkey = TOP;
+ (*percent)(100, percentUserData);
+ return listkey;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ // check if we just want to see if search is supported
+ if (justCheckIfSupported) {
+ *justCheckIfSupported = false;
+ return listkey;
+ }
+
+ // if we don't support this search, fall back to base class
+ return SWModule::Search(istr, searchType, flags, scope, justCheckIfSupported, percent, percentUserData);
+}
+
+
+void RawText::setEntry(const char *inbuf, long len) {
+ VerseKey *key = 0;
+ // see if we have a VerseKey * or decendant
+ try {
+ key = SWDYNAMIC_CAST(VerseKey, this->key);
+ }
+ catch ( ... ) {}
+ // if we don't have a VerseKey * decendant, create our own
+ if (!key)
+ key = new VerseKey(this->key);
+
+ settext(key->Testament(), key->Index(), inbuf, len);
+
+ if (this->key != key) // free our key if we created a VerseKey
+ delete key;
+}
+
+
+void RawText::linkEntry(const SWKey *inkey) {
+ VerseKey *destkey = 0;
+ const VerseKey *srckey = 0;
+ // see if we have a VerseKey * or decendant
+ try {
+ destkey = SWDYNAMIC_CAST(VerseKey, this->key);
+ }
+ catch ( ... ) {}
+ // if we don't have a VerseKey * decendant, create our own
+ if (!destkey)
+ destkey = new VerseKey(this->key);
+
+ // see if we have a VerseKey * or decendant
+ try {
+ srckey = SWDYNAMIC_CAST(VerseKey, inkey);
+ }
+ catch ( ... ) {}
+ // if we don't have a VerseKey * decendant, create our own
+ if (!srckey)
+ srckey = new VerseKey(inkey);
+
+ linkentry(destkey->Testament(), destkey->Index(), srckey->Index());
+
+ if (this->key != destkey) // free our key if we created a VerseKey
+ delete destkey;
+
+ if (inkey != srckey) // free our key if we created a VerseKey
+ delete srckey;
+}
+
+
+/******************************************************************************
+ * RawText::deleteEntry - deletes this entry
+ *
+ * RET: *this
+ */
+
+void RawText::deleteEntry() {
+
+ VerseKey *key = 0;
+
+ try {
+ key = SWDYNAMIC_CAST(VerseKey, this->key);
+ }
+ catch ( ... ) {}
+ if (!key)
+ key = new VerseKey(this->key);
+
+ settext(key->Testament(), key->Index(), "");
+
+ if (key != this->key)
+ delete key;
+}
+
+/******************************************************************************
+ * RawText::increment - Increments module key a number of entries
+ *
+ * ENT: increment - Number of entries to jump forward
+ *
+ * RET: *this
+ */
+
+void RawText::increment(int steps) {
+ long start;
+ unsigned short size;
+ VerseKey *tmpkey = 0;
+
+ try {
+ tmpkey = SWDYNAMIC_CAST(VerseKey, key);
+ }
+ catch ( ... ) {}
+ if (!tmpkey)
+ tmpkey = new VerseKey(key);
+
+ findoffset(tmpkey->Testament(), tmpkey->Index(), &start, &size);
+
+ SWKey lastgood = *tmpkey;
+ while (steps) {
+ long laststart = start;
+ unsigned short lastsize = size;
+ SWKey lasttry = *tmpkey;
+ (steps > 0) ? (*key)++ : (*key)--;
+ if (tmpkey != key)
+ delete tmpkey;
+ tmpkey = 0;
+ try {
+ tmpkey = SWDYNAMIC_CAST(VerseKey, key);
+ }
+ catch ( ... ) {}
+ if (!tmpkey)
+ tmpkey = new VerseKey(key);
+
+ if ((error = key->Error())) {
+ *key = lastgood;
+ break;
+ }
+ long index = tmpkey->Index();
+ findoffset(tmpkey->Testament(), index, &start, &size);
+ 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;
+
+ if (tmpkey != key)
+ delete tmpkey;
+}
diff --git a/src/modules/texts/rawtext/rawtxidx.c b/src/modules/texts/rawtext/rawtxidx.c
new file mode 100644
index 0000000..311103e
--- /dev/null
+++ b/src/modules/texts/rawtext/rawtxidx.c
@@ -0,0 +1,146 @@
+#include <stdio.h>
+#include <fcntl.h>
+
+
+char findbreak(int fp, int *offset, int *num1, int *num2, short *size);
+
+
+main(int argc, char **argv)
+{
+ int fp, vfp, cfp, bfp;
+ long pos;
+ short size, tmp;
+ int num1, num2, offset, curbook = 0, curchap = 0, curverse = 0;
+ char buf[127];
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <file to process>\n", argv[0]);
+ exit(1);
+ }
+
+ if ((fp = open(argv[1], O_RDONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.vss", argv[1]);
+ if ((vfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.cps", argv[1]);
+ if ((cfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.bks", argv[1]);
+ if ((bfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ pos = 0;
+ write(bfp, &pos, 4); /* Book offset for testament intros */
+ pos = 4;
+ write(cfp, &pos, 4); /* Chapter offset for testament intro */
+
+
+/* Right now just zero out intros until parsing correctly */
+ pos = 0;
+ size = 0;
+ write(vfp, &pos, 4); /* Module intro */
+ write(vfp, &size, 2);
+ write(vfp, &pos, 4); /* Testament intro */
+ write(vfp, &size, 2);
+
+ while (!findbreak(fp, &offset, &num1, &num2, &size)) {
+
+ if (num2 == 1) { /* if we're at a new chapter */
+ if (num1 == 1) { /* if we're at a new book */
+ pos = lseek(cfp, 0, SEEK_CUR);
+ write(bfp, &pos, 4);
+ pos = lseek(vfp, 0, SEEK_CUR); /* Book intro (cps) */
+ write(cfp, &pos, 4);
+ pos = 0;
+ tmp = 0;
+ write(vfp, &pos, 4); /* Book intro (vss) */
+ write(vfp, &tmp, 2);
+ curbook++;
+ curchap = 0;
+ }
+ pos = lseek(vfp, 0, SEEK_CUR);
+ write(cfp, &pos, 4);
+ curverse = 1;
+ pos = 0;
+ tmp = 0;
+ write(vfp, &pos, 4); /* Chapter intro */
+ write(vfp, &tmp, 2);
+ curchap++;
+ }
+ else curverse++;
+
+ printf("%2d:%3d:%3d found at offset: %7d\n", curbook, num1, num2, offset);
+
+ if (num1 != curchap) {
+ fprintf(stderr, "Error: Found chaptures out of sequence\n", buf);
+ break;
+ }
+ if (num2 != curverse) {
+ fprintf(stderr, "Error: Found verses out of sequence\n", buf);
+ break;
+ }
+ write(vfp, &offset, 4);
+ write(vfp, &size, 2);
+ }
+
+ close(vfp);
+ close(cfp);
+ close(bfp);
+ close(fp);
+}
+
+
+char findbreak(int fp, int *offset, int *num1, int *num2, short *size)
+{
+ char buf[7];
+ char buf2[7];
+ char loop;
+ int offset2, ch2, vs2;
+
+ memset(buf, ' ', 7);
+
+ while (1) {
+ if (buf[3] == ':') {
+ memcpy(buf2, buf, 7);
+ for (loop = 0; loop < 7; loop++) {
+ if (!isdigit(buf2[loop]))
+ buf2[loop] = ' ';
+ }
+ buf2[3] = 0;
+ *num1 = atoi(buf2);
+ *num2 = atoi(&buf2[4]);
+ if (*num1 && *num2) {
+ *offset = lseek(fp, 0, SEEK_CUR);
+ sprintf(buf2, "%d", *num2);
+ *offset -= 2 - strlen(buf2);
+ if (size) {
+ if (findbreak(fp, &offset2, &ch2, &vs2, 0)) {
+ *size = (short) (lseek(fp, 0, SEEK_END) - (*offset));
+ }
+ else {
+ sprintf(buf2, "%d:%d", ch2, vs2);
+ *size = (offset2 - (*offset)) - (strlen(buf2) + 2);
+ }
+ lseek(fp, *offset, SEEK_SET);
+ }
+ return 0;
+ }
+ }
+ memmove(buf, &buf[1], 6);
+ if (read(fp, &buf[6], 1) != 1)
+ return 1;
+ }
+}
+
diff --git a/src/modules/texts/rawtext/rtfidx.cpp b/src/modules/texts/rawtext/rtfidx.cpp
new file mode 100644
index 0000000..9fdb305
--- /dev/null
+++ b/src/modules/texts/rawtext/rtfidx.cpp
@@ -0,0 +1,164 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <versekey.h>
+
+
+char findbreak(int fp, int *offset, int *num1, int *num2, short *size);
+
+
+main(int argc, char **argv)
+{
+ int fp, vfp, cfp, bfp;
+ long pos;
+ short size, tmp;
+ int num1, num2, offset, curbook = 0, curchap = 0, curverse = 0;
+ char buf[127];
+ VerseKey mykey;
+
+ if ((argc < 2) || (argc > 3)) {
+ fprintf(stderr, "usage: %s <file to process> [nt]\n", argv[0]);
+ exit(1);
+ }
+
+ if ((fp = open(argv[1], O_RDONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.vss", argv[1]);
+ if ((vfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.cps", argv[1]);
+ if ((cfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.bks", argv[1]);
+ if ((bfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ pos = 0;
+ write(bfp, &pos, 4); /* Book offset for testament intros */
+ pos = 4;
+ write(cfp, &pos, 4); /* Chapter offset for testament intro */
+
+
+/* Right now just zero out intros until parsing correctly */
+ pos = 0;
+ size = 0;
+ write(vfp, &pos, 4); /* Module intro */
+ write(vfp, &size, 2);
+ write(vfp, &pos, 4); /* Testament intro */
+ write(vfp, &size, 2);
+
+ mykey = (argc == 3) ? "Matthew 1:1" : "Genesis 1:1";
+
+ while (!findbreak(fp, &offset, &num1, &num2, &size)) {
+ num1 = mykey.Chapter();
+ num2 = mykey.Verse();
+ if (num2 == 1) { /* if we're at a new chapter */
+ if (num1 == 1) { /* if we're at a new book */
+ pos = lseek(cfp, 0, SEEK_CUR);
+ write(bfp, &pos, 4);
+ pos = lseek(vfp, 0, SEEK_CUR); /* Book intro (cps) */
+ write(cfp, &pos, 4);
+ pos = 0;
+ tmp = 0;
+ write(vfp, &pos, 4); /* Book intro (vss) */
+ write(vfp, &tmp, 2);
+ curbook++;
+ curchap = 0;
+ }
+ pos = lseek(vfp, 0, SEEK_CUR);
+ write(cfp, &pos, 4);
+ curverse = 1;
+ pos = 0;
+ tmp = 0;
+ write(vfp, &pos, 4); /* Chapter intro */
+ write(vfp, &tmp, 2);
+ curchap++;
+ }
+ else curverse++;
+
+ printf("%2d:%3d:%3d found at offset: %7d\n", curbook, num1, num2, offset);
+
+ if (num1 != curchap) {
+ fprintf(stderr, "Error: Found chaptures out of sequence\n");
+ break;
+ }
+ if (num2 != curverse) {
+ fprintf(stderr, "Error: Found verses out of sequence\n");
+ break;
+ }
+ write(vfp, &offset, 4);
+ write(vfp, &size, 2);
+ mykey++;
+ }
+
+ close(vfp);
+ close(cfp);
+ close(bfp);
+ close(fp);
+}
+
+
+char findbreak(int fp, int *offset, int *num1, int *num2, short *size)
+{
+ char buf[17];
+ char buf2[7];
+ char loop;
+ char offadj, inquotes, sizeadj;
+ int offset2, ch2, vs2;
+
+ memset(buf, ' ', 17);
+
+ while (1) {
+ offadj = -10;
+ inquotes = 0;
+ sizeadj = 0;
+ if (!memcmp(&buf[1], "\\f0\\fs16\\cf2\\up6", 15)) {
+ offadj = 0;
+ inquotes = 1;
+ sizeadj = (*buf == 10) ? -19:-17;
+ }
+ if (!memcmp(buf, "\\fi200\\widctlpar", 16)) {
+ offadj = -1;
+// inquotes = 1;
+ sizeadj = -18;
+ }
+ if (offadj > -10) {
+ *offset = lseek(fp, 0, SEEK_CUR) + offadj;
+ if (size) {
+ (*offset)++;
+ while (inquotes) {
+ while (read(fp, buf2, 1) == 1) {
+ if (*buf2 == '}')
+ break;
+ (*offset)++;
+ }
+ inquotes--;
+ }
+ if (findbreak(fp, &offset2, &ch2, &vs2, 0)) {
+ *size = (short) (lseek(fp, 0, SEEK_END) - (*offset));
+ }
+ else {
+ sprintf(buf2, "%d:%d", ch2, vs2);
+ *size = (offset2 - (*offset));
+ }
+ lseek(fp, *offset+17, SEEK_SET);
+ }
+ else (*offset) += sizeadj;
+ return 0;
+ }
+ memmove(buf, &buf[1], 16);
+ if (read(fp, &buf[16], 1) != 1)
+ return 1;
+ }
+}
+
diff --git a/src/modules/texts/rawtext/svetxidx.c b/src/modules/texts/rawtext/svetxidx.c
new file mode 100644
index 0000000..26e67fd
--- /dev/null
+++ b/src/modules/texts/rawtext/svetxidx.c
@@ -0,0 +1,153 @@
+#include <stdio.h>
+#include <fcntl.h>
+#ifndef __GNUC__
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+
+char findbreak(int fd, long *offset, int *num1, int *num2, short *size);
+
+
+main(int argc, char **argv)
+{
+ int fd, vfd, cfd, bfd;
+ long pos, offset;
+ short size, tmp;
+ int num1, num2, curbook = 0, curchap = 0, curverse = 0;
+ char buf[127];
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <file to process>\n", argv[0]);
+ exit(1);
+ }
+#ifndef O_BINARY // O_BINARY is for Borland to be happy. If we're in GNU, just define it to a NULL mask
+#define O_BINARY 0
+#endif
+ if ((fd = open(argv[1], O_RDONLY|O_BINARY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.vss", argv[1]);
+ if ((vfd = open(buf, O_CREAT|O_WRONLY|O_BINARY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.cps", argv[1]);
+ if ((cfd = open(buf, O_CREAT|O_WRONLY|O_BINARY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.bks", argv[1]);
+ if ((bfd = open(buf, O_CREAT|O_WRONLY|O_BINARY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ pos = 0;
+ write(bfd, &pos, 4); /* Book offset for testament intros */
+ pos = 4;
+ write(cfd, &pos, 4); /* Chapter offset for testament intro */
+
+
+/* Right now just zero out intros until parsing correctly */
+ pos = 0;
+ size = 0;
+ write(vfd, &pos, 4); /* Module intro */
+ write(vfd, &size, 2);
+ write(vfd, &pos, 4); /* Testament intro */
+ write(vfd, &size, 2);
+
+ while (!findbreak(fd, &offset, &num1, &num2, &size)) {
+
+ if (num2 == 1) { /* if we're at a new chapter */
+ if (num1 == 1) { /* if we're at a new book */
+ pos = lseek(cfd, 0, SEEK_CUR);
+ write(bfd, &pos, 4);
+ pos = lseek(vfd, 0, SEEK_CUR); /* Book intro (cps) */
+ write(cfd, &pos, 4);
+ pos = 0;
+ tmp = 0;
+ write(vfd, &pos, 4); /* Book intro (vss) */
+ write(vfd, &tmp, 2);
+ curbook++;
+ curchap = 0;
+ }
+ pos = lseek(vfd, 0, SEEK_CUR);
+ write(cfd, &pos, 4);
+ curverse = 1;
+ pos = 0;
+ tmp = 0;
+ write(vfd, &pos, 4); /* Chapter intro */
+ write(vfd, &tmp, 2);
+ curchap++;
+ }
+ else curverse++;
+
+ printf("%2d:%3d:%3d found at offset: %7ld\n", curbook, num1, num2, offset);
+
+ if (num1 != curchap) {
+ fprintf(stderr, "Error: Found chaptures out of sequence (%2d:%3d:%3d)\n", curbook, num1-1, num2);
+ curchap = num1;
+// break;
+ }
+ if (num2 != curverse) {
+ fprintf(stderr, "Error: Found verses out of sequence (%2d:%3d:%3d)\n", curbook, num1, num2-1);
+// break;
+ tmp = 0;
+ curverse = num2;
+ write(vfd, &offset, 4);
+ write(vfd, &tmp, 2);
+ }
+ write(vfd, &offset, 4);
+ write(vfd, &size, 2);
+ }
+
+ close(vfd);
+ close(cfd);
+ close(bfd);
+ close(fd);
+}
+
+
+char findbreak(int fd, long *offset, int *num1, int *num2, short *size)
+{
+ char buf[8];
+ char buf2[7];
+ char loop, len;
+
+ memset(buf, ' ', 7);
+ buf[7] = 0;
+
+ while (1) {
+
+ memmove(buf, &buf[1], 6);
+ if (read(fd, &buf[6], 1) != 1)
+ return 1;
+
+ if ((buf[0] == 10) && (isdigit(buf[1]))) {
+ sscanf(buf, "%d %s", num2, buf2);
+ if (!strncmp(buf2, "KAP", 3)) {
+ *num1 = *num2;
+ continue;
+ }
+ sprintf(buf, "%d", *num2);
+ (*offset) = lseek(fd, 0, SEEK_CUR);
+ (*offset) -= (5-strlen(buf));
+ for (len = 1; len == 1; len = read(fd, &loop, 1)) {
+ if ((loop == 10) || (loop == 13))
+ break;
+ }
+
+ *size = (short)(lseek(fd, 0, SEEK_CUR) - *offset) - 1;
+ lseek(fd, -1, SEEK_CUR);
+ break;
+ }
+ }
+ return 0;
+}
+
diff --git a/src/modules/texts/rawtext/vntidx.cpp b/src/modules/texts/rawtext/vntidx.cpp
new file mode 100644
index 0000000..bbb4a9e
--- /dev/null
+++ b/src/modules/texts/rawtext/vntidx.cpp
@@ -0,0 +1,185 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <versekey.h>
+
+
+char findbreak(int fp, int *offset, int *num1, int *num2, short *size);
+
+
+main(int argc, char **argv)
+{
+ int fp, vfp, cfp, bfp;
+ long pos;
+ short size, tmp;
+ int num1, num2, offset, curbook = 0, curchap = 0, curverse = 0;
+ char buf[127];
+ VerseKey mykey;
+
+ if ((argc < 2) || (argc > 3)) {
+ fprintf(stderr, "usage: %s <file to process> [nt]\n", argv[0]);
+ exit(1);
+ }
+
+ if ((fp = open(argv[1], O_RDONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.vss", argv[1]);
+ if ((vfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.cps", argv[1]);
+ if ((cfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.bks", argv[1]);
+ if ((bfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ pos = 0;
+ write(bfp, &pos, 4); /* Book offset for testament intros */
+ pos = 4;
+ write(cfp, &pos, 4); /* Chapter offset for testament intro */
+
+
+/* Right now just zero out intros until parsing correctly */
+ pos = 0;
+ size = 0;
+ write(vfp, &pos, 4); /* Module intro */
+ write(vfp, &size, 2);
+ write(vfp, &pos, 4); /* Testament intro */
+ write(vfp, &size, 2);
+
+ mykey = (argc == 3) ? "Matthew 1:1" : "Genesis 1:1";
+
+ while (!findbreak(fp, &offset, &num1, &num2, &size)) {
+ num1 = mykey.Chapter();
+ num2 = mykey.Verse();
+ if (num2 == 1) { /* if we're at a new chapter */
+ if (num1 == 1) { /* if we're at a new book */
+ pos = lseek(cfp, 0, SEEK_CUR);
+ write(bfp, &pos, 4);
+ pos = lseek(vfp, 0, SEEK_CUR); /* Book intro (cps) */
+ write(cfp, &pos, 4);
+ pos = 0;
+ tmp = 0;
+ write(vfp, &pos, 4); /* Book intro (vss) */
+ write(vfp, &tmp, 2);
+ curbook++;
+ curchap = 0;
+ }
+ pos = lseek(vfp, 0, SEEK_CUR);
+ write(cfp, &pos, 4);
+ curverse = 1;
+ pos = 0;
+ tmp = 0;
+ write(vfp, &pos, 4); /* Chapter intro */
+ write(vfp, &tmp, 2);
+ curchap++;
+ }
+ else curverse++;
+
+ printf("%2d:%3d:%3d found at offset: %7d\n", curbook, num1, num2, offset);
+
+ if (num1 != curchap) {
+ fprintf(stderr, "Error: Found chaptures out of sequence\n");
+ break;
+ }
+ if (num2 != curverse) {
+ fprintf(stderr, "Error: Found verses out of sequence\n");
+ break;
+ }
+ write(vfp, &offset, 4);
+ write(vfp, &size, 2);
+ mykey++;
+ }
+
+ close(vfp);
+ close(cfp);
+ close(bfp);
+ close(fp);
+}
+
+
+char findbreak(int fp, int *offset, int *num1, int *num2, short *size)
+{
+ char buf[17];
+ char buf2[7];
+ char buf3[7];
+ char loop;
+ char offadj, inquotes, sizeadj;
+ int offset2, ch2, vs2;
+
+ strcpy (buf3, "\\par ");
+ buf3[5] = 10;
+ memset(buf, ' ', 17);
+
+ while (1) {
+ offadj = -100;
+ inquotes = 0;
+ sizeadj = 0;
+ if (!memcmp(buf, "\\par FIN DEL NUEVO TESTAMENTO", 16)) {
+ offadj = -11;
+// inquotes = 1;
+ sizeadj = -7;
+ }
+
+ if ((!memcmp(buf, buf3, 6)) && (!size)) {
+ offadj = -11;
+// inquotes = 1;
+ sizeadj = -7;
+ }
+ if (!memcmp(buf, "\\par ", 6)) {
+ if (isdigit(buf[6])) {
+ for (loop = 7; loop < 10; loop++) {
+ if (!isdigit(buf[loop]))
+ break;
+ }
+ offadj = -(11 - (loop - 6));
+ // inquotes = 1;
+ sizeadj = -7;
+ }
+ }
+/*
+ if (!memcmp(buf, "\\fi200\\widctlpar", 16)) {
+ offadj = -1;
+// inquotes = 1;
+ sizeadj = -18;
+ }
+*/
+ if (offadj > -100) {
+ *offset = lseek(fp, 0, SEEK_CUR) + offadj;
+ if (size) {
+ (*offset)++;
+ while (inquotes) {
+ while (read(fp, buf2, 1) == 1) {
+ if (*buf2 == '}')
+ break;
+ (*offset)++;
+ }
+ inquotes--;
+ }
+ if (findbreak(fp, &offset2, &ch2, &vs2, 0)) {
+ *size = (short) (lseek(fp, 0, SEEK_END) - (*offset));
+ }
+ else {
+ *size = (offset2 - (*offset));
+ }
+ lseek(fp, *offset-sizeadj, SEEK_SET);
+ }
+ else (*offset) += sizeadj;
+ return 0;
+ }
+ memmove(buf, &buf[1], 16);
+ if (read(fp, &buf[16], 1) != 1)
+ return 1;
+ }
+}
+
diff --git a/src/modules/texts/swtext.cpp b/src/modules/texts/swtext.cpp
new file mode 100644
index 0000000..5f6b424
--- /dev/null
+++ b/src/modules/texts/swtext.cpp
@@ -0,0 +1,40 @@
+/******************************************************************************
+ * swtext.cpp - code for base class 'SWText'- The basis for all text modules
+ */
+
+#include <swtext.h>
+#include <listkey.h>
+
+
+/******************************************************************************
+ * SWText Constructor - Initializes data for instance of SWText
+ *
+ * ENT: imodname - Internal name for module
+ * imoddesc - Name to display to user for module
+ * idisp - Display object to use for displaying
+ */
+
+SWText::SWText(const char *imodname, const char *imoddesc, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang): SWModule(imodname, imoddesc, idisp, "Biblical Texts", enc, dir, mark, ilang)
+{
+ delete key;
+ key = CreateKey();
+ skipConsecutiveLinks = false;
+}
+
+
+/******************************************************************************
+ * SWText Destructor - Cleans up instance of SWText
+ */
+
+SWText::~SWText() {
+}
+
+
+/******************************************************************************
+ * SWText CreateKey - Create the correct key (VerseKey) for use with SWText
+ */
+
+SWKey *SWText::CreateKey()
+{
+ return new VerseKey();
+}
diff --git a/src/modules/texts/ztext/Makefile b/src/modules/texts/ztext/Makefile
new file mode 100644
index 0000000..35d6648
--- /dev/null
+++ b/src/modules/texts/ztext/Makefile
@@ -0,0 +1,5 @@
+
+root := ../../../..
+
+all:
+ make -C ${root}
diff --git a/src/modules/texts/ztext/Makefile.am b/src/modules/texts/ztext/Makefile.am
new file mode 100644
index 0000000..2b78db6
--- /dev/null
+++ b/src/modules/texts/ztext/Makefile.am
@@ -0,0 +1,4 @@
+ztextdir = $(top_srcdir)/src/modules/texts/ztext
+
+libsword_la_SOURCES += $(ztextdir)/ztext.cpp
+
diff --git a/src/modules/texts/ztext/gbfidx.cpp b/src/modules/texts/ztext/gbfidx.cpp
new file mode 100644
index 0000000..e7a9530
--- /dev/null
+++ b/src/modules/texts/ztext/gbfidx.cpp
@@ -0,0 +1,661 @@
+/*****************************************************************************
+ *
+ * This code reeks but works (sometimes). Good luck!
+ * Modified for zText purposes
+ */
+
+//#include <stdio.h>
+#include <iostream>
+#include <fstream>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+//#ifndef __GNUC__
+#include <io.h>
+//#else
+//#include <unistd.h>
+//#endif
+
+#include <fcntl.h>
+#include <versekey.h>
+
+
+void writeidx(VerseKey &key1, VerseKey &key2, VerseKey &key3, long offset, short size);
+char findbreak(int fp, long *offset, int *num1, int *num2, int *rangemax, unsigned short *size);
+void openfiles(char *fname);
+void checkparams(int argc, char **argv);
+
+
+VerseKey key1, key2, key3;
+int fp=0, vfp=0, cfp=0, bfp=0;
+long chapoffset=0;
+unsigned short chapsize=0;
+long bookoffset=0;
+unsigned short booksize=0;
+long testoffset=0;
+unsigned short testsize=0;
+long verseoffset=0;
+unsigned short versesize=0;
+long nextoffset=0;
+char testmnt=0;
+int deadcount = 0;
+int chapmark=-4, bookmark=-1;
+ofstream cfile;
+
+
+int main(int argc, char **argv)
+{
+ long pos, offset;
+ int num1, num2, rangemax;//, curbook = 0, curchap = 0, curverse = 0;
+ //char buf[127],
+ char startflag = 0;
+ unsigned short size;//, tmp;
+
+ checkparams(argc, argv);
+
+ openfiles(argv[1]);
+ //key1 = "Matthew 1:1";
+ //key2 = "Matthew 1:1";
+ //key3 = "Matthew 1:1";
+
+ testmnt = key1.Testament();
+ cfile << "testament" << (int) testmnt << "\n";
+ num1 = key1.Chapter();
+ num2 = key1.Verse();
+ pos = 0;
+ write(bfp, &pos, 4); /* Book offset for testament intros */
+ pos = 4;
+ write(cfp, &pos, 4); /* Chapter offset for testament intro */
+
+
+/* Right now just zero out intros until parsing correctly */
+ /*pos = 0;
+ size = 0;
+ write(vfp, &pos, 4); // Module intro
+ write(vfp, &size, 2);
+ cfile << "modintro pos{" << pos << "} size{" << size << "}\n";
+ write(vfp, &pos, 4); // Testament intro
+ write(vfp, &size, 2);
+ cfile << "test intro pos{" << pos << "} size{" << size << "}\n";
+ */
+ cout << "GBFIDX Running\n";
+ cout.flush();
+ while(!findbreak(fp, &offset, &num1, &num2, &rangemax, &size)) {
+ if (!startflag) {
+ startflag = 1;
+ }
+ else {
+ if (num2 < key2.Verse()) { // new chapter
+ if (num1 <= key2.Chapter()) { // new book
+ key2.Verse(1);
+ key2.Chapter(1);
+ key2.Book(key2.Book()+1);
+ }
+ cfile << "Found Chapter Break: " << num1 << " ('" << (const char *)key2 << "')\n";
+ //chapoffset = offset;
+ //chapsize = chapsize - size;
+// continue;
+ }
+ }
+ key2.Verse(1);
+ key2.Chapter(num1);
+ key2.Verse(num2);
+
+ key3 = key2;
+// key3 += (rangemax - key3.Verse());
+
+ writeidx(key1, key2, key3, offset, size);
+ }
+ close(vfp);
+ close(cfp);
+ close(bfp);
+ close(fp);
+
+ return 1;
+}
+
+
+/**************************************************************************
+ * writeidx: key1 - current location of index
+ * key2 - minimum keyval for which this offset is valid
+ * key3 - maximum keyval for which this offset is valid
+ */
+
+void writeidx(VerseKey &key1, VerseKey &key2, VerseKey &key3, long offset, short size)
+{
+ long pos;
+ unsigned short tmp;
+
+ for (; ((key1 <= key3) && (key1.Error() != KEYERR_OUTOFBOUNDS) && (key1.Testament() == testmnt)); key1+=1) {
+ if (chapmark>=2)
+ {
+ if (bookmark==2)
+ {
+ //booksize = booksize - chapsize + 7;
+ cfile << "versesize " << versesize << " booksize " << booksize << " chapsize " << chapsize << " size " << size << "\n";
+ //cfile.flush();
+ //assert(chapsize < size);
+ //if (chapsize > size) // At start of Psalms gets chapsize rather than chapsize+size ???
+ //{
+ // versesize = versesize - (booksize - (chapsize - size) + 7);
+ //}
+ //else
+ //{
+ versesize = versesize - (booksize - (chapsize) + 7);
+ //}
+ cfile << "Last verse in book\n";
+ }
+ //chapsize = chapsize - size;
+ cfile << "versesize " << versesize << " chapsize " << chapsize << " size " << size<< "\n";
+ cfile.flush();
+ //assert(chapsize > size);
+ //if (chapsize > size) // At start of Psalms gets chapsize rather than chapsize+size ???
+ //{
+ // versesize = versesize - (chapsize - size);
+ //}
+ //else
+ //{
+ versesize = versesize - (chapsize);
+ //}
+ cfile << "Last verse in chapter\n";
+ }
+ if (chapmark>=2 && bookmark!=1)
+ {
+ cfile << "prev verse pos{" << verseoffset << "} size{" << versesize << "} nextoffset{" << nextoffset << "}\n";
+ cfile.flush();
+ assert(verseoffset==nextoffset);
+ write(vfp, &verseoffset, 4);
+ write(vfp, &versesize, 2);
+ nextoffset = verseoffset+versesize;
+ bookmark = 0;
+ chapmark = 0;
+ }
+ if (key1.Verse() == 1) { // new chapter
+ cfile << "size??? " << size << "\n";
+ cfile.flush();
+ //assert(chapsize > size || key1.Chapter()==1);
+ //assert(chapsize > size);
+ //if (chapsize > size) // At start of books gets chapsize rather than chapsize+size
+ //{
+ // chapsize = chapsize - size;
+ //}
+ if (key1.Chapter() == 1) { // new book
+ booksize = booksize - chapsize + 7;
+ if (key1.Book() == 1)
+ {
+ pos = 0;
+ //tmp = testoffset;
+ tmp = 0; // better just remember that it goes up to the testament intro to avoid 64k limit
+ // AV exceeds that anyway!
+ write(vfp, &pos, 4); /* Module intro */
+ write(vfp, &tmp, 2);
+ assert(nextoffset==0);
+ cfile << "modintro pos{" << pos << "} size{" << tmp << "}\n";
+ testsize = testsize - booksize - chapsize + 7;
+ if (testsize > 10000)
+ {
+ cerr << "Error: testament too big " << testsize << "\n";
+ exit(-1);
+ }
+ //assert(testoffset==nextoffset);
+ write(vfp, &testoffset, 4); /* Testament intro (vss) */
+ write(vfp, &testsize, 2);
+ nextoffset = testoffset+testsize;
+ cfile << "test intro pos{" << testoffset << "} size{" << testsize << "}\n";
+ }
+ pos = lseek(cfp, 0, SEEK_CUR);
+ write(bfp, &pos, 4);
+ pos = lseek(vfp, 0, SEEK_CUR); /* Book intro (cps) */
+ write(cfp, &pos, 4);
+ if (booksize > 10000)
+ {
+ cerr << "Error: book too big " << booksize << "\n";
+ exit(-1);
+ }
+ assert(bookoffset==nextoffset);
+ write(vfp, &bookoffset, 4); /* Book intro (vss) */
+ write(vfp, &booksize, 2);
+ nextoffset = bookoffset+booksize;
+ cfile << "book intro pos{" << bookoffset << "} size{" << booksize << "}\n";
+ //offset += booksize;
+ //bookmark = false;
+ }
+ pos = lseek(vfp, 0, SEEK_CUR);
+ write(cfp, &pos, 4);
+ assert(chapsize < 10000);
+ write(vfp, &chapoffset, 4); /* Chapter intro */
+ write(vfp, &chapsize, 2);
+ nextoffset = chapoffset+chapsize;
+ cfile << "chapter intro pos{" << chapoffset << "} size{" << chapsize << "}\n";
+ //offset += chapsize;
+ //size -= chapsize;
+ //chapmark = false;
+ }
+ if (key1 >= key2) {
+ if (size > 10000)
+ {
+ cerr << "Error: verse too big " << size << "\n";
+ exit(-1);
+ }
+ if (!chapmark && !bookmark)
+ {
+ write(vfp, &offset, 4);
+ write(vfp, &size, 2);
+ cfile << "verse pos{" << offset << "} size{" << size << "}\n";
+ cfile.flush();
+ assert(offset==nextoffset);
+ nextoffset = offset+size;
+ //cfile << "bookmark " << bookmark << " chapmark " << chapmark << "\n";
+ }
+ else
+ {
+ verseoffset = offset;
+ versesize = size;
+ cfile << "saving verse pos{" << offset << "} size{" << size << "}\n";
+ cfile << "bookmark " << bookmark << " chapmark " << chapmark << "\n";
+ }
+ }
+ else {
+ pos = 0;
+ tmp = 0;
+ write(vfp, &pos, 4);
+ write(vfp, &tmp, 2);
+ cfile << "blank pos{" << pos << "} size{" << tmp << "}\n";
+ }
+ }
+}
+
+char startmod(char *buf)
+{
+ //char loop;
+
+ if (buf[0] != '<')
+ return 0;
+ if (buf[1] != 'H')
+ return 0;
+ if (buf[2] != '0')
+ return 0;
+/*
+ if (!isdigit(buf[2]))
+ return 0;
+ for (loop = 3; loop < 7; loop++) {
+ if (buf[loop] == ' ')
+ break;
+ if ((!isdigit(buf[loop])) && (buf[loop] != ',') && (buf[loop] != '-'))
+ return 0;
+ }
+*/
+ return 1;
+}
+
+
+char starttest(char *buf)
+{
+ //char loop;
+
+ if (buf[0] != '<')
+ return 0;
+ if (buf[1] != 'B')
+ return 0;
+ if (testmnt==2)
+ {
+ if (buf[2] != 'N')
+ return 0;
+ }
+ else
+ {
+ if (buf[2] != 'O')
+ return 0;
+ }
+ //if (buf[3] != '>')
+ // return 0;
+/*
+ if (!isdigit(buf[2]))
+ return 0;
+ for (loop = 3; loop < 7; loop++) {
+ if (buf[loop] == ' ')
+ break;
+ if ((!isdigit(buf[loop])) && (buf[loop] != ',') && (buf[loop] != '-'))
+ return 0;
+ }
+*/
+ return 1;
+}
+
+
+char startbook(char *buf)
+{
+ //char loop;
+
+ if (buf[0] != '<')
+ return 0;
+ if (buf[1] != 'S')
+ return 0;
+ if (buf[2] != 'B')
+ return 0;
+/*
+ if (!isdigit(buf[2]))
+ return 0;
+ for (loop = 3; loop < 7; loop++) {
+ if (buf[loop] == ' ')
+ break;
+ if ((!isdigit(buf[loop])) && (buf[loop] != ',') && (buf[loop] != '-'))
+ return 0;
+ }
+*/
+ return 1;
+}
+
+
+char startchap(char *buf)
+{
+ //char loop;
+
+ if (buf[0] != '<')
+ return 0;
+ if (buf[1] != 'S')
+ return 0;
+ if (buf[2] != 'C')
+ return 0;
+/*
+ if (!isdigit(buf[2]))
+ return 0;
+ for (loop = 3; loop < 7; loop++) {
+ if (buf[loop] == ' ')
+ break;
+ if ((!isdigit(buf[loop])) && (buf[loop] != ',') && (buf[loop] != '-'))
+ return 0;
+ }
+*/
+ return 1;
+}
+
+
+char startentry(char *buf)
+{
+ //char loop;
+ //cfile << "{SV}";
+
+ if (buf[0] != '<')
+ {
+ //cfile << "{no<}";
+ return 0;
+ }
+ if (buf[1] != 'S')
+ {
+ //cfile << "\n{noS}\n";
+ return 0;
+ }
+ if (buf[2] != 'V')
+ {
+ //cfile << "\n{noV}\n";
+ return 0;
+ }
+/*
+ if (!isdigit(buf[2]))
+ return 0;
+ for (loop = 3; loop < 7; loop++) {
+ if (buf[loop] == ' ')
+ break;
+ if ((!isdigit(buf[loop])) && (buf[loop] != ',') && (buf[loop] != '-'))
+ return 0;
+ }
+*/
+ return 1;
+}
+
+
+char findbreak(int fp, long *offset, int *num1, int *num2, int *rangemax, unsigned short *size)
+{
+ char buf[8];
+ //char buf2[20];
+ //char ch;
+ char loop=0;
+ long offset2;
+ int ch2, vs2, rm2;
+ bool flag;
+ long versestart = 0;
+ long chapstart = 0;
+ long bookstart = 0;
+ long teststart = 0;
+
+ memset(buf, ' ', 8);
+
+ while (1) {
+ //cfile << "#" << buf << "#";
+ //if (lseek(fp, 0, SEEK_CUR) > 2000000)
+ //{
+ // cfile << lseek(fp, 0, SEEK_CUR) << "\n";
+ //}
+ if (starttest(buf)) {
+ cfile << "\n{start of testament}\n";
+ //chapstart = lseek(fp, 0, SEEK_CUR) - 7;
+ teststart = lseek(fp, 0, SEEK_CUR) - 7;
+ testoffset = teststart;
+ memset(buf, ' ', 3);
+ flag = false;
+ for (loop = 3; loop < 6; loop++) {
+ if (buf[loop]!='>')
+ flag = true;
+ else {
+ buf[loop] = 0;
+ break;
+ }
+ }
+ ch2 = *num1;
+ vs2 = 1;
+ if (size) {
+ if (findbreak(fp, &offset2, &ch2, &vs2, &rm2, 0)) {
+ testsize = (unsigned short) (lseek(fp, 0, SEEK_END) - teststart-7);
+ }
+ else {
+ if (vs2) {
+ testsize = (offset2 - teststart - 7);
+ }
+ }
+ lseek(fp, teststart+7, SEEK_SET);
+ cfile << "\nGot testsize " << testsize << "\n";
+ }
+ }
+
+
+ if (startbook(buf)) {
+ cfile << "\n{start of book}\n";
+ bookmark++;
+ //chapstart = lseek(fp, 0, SEEK_CUR) - 7;
+ bookstart = lseek(fp, 0, SEEK_CUR) - 7;
+ bookoffset = bookstart;
+ memset(buf, ' ', 3);
+ flag = false;
+ for (loop = 3; loop < 6; loop++) {
+ if (buf[loop]!='>')
+ flag = true;
+ else {
+ buf[loop] = 0;
+ break;
+ }
+ }
+ if (size) {
+ ch2 = *num1;
+ vs2 = 1;
+ if (findbreak(fp, &offset2, &ch2, &vs2, &rm2, 0)) {
+ booksize = (unsigned short) (lseek(fp, 0, SEEK_END) - bookstart - 7);
+ }
+ else {
+ if (vs2) {
+ booksize = (offset2 - bookstart - 7);
+ }
+ }
+ lseek(fp, bookstart+7, SEEK_SET);
+ cfile << "\nGot booksize " << booksize << "\n";
+ }
+ }
+
+ if (startchap(buf)) {
+ cfile << "{start of chapter}";
+ chapmark++;
+ //chapstart = lseek(fp, 0, SEEK_CUR) - 7;
+ chapstart = lseek(fp, 0, SEEK_CUR) - 7;
+ chapoffset = chapstart;
+ memset(buf, ' ', 3);
+ flag = false;
+ for (loop = 3; loop < 6; loop++) {
+ if (isdigit(buf[loop]))
+ flag = true;
+ else {
+ buf[loop] = 0;
+ break;
+ }
+ }
+ if (flag)
+ *num1 = atoi(buf);
+ else (*num1)++;
+
+ if (size) {
+ ch2 = *num1;
+ vs2 = 1;
+ lseek(fp, chapstart, SEEK_SET);
+ if (findbreak(fp, &offset2, &ch2, &vs2, &rm2, 0)) {
+ chapsize = (unsigned short) (lseek(fp, 0, SEEK_END) - chapstart);
+ cfile << "getting chapsizeend{" << chapsize << "} = " << lseek(fp, 0, SEEK_END) << " - " << chapstart << "\n";
+ }
+ else {
+ if (vs2) {
+ chapsize = (offset2 - chapstart);
+ cfile << "getting chapsize{" << chapsize << "} = " << offset2 << " - " << chapstart << "\n";
+ }
+ }
+ lseek(fp, chapstart + 7, SEEK_SET);
+ cfile << "\nGot chapsize " << chapsize << " loop{" << (int) loop << "}\n";
+ }
+ //return 0;
+
+ }
+ if (startentry(buf)) {
+ //cfile << "{start of verse}";
+ memset(buf, ' ', 3);
+ flag = false;
+ for (loop = 3; loop < 6; loop++) {
+ if (isdigit(buf[loop]))
+ flag = true;
+ else {
+ buf[loop] = 0;
+ break;
+ }
+ if (flag)
+ *num2 = atoi(buf);
+ else (*num2)++;
+ }
+ loop++;
+ /*
+ if (size)
+ {
+ // *offset = lseek(fp, 0, SEEK_CUR) - (7 - loop);
+ *offset = lseek(fp, 0, SEEK_CUR) - 7;
+ }
+ //else *offset = (chapstart) ? chapstart : lseek(fp, 0, SEEK_CUR) - 7;
+ else *offset = (chapstart) ? chapstart : lseek(fp, 0, SEEK_CUR) - 7;
+ */
+ /*if (chapstart)
+ {
+ chapsize = *offset-chapstart;
+ }
+ else
+ {
+ chapsize = 0;
+ }*/
+ *offset = lseek(fp, 0, SEEK_CUR) - 7;
+ versestart = *offset;
+ if (size) {
+ ch2 = *num1;
+ vs2 = *num2;
+ if (findbreak(fp, &offset2, &ch2, &vs2, &rm2, 0)) {
+ *size = (unsigned short) (lseek(fp, 0, SEEK_END) - versestart);
+ cfile << "getting sizeend{" << *size << "} = " << lseek(fp, 0, SEEK_END) << " - " << versestart << "\n";
+ }
+ else {
+ if (vs2) {
+ *size = (offset2 - versestart);
+ cfile << "getting size{" << *size << "} = " << offset2 << " - " << versestart << "\n";
+ }
+ }
+ lseek(fp, *offset+1, SEEK_SET);
+ }
+ else
+ {
+ cfile << "got offset{" << *offset << "}\n";
+ }
+ return 0;
+ }
+ //cfile << "{ng}";
+ //deadcount++;
+ //if (deadcount==1000) exit(-1);
+ //if (!size)
+ //{
+ // cfile << "not bound offset{" << *offset << "}\n";
+ //}
+ memmove(buf, &buf[1], 6);
+ if (read(fp, &buf[6], 1) != 1)
+ return 1;
+ }
+}
+
+
+void openfiles(char *fname)
+{
+#ifndef O_BINARY // O_BINARY is needed in Borland C++ 4.53
+#define O_BINARY 0 // If it hasn't been defined than we probably
+#endif // don't need it.
+ char buf[255];
+
+ if ((fp = open(fname, O_RDONLY|O_BINARY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", fname);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.vss", fname);
+ if ((vfp = open(buf, O_CREAT|O_WRONLY|O_BINARY|O_TRUNC)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.cps", fname);
+ if ((cfp = open(buf, O_CREAT|O_WRONLY|O_BINARY|O_TRUNC)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.bks", fname);
+ if ((bfp = open(buf, O_CREAT|O_WRONLY|O_BINARY|O_TRUNC)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+ cfile.open("gbfidx.log", ios::out);
+ if (!cfile.is_open())
+ {
+ cerr << "Failed to open log file\n";
+ exit(-1);
+ }
+}
+
+
+void checkparams(int argc, char **argv)
+{
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s <file to process> [nt - for new testmt file]\n", argv[0]);
+ exit(1);
+ }
+ if (!strcmp(argv[1], "nt"))
+ key1 = key2 = key3 = "Matthew 1:1";
+ else if (!strcmp(argv[1], "ot"))
+ {
+ key1 = key2 = key3 = "Genesis 1:1";
+ }
+ else
+ {
+ cerr << "File must be ot or nt\n";
+ exit(-1);
+ }
+}
diff --git a/src/modules/texts/ztext/makeidx.c b/src/modules/texts/ztext/makeidx.c
new file mode 100644
index 0000000..311103e
--- /dev/null
+++ b/src/modules/texts/ztext/makeidx.c
@@ -0,0 +1,146 @@
+#include <stdio.h>
+#include <fcntl.h>
+
+
+char findbreak(int fp, int *offset, int *num1, int *num2, short *size);
+
+
+main(int argc, char **argv)
+{
+ int fp, vfp, cfp, bfp;
+ long pos;
+ short size, tmp;
+ int num1, num2, offset, curbook = 0, curchap = 0, curverse = 0;
+ char buf[127];
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <file to process>\n", argv[0]);
+ exit(1);
+ }
+
+ if ((fp = open(argv[1], O_RDONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", argv[1]);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.vss", argv[1]);
+ if ((vfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.cps", argv[1]);
+ if ((cfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ sprintf(buf, "%s.bks", argv[1]);
+ if ((bfp = open(buf, O_CREAT|O_WRONLY)) == -1) {
+ fprintf(stderr, "Couldn't open file: %s\n", buf);
+ exit(1);
+ }
+
+ pos = 0;
+ write(bfp, &pos, 4); /* Book offset for testament intros */
+ pos = 4;
+ write(cfp, &pos, 4); /* Chapter offset for testament intro */
+
+
+/* Right now just zero out intros until parsing correctly */
+ pos = 0;
+ size = 0;
+ write(vfp, &pos, 4); /* Module intro */
+ write(vfp, &size, 2);
+ write(vfp, &pos, 4); /* Testament intro */
+ write(vfp, &size, 2);
+
+ while (!findbreak(fp, &offset, &num1, &num2, &size)) {
+
+ if (num2 == 1) { /* if we're at a new chapter */
+ if (num1 == 1) { /* if we're at a new book */
+ pos = lseek(cfp, 0, SEEK_CUR);
+ write(bfp, &pos, 4);
+ pos = lseek(vfp, 0, SEEK_CUR); /* Book intro (cps) */
+ write(cfp, &pos, 4);
+ pos = 0;
+ tmp = 0;
+ write(vfp, &pos, 4); /* Book intro (vss) */
+ write(vfp, &tmp, 2);
+ curbook++;
+ curchap = 0;
+ }
+ pos = lseek(vfp, 0, SEEK_CUR);
+ write(cfp, &pos, 4);
+ curverse = 1;
+ pos = 0;
+ tmp = 0;
+ write(vfp, &pos, 4); /* Chapter intro */
+ write(vfp, &tmp, 2);
+ curchap++;
+ }
+ else curverse++;
+
+ printf("%2d:%3d:%3d found at offset: %7d\n", curbook, num1, num2, offset);
+
+ if (num1 != curchap) {
+ fprintf(stderr, "Error: Found chaptures out of sequence\n", buf);
+ break;
+ }
+ if (num2 != curverse) {
+ fprintf(stderr, "Error: Found verses out of sequence\n", buf);
+ break;
+ }
+ write(vfp, &offset, 4);
+ write(vfp, &size, 2);
+ }
+
+ close(vfp);
+ close(cfp);
+ close(bfp);
+ close(fp);
+}
+
+
+char findbreak(int fp, int *offset, int *num1, int *num2, short *size)
+{
+ char buf[7];
+ char buf2[7];
+ char loop;
+ int offset2, ch2, vs2;
+
+ memset(buf, ' ', 7);
+
+ while (1) {
+ if (buf[3] == ':') {
+ memcpy(buf2, buf, 7);
+ for (loop = 0; loop < 7; loop++) {
+ if (!isdigit(buf2[loop]))
+ buf2[loop] = ' ';
+ }
+ buf2[3] = 0;
+ *num1 = atoi(buf2);
+ *num2 = atoi(&buf2[4]);
+ if (*num1 && *num2) {
+ *offset = lseek(fp, 0, SEEK_CUR);
+ sprintf(buf2, "%d", *num2);
+ *offset -= 2 - strlen(buf2);
+ if (size) {
+ if (findbreak(fp, &offset2, &ch2, &vs2, 0)) {
+ *size = (short) (lseek(fp, 0, SEEK_END) - (*offset));
+ }
+ else {
+ sprintf(buf2, "%d:%d", ch2, vs2);
+ *size = (offset2 - (*offset)) - (strlen(buf2) + 2);
+ }
+ lseek(fp, *offset, SEEK_SET);
+ }
+ return 0;
+ }
+ }
+ memmove(buf, &buf[1], 6);
+ if (read(fp, &buf[6], 1) != 1)
+ return 1;
+ }
+}
+
diff --git a/src/modules/texts/ztext/nasb.cpp b/src/modules/texts/ztext/nasb.cpp
new file mode 100644
index 0000000..51e08b4
--- /dev/null
+++ b/src/modules/texts/ztext/nasb.cpp
@@ -0,0 +1,107 @@
+
+
+#include <ctype.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#ifndef __GNUC__
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <swcomprs.h>
+
+class FileCompress: public SWCompress {
+ int ifd;
+ int ofd;
+ int ufd;
+ int zfd;
+public:
+ FileCompress(char *);
+ ~FileCompress();
+ int GetChars(char *, int len);
+ int SendChars(char *, int len);
+ void Encode();
+ void Decode();
+};
+
+
+FileCompress::FileCompress(char *fname)
+{
+ char buf[256];
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+ ufd = open(fname, O_RDWR|O_CREAT|O_BINARY);
+
+ sprintf(buf, "%s.zzz", fname);
+ zfd = open(buf, O_RDWR|O_CREAT|O_BINARY);
+}
+
+
+FileCompress::~FileCompress(char *fname)
+{
+ close(ufd);
+ close(zfd);
+}
+
+
+int FileCompress::GetChars(char *buf, int len)
+{
+ return read(ifd, buf, len);
+}
+
+
+int FileCompress::SendChars(char *buf, int len)
+{
+ return write(ofd, buf, len);
+}
+
+
+void FileCompress::Encode()
+{
+ ifd = ufd;
+ ofd = zfd;
+
+ SWCompress::Encode();
+}
+
+
+void FileCompress::Decode()
+{
+ ifd = zfd;
+ ofd = ufd;
+
+ SWCompress::Decode();
+}
+
+
+main(int argc, char **argv)
+{
+ int decomp = 0;
+ SWCompress *fobj;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <filename|filename.zzz>\n", argv[0]);
+ exit(1);
+ }
+
+ if (strlen(argv[1]) > 4) {
+ if (!strcmp(&argv[1][strlen(argv[1])-4], ".zzz")) {
+ argv[1][strlen(argv[1])-4] = 0;
+ decomp = 1;
+ }
+ }
+
+ fobj = new FileCompress(argv[1]);
+
+ if (decomp)
+ fobj->Decode();
+ else fobj->Encode();
+
+ delete fobj;
+}
diff --git a/src/modules/texts/ztext/rawtxt2z.cpp b/src/modules/texts/ztext/rawtxt2z.cpp
new file mode 100644
index 0000000..7eafe2a
--- /dev/null
+++ b/src/modules/texts/ztext/rawtxt2z.cpp
@@ -0,0 +1,457 @@
+// Compression on variable granularity
+
+#include <fcntl.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#ifndef __GNUC__
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <zlib.h>
+#include <versekey.h>
+
+int iBufSize, ulBuffNum;
+ofstream cfile;
+ofstream cfile2;
+
+int ofd[2], oxfd[2], ovxfd[2];
+int ifd[2], ixfd[2];
+int itestfd[2], itestxfd[2];
+unsigned long ulIOff=0, ulCOff=0, ulFOff=0, ulNone=0;
+string currbuff="";
+
+
+int openreadfile(char *buffer, char *path, const char *filename)
+{
+ int filenum;
+ sprintf(buffer, "%s/%s", path, filename);
+ cfile << buffer << "\n";
+ filenum = open(buffer, O_RDONLY|O_BINARY);
+ if (filenum > 0)
+ {
+ return filenum;
+ }
+ else
+ {
+ cerr << "failed to open file to read\n";
+ exit(-1);
+ }
+}
+
+int openwritefile(char *buffer, char *path, const char *filename)
+{
+ int filenum;
+ sprintf(buffer, "%s/%s", path, filename);
+ cfile << buffer << "\n";
+ filenum = open(buffer, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC);
+ if (filenum > 0)
+ {
+ return filenum;
+ }
+ else
+ {
+ cerr << "failed to open file to read\n";
+ exit(-1);
+ }
+}
+
+int bytebound(unsigned long offset, VerseKey &thekey)
+{
+ unsigned long bufferoff;
+ cfile << "byteboundtest " << thekey << "\n";
+ bufferoff = iBufSize * (ulBuffNum+1);
+ if (offset > bufferoff)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int versebound(unsigned long offset, VerseKey &thekey)
+{
+ cfile << "verseboundtest " << thekey << "\n";
+ return 1;
+}
+
+int chapterbound(unsigned long offset, VerseKey &thekey)
+{
+ VerseKey testkey;
+ testkey = thekey;
+ testkey++;
+ //cfile << "chapterboundtest " << testkey;
+ if (testkey.Verse()==1 || (!thekey.compare("Revelation of John 22:21")))
+ {
+ //cfile << " 1\n";
+ return 1;
+ }
+ else
+ {
+ //cfile << " 0\n";
+ return 0;
+ }
+}
+
+int bookbound(unsigned long offset, VerseKey &thekey)
+{
+ VerseKey testkey;
+ testkey = thekey;
+ cfile << "bookboundtest " << testkey << "\n";
+ testkey++;
+ if (testkey.Chapter()==1 || (!thekey.compare("Revelation of John 22:21")))
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+typedef int (*boundfunc)(unsigned long offset, VerseKey &thekey);
+
+int writeblock(int i)
+{
+ char *destbuff=NULL;
+ unsigned long compsize = 0, buffsize=0;
+
+ cfile << "compressing block\n";
+ // compress current buffer
+ buffsize = currbuff.length();
+ write(itestfd[i], currbuff.c_str(), buffsize);
+ compsize = (unsigned long) (buffsize*1.01)+20; // at least 1% bigger than buffer + 12 bytes
+ //cfile << "{" << compsize << "}";
+ //destbuff = (char *) calloc(compsize + 1, 1);
+ destbuff = new char[compsize];
+ if (compress((Bytef*)destbuff, &compsize, (const Bytef*)currbuff.c_str(), buffsize)!=Z_OK)
+ {
+ cerr << "Could not compress buffer: exiting\n";
+ delete[] destbuff;
+ exit(-1);
+ }
+ //cout << "Compressed buffer{" << compsize << "}\n" << destbuff << "\n";
+ //cout.flush();
+ // write to compressed file index
+ ulCOff = lseek(ofd[i], 0, SEEK_END);
+ write(oxfd[i], &ulCOff, 4); // offset in compressed file
+ write(oxfd[i], &compsize, 4); // compressed size
+ write(oxfd[i], &buffsize, 4); // uncompressed size
+ cfile << buffsize << " -> " << compsize << "\n";
+ cfile2 << "Compressed{" << compsize << "}\n" << destbuff << "\n";
+ cfile2.flush();
+
+ //write compressed buffer to file
+ write(ofd[i], destbuff, compsize);
+
+ //free(destbuff);
+ delete[] destbuff;
+
+ currbuff = "";
+ ulBuffNum++;
+ ulIOff = 0;
+ return 1;
+}
+
+
+
+int main(int argc, char **argv)
+{
+ VerseKey key1, key2, key3;
+ int i;
+ char xbuff[64];
+ unsigned long offset;
+ unsigned short size=0;
+ unsigned long ulsize=0;
+ char *tmpbuf=NULL;
+ int iType;
+ boundfunc blockbound[4] = {bytebound, versebound, chapterbound, bookbound};
+ bool newbook=true, newchapter=true, newtestament = true, newmodule = true, lasttodo=true;
+
+ if ((argc < 2) || (argc > 4)) {
+ cerr << "usage: " << argv[0] << " datapath [compression type [buffer size]]\n";
+ exit(1);
+ }
+
+ if (argc>2)
+ {
+ iType = atoi(argv[2]);
+ if (argc==4)
+ {
+ iBufSize = atoi(argv[3]);
+ }
+ else
+ {
+ iBufSize = 1;
+ }
+ }
+ else
+ {
+ iType = 2;
+ iBufSize = 1;
+ }
+
+ cfile.open("raw2z.log", ios::out);
+ if (!cfile.is_open())
+ {
+ cerr << "Failed to open log file\n";
+ exit(-1);
+ }
+ cfile2.open("raw2z.lg2", ios::out);
+ if (!cfile2.is_open())
+ {
+ cerr << "Failed to open log file\n";
+ exit(-1);
+ }
+ cfile << iType << " " << iBufSize << "\n";
+
+ if ((iType<=0) || (iType > 4) || !iBufSize || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help") || !strcmp(argv[1], "/?") || !strcmp(argv[1], "-help"))
+ {
+ cfile << argv[0] << " - a tool to create compressed Sword modules\n";
+ cfile << "version 0.1\n\n";
+ cfile << "usage: "<< argv[0] << " datapath [compression type [buffer size]]\n\n";
+ cfile << "datapath: the directory in which to find the raw module\n";
+ cfile << "compression type: (default 2)\n" << " 1 - bytes\n" << " 2 - verses\n" << " 3 - chapters\n" << " 4 - books\n";
+ cfile << "buffer size (default 1): the number of the compression type in each block\n";
+ exit(1);
+ }
+
+ //zobj = new SWCompress();
+ //rawdrv = new RawVerse(argv[1]);
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+ cfile << "opening files\n";
+
+ tmpbuf = new char [ strlen(argv[1]) + 11 ];
+
+ //original files
+ ifd[0] = openreadfile(tmpbuf, argv[1], "ot");
+ ixfd[0] = openreadfile(tmpbuf, argv[1], "ot.vss");
+ ifd[1] = openreadfile(tmpbuf, argv[1], "nt");
+ ixfd[1] = openreadfile(tmpbuf, argv[1], "nt.vss");
+
+switch ( iType) {
+ case 1 :
+ ofd[0] = openwritefile(tmpbuf, argv[1], "ot.rzz");
+ oxfd[0] = openwritefile(tmpbuf, argv[1], "ot.rzs");
+ ovxfd[0] = openwritefile(tmpbuf, argv[1], "ot.rzv");
+ ofd[1] = openwritefile(tmpbuf, argv[1], "nt.rzz");
+ oxfd[1] = openwritefile(tmpbuf, argv[1], "nt.rzs");
+ ovxfd[1] = openwritefile(tmpbuf, argv[1], "nt.rzv");
+ //boundfunc = bytebound;
+ break;
+ case 2 :
+ ofd[0] = openwritefile(tmpbuf, argv[1], "ot.vzz");
+ oxfd[0] = openwritefile(tmpbuf, argv[1], "ot.vzs");
+ ovxfd[0] = openwritefile(tmpbuf, argv[1], "ot.vzv");
+ ofd[1] = openwritefile(tmpbuf, argv[1], "nt.vzz");
+ oxfd[1] = openwritefile(tmpbuf, argv[1], "nt.vzs");
+ ovxfd[1] = openwritefile(tmpbuf, argv[1], "nt.vzv");
+ break;
+ case 3 :
+ ofd[0] = openwritefile(tmpbuf, argv[1], "ot.czz");
+ oxfd[0] = openwritefile(tmpbuf, argv[1], "ot.czs");
+ ovxfd[0] = openwritefile(tmpbuf, argv[1], "ot.czv");
+ ofd[1] = openwritefile(tmpbuf, argv[1], "nt.czz");
+ oxfd[1] = openwritefile(tmpbuf, argv[1], "nt.czs");
+ ovxfd[1] = openwritefile(tmpbuf, argv[1], "nt.czv");
+ break;
+ case 4 :
+ ofd[0] = openwritefile(tmpbuf, argv[1], "ot.bzz");
+ oxfd[0] = openwritefile(tmpbuf, argv[1], "ot.bzs");
+ ovxfd[0] = openwritefile(tmpbuf, argv[1], "ot.bzv");
+ ofd[1] = openwritefile(tmpbuf, argv[1], "nt.bzz");
+ oxfd[1] = openwritefile(tmpbuf, argv[1], "nt.bzs");
+ ovxfd[1] = openwritefile(tmpbuf, argv[1], "nt.bzv");
+ break;
+ default:
+ cerr << "Unknown compression type\n";
+ exit(-1);
+}
+ itestfd[0] = openwritefile(tmpbuf, argv[1], "ot.tst");
+ itestfd[1] = openwritefile(tmpbuf, argv[1], "nt.tst");
+ itestxfd[0] = openwritefile(tmpbuf, argv[1], "ot.tdx");
+ itestxfd[1] = openwritefile(tmpbuf, argv[1], "nt.tdx");
+
+
+ delete [] tmpbuf;
+
+ //cfile << "about to start\n";
+
+for ( i=0; i<2; i++)
+{
+ ulIOff=0, ulBuffNum=0;
+ currbuff = "";
+ key1 = (i == 1) ? "Matthew 1:1" : "Genesis 1:1";
+ key2 = key3 = key1;
+ newtestament = true;
+
+ cfile << "key: " << key1 << " Testament {" << key1.Testament()-1 << "}\n";
+ //cfile << "Chapter {" << key.Chapter() << "}\n";
+ //cfile << "Verse {" << key.Verse() << "}\n";
+ //cfile << key.compare("Revelation of John 22:21") << "\n";
+ //cfile << key.compare("Genesis 1:1") << "\n";
+ do
+ {
+ //cfile << "ok";
+ // read current verse offset
+ if (read(ixfd[i], &offset, 4) != 4)
+ {
+ cfile << "Failed to read input verse offsets?\n";
+ break;
+ }
+ if (read(ixfd[i], &size, 2) != 2)
+ {
+ cfile << "Failed to read input verse sizes?\n";
+ break;
+ }
+ cfile << "key:" << key1 << " offset:" << offset << " size:" << size << "\n";
+ sprintf(xbuff, "key{%s} offset{%ld} size{%d}\n", (const char *)key1, offset, size);
+ write(itestxfd[i], &xbuff, strlen(xbuff));
+ ulsize = size;
+ if (!offset && !size)
+ {
+ //Check for module header
+ if (read(ixfd[i], &ulIOff, 4) != 4)
+ {
+ cfile << "Failed to read input verse offsets?\n";
+ break;
+ }
+ ulsize = ulIOff;
+ ulIOff = 0;
+ lseek(ixfd[i], 6, SEEK_SET);
+ }
+
+ if (ulsize)
+ {
+ // read current verse and add to current buffer
+ tmpbuf = (char *) calloc(ulsize + 1, 1);
+ lseek(ifd[i], offset, SEEK_SET);
+ read(ifd[i], tmpbuf, ulsize);
+ currbuff += tmpbuf;
+ //cfile << currbuff << "\n";
+
+ // write to verse index into compressed
+ write(ovxfd[i], &ulBuffNum, 4); // current buffer number
+ write(ovxfd[i], &ulIOff, 4); // offset within the buffer
+ write(ovxfd[i], &size, 2); // verse size
+
+ ulFOff = lseek(ofd[i], 0, SEEK_CUR) + size;
+ if (key1.compare("Revelation of John 22:21")!=-1)
+ {
+ lasttodo = false;
+ }
+ if (blockbound[iType-1](ulFOff, key1)/*at block boudary*/)
+ {
+ writeblock(i);
+ /*
+ cfile << "compressing block\n";
+ // compress current buffer
+ buffsize = currbuff.length();
+ write(itestfd[i], currbuff.c_str(), buffsize);
+ compsize = (unsigned long) (buffsize*1.01)+20; // at least 1% bigger than buffer + 12 bytes
+ //cfile << "{" << compsize << "}";
+ //destbuff = (char *) calloc(compsize + 1, 1);
+ destbuff = new char[compsize];
+ if (compress((Bytef*)destbuff, &compsize, (const Bytef*)currbuff.c_str(), buffsize)!=Z_OK)
+ {
+ cerr << "Could not compress buffer: exiting\n";
+ delete[] destbuff;
+ exit(-1);
+ }
+ //cout << "Compressed buffer{" << compsize << "}\n" << destbuff << "\n";
+ //cout.flush();
+ // write to compressed file index
+ ulCOff = lseek(ofd[i], 0, SEEK_END);
+ write(oxfd[i], &ulCOff, 4); // offset in compressed file
+ write(oxfd[i], &compsize, 4); // compressed size
+ write(oxfd[i], &buffsize, 4); // uncompressed size
+ cfile << buffsize << " -> " << compsize << "\n";
+ cfile2 << "Compressed{" << compsize << "}\n" << destbuff << "\n";
+ cfile2.flush();
+
+ //write compressed buffer to file
+ write(ofd[i], destbuff, compsize);
+
+ //free(destbuff);
+ delete[] destbuff;
+
+ currbuff = "";
+ ulBuffNum++;
+ ulIOff = 0;
+ */
+ }
+ else
+ {
+ ulIOff += ulsize;
+ }
+ free(tmpbuf);
+
+ if (newmodule)
+ {
+ newmodule = false;
+ cfile << "had a new module " << (const char *) key1 << "{" << offset << "}\n";
+ writeblock(i);
+ }
+ else if (newtestament)
+ {
+ newtestament = false;
+ cfile << "had a new testament " << (const char *) key1 << "{" << offset << "}\n";
+ }
+ else if (newbook)
+ {
+ newbook = false;
+ cfile << "had a new book " << (const char *) key1 << "{" << offset << "}\n";
+ }
+ else if (newchapter)
+ {
+ newchapter = false;
+ cfile << "had a new chapter " << (const char *) key1 << "{" << offset << "}\n";
+ }
+ else
+ {
+ key1++;
+ }
+
+ if (key1.Chapter()!=key2.Chapter() || (key1.Book()!=key2.Book()))
+ {
+ newchapter = true;
+ cfile << "got a new chapter " << (const char *) key1 << "\n";
+ }
+ if (key1.Book()!=key2.Book())
+ {
+ newbook = true;
+ cfile << "got a new book " << (const char *) key1 << "\n";
+ }
+ key2 = key1;
+
+ }
+ else
+ {
+ cfile << "empty offset\n";
+ // write to verse index into compressed
+ write(ovxfd[i], &ulNone, 4); // current buffer number
+ write(ovxfd[i], &size, 2); // verse size
+ write(ovxfd[i], &ulNone, 4); // offset within the buffer
+ }
+ }
+ while ( (key1.Testament()==i+1) && ((key1.compare("Revelation of John 22:21")==-1) || (lasttodo)));
+
+ close(ifd[i]);
+ close(ofd[i]);
+ close(ixfd[i]);
+ close(oxfd[i]);
+ close(ovxfd[i]);
+ close(itestfd[i]);
+ close(itestxfd[i]);
+}
+ return 1;
+}
diff --git a/src/modules/texts/ztext/ztext.cpp b/src/modules/texts/ztext/ztext.cpp
new file mode 100644
index 0000000..c774693
--- /dev/null
+++ b/src/modules/texts/ztext/ztext.cpp
@@ -0,0 +1,309 @@
+/******************************************************************************
+ * ztext.cpp - code for class 'zText'- a module that reads compressed text
+ * files: ot and nt using indexs ??.vss
+ */
+
+
+#include <ctype.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#ifndef __GNUC__
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <string.h>
+#include <utilfuns.h>
+//#include <rawverse.h>
+#include <ztext.h>
+//#include <zlib.h>
+
+
+/******************************************************************************
+ * zText Constructor - Initializes data for instance of zText
+ *
+ * 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
+ */
+
+zText::zText(const char *ipath, const char *iname, const char *idesc, int iblockType, SWCompress *icomp, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang) : zVerse(ipath, -1, iblockType, icomp), SWText(iname, idesc, idisp, enc, dir, mark, ilang)/*, SWCompress()*/
+{
+ blockType = iblockType;
+ lastWriteKey = 0;
+}
+
+
+/******************************************************************************
+ * zText Destructor - Cleans up instance of zText
+ */
+
+zText::~zText()
+{
+ flushCache();
+
+ if (lastWriteKey)
+ delete lastWriteKey;
+}
+
+
+/******************************************************************************
+ * zText::getRawEntry - Returns the current verse buffer
+ *
+ * RET: buffer with verse
+ */
+
+char *zText::getRawEntry()
+{
+/*
+ long start;
+ unsigned long size;
+ unsigned long destsize;
+ char *tmpbuf;
+ char *dest;
+ VerseKey *lkey = (VerseKey *) SWModule::key;
+ char sizebuf[3];
+
+ lkey->Verse(0);
+ if (chapcache != lkey->Index()) {
+ findoffset(lkey->Testament(), lkey->Index(), &start, &((unsigned short) size));
+ readtext(lkey->Testament(), start, 3, sizebuf);
+ memcpy(&size, sizebuf, 2);
+ tmpbuf = new char [ size + 1 ];
+ readtext(lkey->Testament(), start + 2, size + 1 , tmpbuf);
+ //zBuf(&size, tmpbuf);
+ dest = new char [ (size*4) + 1 ];
+ uncompress((Bytef *)dest, &destsize, (Bytef *) tmpbuf, size);
+ chapcache = lkey->Index();
+ delete [] tmpbuf;
+ }
+
+ //findoffset(key->Testament(), key->Index(), &start, &size);
+ findoffset(lkey->Testament(), lkey->Index(), &start, &((unsigned short) size));
+
+ if (versebuf)
+ delete [] versebuf;
+ versebuf = new char [ size + 1 ];
+ //memcpy(versebuf, Buf(), size);
+ memcpy(versebuf, dest, destsize);
+ delete [] dest;
+
+ preptext(versebuf);
+
+ return versebuf;
+*/
+
+ long start = 0;
+ unsigned short size = 0;
+ VerseKey *key = 0;
+
+ //printf ("zText char *\n");
+
+ // see if we have a VerseKey * or decendant
+ try {
+ key = SWDYNAMIC_CAST(VerseKey, this->key);
+ }
+ catch ( ... ) {}
+ // if we don't have a VerseKey * decendant, create our own
+ if (!key)
+ key = new VerseKey(this->key);
+
+ //printf ("checking cache\n");
+ //printf ("finding offset\n");
+ findoffset(key->Testament(), key->Index(), &start, &size);
+ entrySize = size; // support getEntrySize call
+
+ //printf ("deleting previous buffer\n");
+ unsigned long newsize = (size + 2) * FILTERPAD;
+ if (newsize > entrybufallocsize) {
+ if (entrybuf)
+ delete [] entrybuf;
+ entrybuf = new char [ newsize ];
+ entrybufallocsize = newsize;
+ }
+ *entrybuf = 0;
+
+ //printf ("getting text\n");
+ zreadtext(key->Testament(), start, (size + 2), entrybuf);
+ //printf ("got text\n");
+
+ rawFilter(entrybuf, size, key);
+
+ //printf ("preparing text\n");
+ if (!isUnicode())
+ preptext(entrybuf);
+
+ if (this->key != key) // free our key if we created a VerseKey
+ delete key;
+
+ //printf ("returning text\n");
+ return entrybuf;
+
+}
+
+
+bool zText::sameBlock(VerseKey *k1, VerseKey *k2) {
+ if (k1->Testament() != k2->Testament())
+ return false;
+
+ switch (blockType) {
+ case VERSEBLOCKS:
+ if (k1->Verse() != k2->Verse())
+ return false;
+ case CHAPTERBLOCKS:
+ if (k1->Chapter() != k2->Chapter())
+ return false;
+ case BOOKBLOCKS:
+ if (k1->Book() != k2->Book())
+ return false;
+ }
+ return true;
+}
+
+
+void zText::setEntry(const char *inbuf, long len) {
+ VerseKey *key = 0;
+ // see if we have a VerseKey * or decendant
+ try {
+ key = SWDYNAMIC_CAST(VerseKey, this->key);
+ }
+ catch ( ... ) {}
+ // if we don't have a VerseKey * decendant, create our own
+ if (!key)
+ key = new VerseKey(this->key);
+
+
+ // see if we've jumped across blocks since last write
+ if (lastWriteKey) {
+ if (!sameBlock(lastWriteKey, key)) {
+ flushCache();
+ }
+ delete lastWriteKey;
+ }
+
+ settext(key->Testament(), key->Index(), inbuf, len);
+
+ lastWriteKey = (VerseKey *)key->clone(); // must delete
+
+ if (this->key != key) // free our key if we created a VerseKey
+ delete key;
+}
+
+
+void zText::linkEntry(const SWKey *inkey) {
+ VerseKey *destkey = 0;
+ const VerseKey *srckey = 0;
+ // see if we have a VerseKey * or decendant
+ try {
+ destkey = SWDYNAMIC_CAST(VerseKey, this->key);
+ }
+ catch ( ... ) {}
+ // if we don't have a VerseKey * decendant, create our own
+ if (!destkey)
+ destkey = new VerseKey(this->key);
+
+ // see if we have a VerseKey * or decendant
+ try {
+ srckey = (const VerseKey *) SWDYNAMIC_CAST(VerseKey, inkey);
+ }
+ catch ( ... ) {
+ }
+ // if we don't have a VerseKey * decendant, create our own
+ if (!srckey)
+ srckey = new VerseKey(inkey);
+
+ linkentry(destkey->Testament(), destkey->Index(), srckey->Index());
+
+ if (this->key != destkey) // free our key if we created a VerseKey
+ delete destkey;
+
+ if (inkey != srckey) // free our key if we created a VerseKey
+ delete srckey;
+}
+
+
+/******************************************************************************
+ * zFiles::deleteEntry - deletes this entry
+ *
+ */
+
+void zText::deleteEntry() {
+
+ VerseKey *key = 0;
+
+ try {
+ key = SWDYNAMIC_CAST(VerseKey, this->key);
+ }
+ catch ( ... ) {}
+ if (!key)
+ key = new VerseKey(this->key);
+
+ settext(key->Testament(), key->Index(), "");
+
+ if (key != this->key)
+ delete key;
+}
+
+
+/******************************************************************************
+ * zText::increment - Increments module key a number of entries
+ *
+ * ENT: increment - Number of entries to jump forward
+ *
+ */
+
+void zText::increment(int steps) {
+ long start;
+ unsigned short size;
+ VerseKey *tmpkey = 0;
+
+ try {
+ tmpkey = SWDYNAMIC_CAST(VerseKey, key);
+ }
+ catch ( ... ) {}
+ if (!tmpkey)
+ tmpkey = new VerseKey(key);
+
+ findoffset(tmpkey->Testament(), tmpkey->Index(), &start, &size);
+
+ SWKey lastgood = *tmpkey;
+ while (steps) {
+ long laststart = start;
+ unsigned short lastsize = size;
+ SWKey lasttry = *tmpkey;
+ (steps > 0) ? (*key)++ : (*key)--;
+ if (tmpkey != key)
+ delete tmpkey;
+ tmpkey = 0;
+ try {
+ tmpkey = SWDYNAMIC_CAST(VerseKey, key);
+ }
+ catch ( ... ) {}
+ if (!tmpkey)
+ tmpkey = new VerseKey(key);
+
+ if ((error = key->Error())) {
+ *key = lastgood;
+ break;
+ }
+ long index = tmpkey->Index();
+ findoffset(tmpkey->Testament(), index, &start, &size);
+
+ 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;
+
+ if (tmpkey != key)
+ delete tmpkey;
+}