00001 enum TToken {
00002 tokNull, tokEOF, tokHeader, tokContent, tokTail, tokStyle,
00003 tokWord, tokSpace, tokSync, tokControl, tokChar, tokFont};
00004
00005 enum TCharacterAttribute { caBold, caSmallCaps, caItalic, caOTQuote, caRed,
00006 caSuperscript, caUnderline, caSubscript};
00007
00008
00009
00010
00011 struct TBookNameRec {
00012 string Name, Abbr;
00013 char Num;
00014 }
00015
00016 const struct TBookNameRec TBookAbbr[116] = {
00017 {"1 Chronicles", "1CH", 13},
00018 {"1 Corinthians", "1CO", 70},
00019 {"1 Esdras", "1E", 52},
00020 {"1 John", "1J", 86},
00021 {"1 Kings", "1K", 11},
00022 {"1 Maccabees", "1M", 50},
00023 {"1 Peter", "1P", 84},
00024 {"1 Samuel", "1S", 9},
00025 {"1 Thessalonians", "1TH", 76},
00026 {"1 Timothy", "1TI", 78},
00027 {"2 Chronicles", "2CH", 14},
00028 {"2 Corinthians", "2CO", 71},
00029 {"2 Esdras", "2E", 56},
00030 {"2 John", "2J", 87},
00031 {"2 Kings", "2K", 12},
00032 {"2 Maccabees", "2M", 51},
00033 {"2 Peter", "2P", 85},
00034 {"2 Samuel", "2S", 10},
00035 {"2 Thessalonians", "2TH", 77},
00036 {"2 Timothy", "2TI", 79},
00037 {"3 John", "3J", 88},
00038 {"3 Maccabees", "3M", 55},
00039 {"4 Maccabees", "4M", 57},
00040 {"1 Chronicles", "1 CH", 13},
00041 {"1 Corinthians", "1 CO", 70},
00042 {"1 Esdras", "1 E", 52},
00043 {"1 John", "1 J", 86},
00044 {"1 Kings", "1 K", 11},
00045 {"1 Maccabees", "1 M", 50},
00046 {"1 Peter", "1 P", 84},
00047 {"1 Samuel", "1 S", 9},
00048 {"1 Thessalonians", "1 TH", 76},
00049 {"1 Timothy", "1 TI", 78},
00050 {"2 Chronicles", "2 CH", 14},
00051 {"2 Corinthians", "2 CO", 71},
00052 {"2 Esdras", "2 E", 56},
00053 {"2 John", "2 J", 87},
00054 {"2 Kings", "2 K", 12},
00055 {"2 Maccabees", "2 M", 51},
00056 {"2 Peter", "2 P", 85},
00057 {"2 Samuel", "2 S", 10},
00058 {"2 Thessalonians", "2 TH", 77},
00059 {"2 Timothy", "2 TI", 79},
00060 {"3 John", "3 J", 88},
00061 {"3 Maccabees", "3 M", 55},
00062 {"4 Maccabees", "4 M", 57},
00063 {"Acts", "AC", 68},
00064 {"Amos", "AM", 30},
00065 {"Prayer of Asariah and the Song of the Three Jews", "AZ", 47},
00066 {"Baruch", "BA", 45},
00067 {"Bel and the Dragon","BE", 49},
00068 {"Colossians", "CO", 75},
00069 {"Daniel", "DA", 27},
00070 {"Deuteronomy", "DE", 5},
00071 {"Deuteronomy", "DT", 5},
00072 {"Ecclesiasties", "EC", 21},
00073 {"Esther", "ES", 17},
00074 {"Exodus", "EX", 2},
00075 {"Ezekiel", "EZE", 26},
00076 {"Ezra", "EZR", 15},
00077 {"Galatians", "GA", 72},
00078 {"Genesis", "GE", 1},
00079 {"Genesis", "GN", 1},
00080 {"Ephesians", "EP", 73},
00081 {"Esther (Greek}", "GR", 42),
00082 {"Habakkuk", "HAB", 35},
00083 {"Haggai", "HAG", 37},
00084 {"Hebrews", "HE", 82},
00085 {"Hosea", "HO", 28},
00086 {"Isaiah", "IS", 23},
00087 {"James", "JA", 83},
00088 {"Jeremiah", "JE", 24},
00089 {"Job", "JOB", 18},
00090 {"Joel", "JOE", 29},
00091 {"John", "JOH", 67},
00092 {"Jonah", "JON", 32},
00093 {"Joshua", "JOS", 6},
00094 {"Jude", "JUDE", 89},
00095 {"Judges", "JUDG", 7},
00096 {"Judith", "JUDI", 41},
00097 {"Lamentations", "LA", 25},
00098 {"Letter of Jeremiah",Abbr:"LET", 46},
00099 {"Leviticus", "LEV", 3},
00100 {"Luke", "LK", 66},
00101 {"Leviticus", "LV", 3},
00102 {"Luke", "LU", 66},
00103 {"Malachi", "MAL", 39},
00104 {"Prayer of Manasseh",Abbr:"MAN", 53},
00105 {"Mark", "MAR", 65},
00106 {"Matthew", "MAT", 64},
00107 {"Micah", "MI", 33},
00108 {"Nahum", "NA", 34},
00109 {"Nehemiah", "NE", 16},
00110 {"Numbers", "NU", 4},
00111 {"Obadiah", "OB", 31},
00112 {"Psalm 151", "P1", 54},
00113 {"Philemon", "PHILE", 81},
00114 {"Philippians", "PHILI", 74},
00115 {"Philemon", "PHM", 81},
00116 {"Philippians", "PHP", 74},
00117 {"Proverbs", "PR", 20},
00118 {"Psalms", "PS", 19},
00119 {"Revelation", "RE", 90},
00120 {"Romans", "RM", 69},
00121 {"Romans", "RO", 69},
00122 {"Ruth", "RU", 8},
00123 {"Sirach", "SI", 44},
00124 {"Song of Solomon", "SOL", 22},
00125 {"Song of Solomon", "SON", 22},
00126 {"Song of Solomon", "SS", 22},
00127 {"Susanna", "SU", 48},
00128 {"Titus", "TI", 80},
00129 {"Tobit", "TO", 40},
00130 {"Wisdom", "WI", 43},
00131 {"Zechariah", "ZEC", 38},
00132 {"Zephaniah", "ZEP", 36}
00133 },
00134
00135 string BookFileName[91] = {
00136 "","Genesis","Exodus","Lev","Num","Deut","Joshua","Judges",
00137 "Ruth","1Sam","2Sam","1Kings","2Kings","1Chron","2Chron",
00138 "Ezra","Nehemiah","Esther","Job","Psalms","Proverbs",
00139 "Eccl","Song","Isaiah","Jeremiah","Lament","Ezekiel",
00140 "Daniel","Hosea","Joel","Amos","Obadiah","Jonah","Micah",
00141 "Nahum","Habakkuk","Zeph","Haggai","Zech","Malachi",
00142 "Tobit","Judith","Esther","Wisdom","Sirach","Baruch",
00143 "Let","Azar","Susanna","Bel","1Mac","2Mac","1Esdras",
00144 "Man","P1","3Mac","2Esdras","4Mac","","","","","","",
00145 "Matthew","Mark","Luke","John","Acts","Romans","1Cor",
00146 "2Cor","Gal","Eph","Philip","Col","1Thes","2Thes","1Tim",
00147 "2Tim","Titus","Philemon","Hebrews","James","1Peter",
00148 "2Peter","1John","2John","3John","Jude","Rev"};
00149
00150 class TReadGBF {
00151 private:
00152 FILE *fp;
00153 string FName, TokenLine;
00154 int TokenPos;
00155 bool fFileIsOpen, fParagraphEnd, fInTitle, fInPsalmBookTitle, fInHebrewTitle, fInSectionTitle;
00156
00157 public:
00158 string sBook, sChapter, sVerse, sMode;
00159 string sContext;
00160 string sTitle;
00161 string sPsalmBookTitle;
00162 string sHebrewTitle;
00163 string sSectionTitle;
00164 string sDate;
00165 string sFontName;
00166 int iTotalWords;
00167 char chJustification, chDirection;
00168 bool fIndent, fPoetry;
00169 int CharAttribs;
00170 char bBk, bChap, bVs, bWd;
00171
00172 bool Init(const string sFileName);
00173 void Done();
00174 string GetToken(TToken &TokenKind);
00175 end;
00176
00177 class TWriteGBF {
00178 private:
00179 F: TextFile;
00180 FName, LineOut: string;
00181 fFileIsOpen: boolean;
00182 bBk, bChap, bVs, bWd: byte;
00183
00184 public
00185
00186 function Init(const sFileName: string): boolean;
00187 function Done: boolean;
00188 procedure Out(const s: string);
00189 end;
00190
00191 function isletter(const ch: char): boolean;
00192 function isinword(const ch: char): boolean;
00193 function IsDigit(const ch: char): Boolean;
00194 function IsUpper(const ch: char): Boolean;
00195 function ConformCase(const sPat, sSrc: string): string;
00196 function BookNameToNumber(const sBookName: string): byte;
00197
00198 implementation
00199
00200 function isletter(const ch: char): boolean;
00201 begin
00202 case ch of
00203 'A'..'Z': isletter := true;
00204 'a'..'z': isletter := true;
00205 else
00206 isletter := false;
00207 end;
00208 end;
00209
00210 function isinword(const ch: char): boolean;
00211 begin
00212 case ch of
00213 '-': isinword := true;
00214 'A'..'Z': isinword := true;
00215 'a'..'z': isinword := true;
00216 else
00217 isinword := false;
00218 end;
00219 end;
00220
00221 function IsUpper(const ch: char): Boolean;
00222 begin
00223 case ch of
00224 'A'..'Z': IsUpper := true;
00225 else
00226 IsUpper := false;
00227 end;
00228 end;
00229
00230 function IsDigit(const ch: char): Boolean;
00231 begin
00232 case ch of
00233 '0'..'9': IsDigit := true;
00234 else
00235 IsDigit := false;
00236 end;
00237 end;
00238
00239
00240 function MatchAbbrev(const sName, sAbbrev: string): boolean;
00241 var i: integer;
00242 begin
00243 if Length(sName) < Length(sAbbrev) then
00244 Result := false
00245 else
00246 Result := true;
00247 i := 1;
00248 while (i <= Length(sAbbrev)) and Result do
00249 begin
00250 if UpCase(sName[i]) <> sAbbrev[i] then
00251 Result := false;
00252 inc(i);
00253 end;
00254 end;
00255
00256 function BookNameToNumber(const sBookName: string): byte;
00257 var i: integer;
00258 begin
00259 Result := 0;
00260 try
00261 if IsDigit(sBookName[Length(sBookName)]) and IsDigit(sBookName[1]) then
00262 Result := StrToInt(sBookName);
00263 except
00264 Result := 0;
00265 end;
00266 i := 0;
00267 while (Result = 0) and (i <= 115) do
00268 begin
00269 if MatchAbbrev(sBookName,BookAbbr[i].Abbr) then
00270 begin
00271 Result := BookAbbr[i].Num;
00272 end;
00273 inc(i);
00274 end;
00275 end;
00276
00277 function BookNumberToName(const bBookNum: byte): string;
00278 begin
00279 if bBookNum <= 115 then
00280 Result := BookAbbr[bBookNum].Name
00281 else
00282 Result := '';
00283 end;
00284
00285 function ConformCase(const sPat, sSrc: string): string;
00286 var i: integer;
00287 begin
00288 Result := sSrc;
00289 if (Length(sPat) > 0) and (Length(sSrc) > 0) then
00290 begin
00291 Result := LowerCase(sSrc);
00292 if IsUpper(sPat[1]) then
00293 Result[1] := UpCase(Result[1]);
00294 if (Length(sPat) > 1) and (Length(sSrc) > 1) then
00295 begin
00296 if IsUpper(sPat[2]) then
00297 begin
00298 for i := 2 to Length(Result) do
00299 Result[i] := UpCase(Result[i]);
00300 end;
00301 end;
00302 end;
00303 end;
00304
00305 function TReadGBF.Init(const sFileName: string): boolean;
00306 var s: string;
00307 tok: TToken;
00308 begin
00309 try
00310 fParagraphEnd := false;
00311 bBk := 0;
00312 bChap := 0;
00313 bVs := 0;
00314 bWd := 0;
00315 iTotalWords := 0;
00316 FName := sFileName;
00317 Assign(F, FName);
00318 reset(F);
00319 readln(F, TokenLine);
00320 TokenPos := 1;
00321 fFileIsOpen := true;
00322 repeat
00323 s := GetToken(tok)
00324 until (tok = tokEOF) or ((tok = tokHeader) and (s[3] = '0'));
00325 Init := true;
00326 except
00327 Init := false;
00328 fFileIsOpen := false;
00329 end
00330 end;
00331
00332 procedure TReadGBF.Done;
00333 begin
00334 if fFileIsOpen then
00335 begin
00336 closefile(F);
00337 fFileIsOpen := false;
00338 end;
00339 end;
00340
00341 function TReadGBF.GetToken(var TokenKind: TToken): string;
00342 var m: integer;
00343 begin
00344 Result := '';
00345 TokenKind := tokNull;
00346 if TokenPos = 0 then
00347 begin
00348 if (not fFileIsOpen) or EOF(F) then
00349 TokenKind := tokEOF
00350 else
00351 begin
00352 ReadLn(F,TokenLine);
00353 TokenPos := 1;
00354 end;
00355 end;
00356 if TokenKind <> tokEOF then
00357 begin
00358 m := Length(TokenLine);
00359 if TokenPos > m then
00360 begin
00361 TokenKind := tokSpace;
00362 if fParagraphEnd then
00363 fParagraphEnd := false
00364 else
00365 Result := ' ';
00366 TokenPos := 0;
00367 end
00368 else
00369 begin
00370 if (TokenLine[TokenPos] = '<') then
00371 begin
00372 fParagraphEnd := false;
00373 repeat
00374 Result := Result + TokenLine[TokenPos];
00375 inc(TokenPos);
00376 until (TokenLine[TokenPos] = '>') or (TokenPos > m);
00377 Result := Result + '>';
00378 inc(TokenPos);
00379 case result[2] of
00380 'B': begin
00381 TokenKind := tokContent;
00382 sContext := Result;
00383 end;
00384 'C': begin
00385 TokenKind := tokControl;
00386 if (Result[3] = 'M') or (Result[3] = 'L') then
00387 fParagraphEnd := true;
00388 end;
00389 'D': begin
00390 TokenKind := tokControl;
00391 chDirection := Result[3];
00392 end;
00393 'H': begin
00394 TokenKind := tokHeader;
00395 sContext := Result;
00396 end;
00397 'F': begin
00398 TokenKind := tokFont;
00399 case Result[3] of
00400 'B': CharAttribs := CharAttribs + [caBold];
00401 'C': CharAttribs := CharAttribs + [caSmallCaps];
00402 'I': CharAttribs := CharAttribs + [caItalic];
00403 'N': sFontName := copy(Result,4,Length(Result)-4);
00404 'O': CharAttribs := CharAttribs + [caOTQuote];
00405 'R': CharAttribs := CharAttribs + [caRed];
00406 'S': CharAttribs := CharAttribs + [caSuperscript];
00407 'U': CharAttribs := CharAttribs + [caUnderline];
00408 'V': CharAttribs := CharAttribs + [caSubscript];
00409 'b': CharAttribs := CharAttribs - [caBold];
00410 'c': CharAttribs := CharAttribs - [caSmallCaps];
00411 'i': CharAttribs := CharAttribs - [caItalic];
00412 'n': sFontName := '';
00413 'o': CharAttribs := CharAttribs - [caOTQuote];
00414 'r': CharAttribs := CharAttribs - [caRed];
00415 's': CharAttribs := CharAttribs - [caSuperscript];
00416 'u': CharAttribs := CharAttribs - [caUnderline];
00417 'v': CharAttribs := CharAttribs - [caSubscript];
00418
00419 end;
00420 end;
00421 'J': begin
00422 TokenKind := tokStyle;
00423 chJustification := Result[3];
00424 end;
00425 'P': begin
00426 TokenKind := tokControl;
00427 case Result[3] of
00428 'I': fIndent := true;
00429 'P': fPoetry := true;
00430 'i': fIndent := false;
00431 'p': fPoetry := false;
00432 end;
00433 end;
00434 'R': begin
00435 TokenKind := tokControl;
00436 end;
00437 'S': begin
00438 TokenKind := TokSync;
00439 case Result[3] of
00440 'B': begin
00441 sBook := system.copy(Result, 4, length(Result)-4);
00442 sPsalmBookTitle := '';
00443 if sBook = '' then
00444 begin
00445 inc(bBk);
00446 sBook := BookNumberToName(bBk);
00447 end
00448 else
00449 bBk := BookNameToNumber(sBook);
00450 sTitle := sBook;
00451 end;
00452 'C': begin
00453 sChapter := system.copy(Result, 4, length(Result)-4);
00454 if sChapter = '' then
00455 begin
00456 inc(bChap);
00457 sChapter := IntToStr(bChap);
00458 end
00459 else
00460 begin
00461 try
00462 bChap := StrToInt(sChapter);
00463 except
00464 showmessage('Non-numeric chapter: '+sBook+' '+sChapter);
00465 end;
00466 end;
00467 sHebrewTitle := '';
00468 end;
00469 'V': begin
00470 bWd := 0;
00471 sVerse := system.copy(Result, 4, length(Result)-4);
00472 if sVerse = '' then
00473 begin
00474 inc(bVs);
00475 sVerse := IntToStr(bVs);
00476 end
00477 else
00478 begin
00479 try
00480 bVs := StrToInt(sVerse);
00481 except
00482 showmessage('Non-numeric verse: '+sBook+' '+sChapter+':'+sVerse);
00483 end;
00484 end;
00485 end;
00486 'D': begin
00487 sDate := system.copy(Result, 3, length(Result)-4);
00488 end;
00489 end;
00490 end;
00491 'T': begin
00492 TokenKind := TokContent;
00493 case Result[3] of
00494 'B':
00495 begin
00496 sPsalmBookTitle := '';
00497 fInPsalmBookTitle := true;
00498 end;
00499 'b': fInPsalmBookTitle := true;
00500 'H':
00501 begin
00502 sHebrewTitle := '';
00503 fInHebrewTitle := true;
00504 end;
00505 'h': fInHebrewTitle := false;
00506 'S':
00507 begin
00508 sSectionTitle := '';
00509 fInSectionTitle := true;
00510 end;
00511 's': fInSectionTitle := false;
00512 'T':
00513 begin
00514 sTitle := '';
00515 fInTitle := true;
00516 end;
00517 't': fInTitle := false;
00518 end;
00519 end;
00520 'Z': begin
00521 TokenKind := tokTail;
00522 sContext := Result;
00523 if Result[3] = 'Z' then
00524 done;
00525 end;
00526 else
00527 TokenKind := TokControl;
00528
00529 end;
00530 end
00531 else if isletter(TokenLine[TokenPos]) then
00532 begin {Word}
00533 fParagraphEnd := false;
00534 TokenKind := tokWord;
00535 repeat
00536 Result := Result + TokenLine[TokenPos];
00537 inc(TokenPos);
00538 until (TokenPos > m) or (not isinword(TokenLine[TokenPos]));
00539 inc(bWd);
00540 inc(iTotalWords);
00541 end
00542 else if ((TokenLine[TokenPos] = ' ') or (TokenLine[TokenPos] = #9)) then
00543 begin
00544 fParagraphEnd := false;
00545 TokenKind := tokSpace;
00546 Result := Result + TokenLine[TokenPos];
00547 inc(TokenPos);
00548 end
00549 else
00550 begin
00551 fParagraphEnd := false;
00552 TokenKind := tokChar;
00553 Result := Result + TokenLine[TokenPos];
00554 inc(TokenPos);
00555 end
00556 end;
00557 end;
00558 if ((TokenKind = tokWord) or (TokenKind = tokSpace) or
00559 (TokenKind = tokChar)) then
00560 begin
00561 if fInTitle then
00562 sTitle := sTitle + Result
00563 else if fInPsalmBookTitle then
00564 sPsalmBookTitle := sPsalmBookTitle + Result
00565 else if fInHebrewTitle then
00566 sHebrewTitle := sHebrewTitle + Result
00567 else if fInSectionTitle then
00568 sSectionTitle := sSectionTitle + Result;
00569 end;
00570 end;
00571
00572 function TWriteGBF.Init(const sFileName: string): boolean;
00573 begin
00574 try
00575 bBk := 0;
00576 bChap := 0;
00577 bVs := 0;
00578 bWd := 0;
00579 LineOut := '';
00580 FName := sFileName;
00581 Assign(F, FName);
00582 filemode := 1;
00583 rewrite(F);
00584 fFileIsOpen := true;
00585 Init := true;
00586 except
00587 Init := false;
00588 fFileIsOpen := false;
00589 end
00590 end;
00591
00592 function TWriteGBF.Done: boolean;
00593 begin
00594 try
00595 if fFileIsOpen then
00596 begin
00597 if LineOut <> '' then
00598 begin
00599 WriteLn(F, LineOut);
00600 LineOut := '';
00601 end;
00602 CloseFile(F);
00603 end;
00604 Done := true;
00605 except
00606 Done := false;
00607 end;
00608 end;
00609
00610 procedure TWriteGBF.Out(const s: string);
00611 var sPrint, sSave, sBook, sChapter, sVerse: string;
00612 i: integer;
00613 b: byte;
00614 begin
00615 if (Length(s) > 0) and IsLetter(s[1]) then
00616 begin
00617 inc(bWd);
00618 LineOut := LineOut + s;
00619 end
00620 else if Length(s) > 3 then
00621 begin
00622 if (s[1] = '<') and (s[2] = 'S') then
00623 begin
00624 case s[3] of
00625 'B': begin
00626 sBook := system.copy(s, 4, length(s)-4);
00627 if sBook = '' then
00628 begin
00629 inc(bBk);
00630 LineOut := LineOut + s;
00631 end
00632 else
00633 begin
00634 b := bBk;
00635 bBk := BookNameToNumber(sBook);
00636 if b <> bBk then
00637 LineOut := LineOut + s;
00638 end;
00639 end;
00640 'C': begin
00641 sChapter := system.copy(s, 4, length(s)-4);
00642 if sChapter = '' then
00643 begin
00644 inc(bChap);
00645 LineOut := LineOut + s;
00646 end
00647 else
00648 begin
00649 try
00650
00651 bChap := StrToInt(sChapter);
00652
00653 LineOut := LineOut + s;
00654 except
00655 showmessage('Non-numeric chapter: '+sBook+' '+sChapter);
00656 end;
00657 end;
00658 end;
00659 'V': begin
00660 bWd := 0;
00661 sVerse := system.copy(s, 4, length(s)-4);
00662 if sVerse = '' then
00663 begin
00664 inc(bVs);
00665 LineOut := LineOut + s;
00666 end
00667 else
00668 begin
00669 try
00670
00671 bVs := StrToInt(sVerse);
00672
00673 LineOut := LineOut + s;
00674 except
00675 showmessage('Non-numeric verse: '+sBook+' '+sChapter+':'+sVerse);
00676 end;
00677 end;
00678 end;
00679 else
00680 LineOut := LineOut + s;
00681 end
00682 end
00683 else
00684 LineOut := LineOut + s;
00685 end
00686 else
00687 LineOut := LineOut + s;
00688 if ((s = '<CM>') or (s = '<CL>')) then
00689 begin
00690 if (Length(LineOut) > 78) then
00691 begin
00692 i := 78;
00693 while (i > 0) and (LineOut[i] <> ' ') do
00694 dec(i);
00695 if i < 1 then
00696 begin
00697 WriteLn(F,LineOut);
00698 LineOut := '';
00699 end
00700 else
00701 begin
00702 sPrint := system.copy(LineOut,1,i-1);
00703 sSave := system.copy(LineOut,i+1,Length(LineOut)-i);
00704 WriteLn(F,sPrint);
00705 WriteLn(F, sSave);
00706 LineOut := '';
00707 end
00708 end
00709 else
00710 begin
00711 WriteLn(F, LineOut);
00712 LineOut := '';
00713 end
00714 end
00715 else if (Length(LineOut) > 78) then
00716 begin
00717 i := 78;
00718 while (i > 0) and (LineOut[i] <> ' ') do
00719 dec(i);
00720 if i < 1 then
00721 begin
00722 WriteLn(F,LineOut);
00723 LineOut := '';
00724 end
00725 else
00726 begin
00727 sPrint := system.copy(LineOut,1,i-1);
00728 sSave := system.copy(LineOut,i+1,Length(LineOut)-i);
00729 WriteLn(F,sPrint);
00730 LineOut := sSave;
00731 end
00732 end
00733 end;
00734
00735 end.