diff options
Diffstat (limited to 'src/modules/filters/thmlrtf.cpp')
-rw-r--r-- | src/modules/filters/thmlrtf.cpp | 243 |
1 files changed, 169 insertions, 74 deletions
diff --git a/src/modules/filters/thmlrtf.cpp b/src/modules/filters/thmlrtf.cpp index 76289ec..4487921 100644 --- a/src/modules/filters/thmlrtf.cpp +++ b/src/modules/filters/thmlrtf.cpp @@ -15,12 +15,14 @@ ***************************************************************************/ #include <stdlib.h> -#include <string.h> #include <thmlrtf.h> +#include <swmodule.h> +#include <utilxml.h> +#include <versekey.h> +SWORD_NAMESPACE_START -ThMLRTF::ThMLRTF() -{ +ThMLRTF::ThMLRTF() { setTokenStart("<"); setTokenEnd(">"); @@ -30,6 +32,7 @@ ThMLRTF::ThMLRTF() setEscapeStringCaseSensitive(true); addEscapeStringSubstitute("nbsp", " "); + addEscapeStringSubstitute("apos", "'"); addEscapeStringSubstitute("quot", "\""); addEscapeStringSubstitute("amp", "&"); addEscapeStringSubstitute("lt", "<"); @@ -128,87 +131,178 @@ ThMLRTF::ThMLRTF() setTokenCaseSensitive(true); - addTokenSubstitute("/scripRef", "|}"); - addTokenSubstitute("/note", ") }"); - - addTokenSubstitute("br", "\\line "); - addTokenSubstitute("br /", "\\line "); - addTokenSubstitute("i", "{\\i1 "); - addTokenSubstitute("/i", "}"); - addTokenSubstitute("b", "{\\b1 "); - addTokenSubstitute("/b", "}"); - addTokenSubstitute("p", "\\par "); - - //we need uppercase forms for the moment to support a few early ThML modules that aren't XHTML compliant - addTokenSubstitute("BR", "\\line "); - addTokenSubstitute("I", "{\\i1 "); - addTokenSubstitute("/I", "}"); - addTokenSubstitute("B", "{\\b1 "); - addTokenSubstitute("/B", "}"); - addTokenSubstitute("P", "\\par "); + + addTokenSubstitute("br", "\\line "); + addTokenSubstitute("br /", "\\line "); + addTokenSubstitute("i", "{\\i1 "); + addTokenSubstitute("/i", "}"); + addTokenSubstitute("b", "{\\b1 "); + addTokenSubstitute("/b", "}"); + addTokenSubstitute("p", "\\par "); + + //we need uppercase forms for the moment to support a few early ThML modules that aren't XHTML compliant + addTokenSubstitute("BR", "\\line "); + addTokenSubstitute("I", "{\\i1 "); + addTokenSubstitute("/I", "}"); + addTokenSubstitute("B", "{\\b1 "); + addTokenSubstitute("/B", "}"); + addTokenSubstitute("P", "\\par "); + addTokenSubstitute("scripture", "{\\i1 "); + addTokenSubstitute("/scripture", "}"); } -bool ThMLRTF::handleToken(char **buf, const char *token, DualStringMap &userData) { - if (!substituteToken(buf, token)) { - // manually process if it wasn't a simple substitution - if (!strncmp(token, "sync type=\"Strongs\" value=\"", 27)) { -/* if (token[27] == 'H' || token[27] == 'G' || token[27] == 'A') { - pushString(buf, " {\\fs15 <"); - for (unsigned int i = 28; token[i] != '\"'; i++) - *(*buf)++ = token[i]; - pushString(buf, ">}"); - } - else if (token[27] == 'T') { - pushString(buf, " {\\fs15 ("); - for (unsigned int i = 28; token[i] != '\"'; i++) - *(*buf)++ = token[i]; - pushString(buf, ")}"); + +char ThMLRTF::processText(SWBuf &text, const SWKey *key, const SWModule *module) { + SWBasicFilter::processText(text, key, module); //handle tokens as usual + const char *from; + SWBuf orig = text; + from = orig.c_str(); + for (text = ""; *from; from++) { //loop to remove extra spaces + if ((strchr(" \t\n\r", *from))) { + while (*(from+1) && (strchr(" \t\n\r", *(from+1)))) { + from++; } + text += " "; + } + else { + text += *from; + } + } + text += (char)0; + return 0; +} + + +ThMLRTF::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) { + if (module) { + version = module->Name(); + BiblicalText = (!strcmp(module->Type(), "Biblical Texts")); + } +} + + +bool ThMLRTF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) { + const char *tok; + if (!substituteToken(buf, token)) { // manually process if it wasn't a simple substitution + MyUserData *u = (MyUserData *)userData; + XMLTag tag(token); + if ((!tag.isEndTag()) && (!tag.isEmpty())) + u->startTag = tag; + if (tag.getName() && !strcmp(tag.getName(), "sync")) { + SWBuf value = tag.getAttribute("value"); + if (tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "morph")) { //> + buf.appendFormatted(" {\\cf4 \\sub (%s)}", value.c_str()); + } + else if( tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "Strongs")) { + if (value[0] == 'H' || value[0] == 'G' || value[0] == 'A') { + value<<1; + buf.appendFormatted(" {\\cf3 \\sub <%s>}", value.c_str()); + } + else if (value[0] == 'T') { + value<<1; + buf.appendFormatted(" {\\cf4 \\sub (%s)}", value.c_str()); + } + } + else if (tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "Dict")) { + if (!tag.isEndTag()) + buf += "{\\b "; + else buf += "}"; + } } - else if (!strncmp(token, "sync type=\"morph\" ", 18)) { - pushString(buf, " {\\fs15 ("); - for (const char *tok = token + 5; *tok; tok++) { - if (!strncmp(tok, "value=\"", 7)) { - tok += 7; - for (;*tok != '\"'; tok++) - *(*buf)++ = *tok; - break; + // <note> tag + else if (!strcmp(tag.getName(), "note")) { + if (!tag.isEndTag()) { + if (!tag.isEmpty()) { + SWBuf type = tag.getAttribute("type"); + SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); + VerseKey *vkey; + // see if we have a VerseKey * or descendant + try { + vkey = SWDYNAMIC_CAST(VerseKey, u->key); + } + catch ( ... ) { } + if (vkey) { + // leave this special osis type in for crossReference notes types? Might thml use this some day? Doesn't hurt. + char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); + buf.appendFormatted("{\\super <a href=\"\">*%c%i.%s</a>} ", ch, vkey->Verse(), footnoteNumber.c_str()); + } + u->suspendTextPassThru = true; } } + if (tag.isEndTag()) { + u->suspendTextPassThru = false; + } + } + - pushString(buf, ")}"); -*/ } - else if (!strncmp(token, "sync type=\"lemma\" value=\"", 25)) { - pushString(buf, "{\\fs15 ("); - for (unsigned int i = 25; token[i] != '\"'; i++) - *(*buf)++ = token[i]; - pushString(buf, ")}"); + else if (!strcmp(tag.getName(), "scripRef")) { + if (!tag.isEndTag()) { + if (!tag.isEmpty()) { + u->suspendTextPassThru = true; + } + } + if (tag.isEndTag()) { // </scripRef> + if (!u->BiblicalText) { + SWBuf refList = u->startTag.getAttribute("passage"); + if (!refList.length()) + refList = u->lastTextNode; + SWBuf version = tag.getAttribute("version"); + buf += "<a href=\"\">"; + buf += refList.c_str(); +// buf += u->lastTextNode.c_str(); + buf += "</a>"; + } + else { + SWBuf footnoteNumber = u->startTag.getAttribute("swordFootnote"); + VerseKey *vkey; + // see if we have a VerseKey * or descendant + try { + vkey = SWDYNAMIC_CAST(VerseKey, u->key); + } + catch ( ... ) {} + if (vkey) { + // leave this special osis type in for crossReference notes types? Might thml use this some day? Doesn't hurt. + buf.appendFormatted("{\\super <a href=\"\">*x%i.%s</a>} ", vkey->Verse(), footnoteNumber.c_str()); + } + } + + // let's let text resume to output again + u->suspendTextPassThru = false; + } } - else if (!strncmp(token, "scripRef", 8)) { - pushString(buf, "{\\cf2 #"); + + else if (tag.getName() && !strcmp(tag.getName(), "div")) { + if (tag.isEndTag() && u->SecHead) { + buf += "\\par}"; + u->SecHead = false; + } + else if (tag.getAttribute("class")) { + if (!stricmp(tag.getAttribute("class"), "sechead")) { + u->SecHead = true; + buf += "{\\par\\i1\\b1 "; + } + else if (!stricmp(tag.getAttribute("class"), "title")) { + u->SecHead = true; + buf += "{\\par\\i1\\b1 "; + } + } } - else if (!strncmp(token, "div", 3)) { - *(*buf)++ = '{'; - if (!strncmp(token, "div class=\"title\"", 17)) { - pushString(buf, "\\par\\i1\\b1 "); - userData["sechead"] = "true"; - } - else if (!strncmp(token, "div class=\"sechead\"", 19)) { - pushString(buf, "\\par\\i1\\b1 "); - userData["sechead"] = "true"; - } - } - else if (!strncmp(token, "/div", 4)) { - *(*buf)++ = '}'; - if (userData["sechead"] == "true") { - pushString(buf, "\\par "); - userData["sechead"] == "false"; - } - } - else if (!strncmp(token, "note", 4)) { - pushString(buf, " {\\i1\\fs15 ("); - } + else if (tag.getName() && (!strcmp(tag.getName(), "img") || !strcmp(tag.getName(), "image"))) { + const char *src = tag.getAttribute("src"); + if (!src) // assert we have a src attribute + return false; + char* filepath = new char[strlen(u->module->getConfigEntry("AbsoluteDataPath")) + strlen(token)]; + *filepath = 0; + strcpy(filepath, userData->module->getConfigEntry("AbsoluteDataPath")); + strcat(filepath, src); + +// we do this because BibleCS looks for this EXACT format for an image tag + buf+="<img src=\""; + buf+=filepath; + buf+="\" />"; + delete [] filepath; + } else { return false; // we still didn't handle token } @@ -217,3 +311,4 @@ bool ThMLRTF::handleToken(char **buf, const char *token, DualStringMap &userData } +SWORD_NAMESPACE_END |