diff options
Diffstat (limited to 'src/modules/texts/rawgbf/gbf.cpp')
-rw-r--r-- | src/modules/texts/rawgbf/gbf.cpp | 735 |
1 files changed, 735 insertions, 0 deletions
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. |