summaryrefslogtreecommitdiff
path: root/src/modules/filters/thmlhtmlhref.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/filters/thmlhtmlhref.cpp')
-rw-r--r--src/modules/filters/thmlhtmlhref.cpp350
1 files changed, 145 insertions, 205 deletions
diff --git a/src/modules/filters/thmlhtmlhref.cpp b/src/modules/filters/thmlhtmlhref.cpp
index ce7e3fd..b94b8ae 100644
--- a/src/modules/filters/thmlhtmlhref.cpp
+++ b/src/modules/filters/thmlhtmlhref.cpp
@@ -15,255 +15,195 @@
***************************************************************************/
#include <stdlib.h>
-#include <string.h>
#include <thmlhtmlhref.h>
#include <swmodule.h>
+#include <utilxml.h>
+#include <versekey.h>
+SWORD_NAMESPACE_START
-ThMLHTMLHREF::ThMLHTMLHREF() {
- setTokenStart("<");
- setTokenEnd(">");
-/*
- setEscapeStart("&");
- setEscapeEnd(";");
- setEscapeStringCaseSensitive(true);
+ThMLHTMLHREF::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) {
+ if (module) {
+ version = module->Name();
+ BiblicalText = (!strcmp(module->Type(), "Biblical Texts"));
+ }
+}
- addEscapeStringSubstitute("nbsp", " ");
- addEscapeStringSubstitute("quot", "\"");
- addEscapeStringSubstitute("amp", "&");
- addEscapeStringSubstitute("lt", "<");
- addEscapeStringSubstitute("gt", ">");
- addEscapeStringSubstitute("brvbar", "|");
- addEscapeStringSubstitute("sect", "§");
- addEscapeStringSubstitute("copy", "©");
- addEscapeStringSubstitute("laquo", "«");
- addEscapeStringSubstitute("reg", "®");
- addEscapeStringSubstitute("acute", "´");
- addEscapeStringSubstitute("para", "¶");
- addEscapeStringSubstitute("raquo", "»");
- addEscapeStringSubstitute("Aacute", "Á");
- addEscapeStringSubstitute("Agrave", "À");
- addEscapeStringSubstitute("Acirc", "Â");
- addEscapeStringSubstitute("Auml", "Ä");
- addEscapeStringSubstitute("Atilde", "Ã");
- addEscapeStringSubstitute("Aring", "Å");
- addEscapeStringSubstitute("aacute", "á");
- addEscapeStringSubstitute("agrave", "à");
- addEscapeStringSubstitute("acirc", "â");
- addEscapeStringSubstitute("auml", "ä");
- addEscapeStringSubstitute("atilde", "ã");
- addEscapeStringSubstitute("aring", "å");
- addEscapeStringSubstitute("Eacute", "É");
- addEscapeStringSubstitute("Egrave", "È");
- addEscapeStringSubstitute("Ecirc", "Ê");
- addEscapeStringSubstitute("Euml", "Ë");
- addEscapeStringSubstitute("eacute", "é");
- addEscapeStringSubstitute("egrave", "è");
- addEscapeStringSubstitute("ecirc", "ê");
- addEscapeStringSubstitute("euml", "ë");
- addEscapeStringSubstitute("Iacute", "Í");
- addEscapeStringSubstitute("Igrave", "Ì");
- addEscapeStringSubstitute("Icirc", "Î");
- addEscapeStringSubstitute("Iuml", "Ï");
- addEscapeStringSubstitute("iacute", "í");
- addEscapeStringSubstitute("igrave", "ì");
- addEscapeStringSubstitute("icirc", "î");
- addEscapeStringSubstitute("iuml", "ï");
- addEscapeStringSubstitute("Oacute", "Ó");
- addEscapeStringSubstitute("Ograve", "Ò");
- addEscapeStringSubstitute("Ocirc", "Ô");
- addEscapeStringSubstitute("Ouml", "Ö");
- addEscapeStringSubstitute("Otilde", "Õ");
- addEscapeStringSubstitute("oacute", "ó");
- addEscapeStringSubstitute("ograve", "ò");
- addEscapeStringSubstitute("ocirc", "ô");
- addEscapeStringSubstitute("ouml", "ö");
- addEscapeStringSubstitute("otilde", "õ");
- addEscapeStringSubstitute("Uacute", "Ú");
- addEscapeStringSubstitute("Ugrave", "Ù");
- addEscapeStringSubstitute("Ucirc", "Û");
- addEscapeStringSubstitute("Uuml", "Ü");
- addEscapeStringSubstitute("uacute", "ú");
- addEscapeStringSubstitute("ugrave", "ù");
- addEscapeStringSubstitute("ucirc", "û");
- addEscapeStringSubstitute("uuml", "ü");
- addEscapeStringSubstitute("Yacute", "Ý");
- addEscapeStringSubstitute("yacute", "ý");
- addEscapeStringSubstitute("yuml", "ÿ");
+ThMLHTMLHREF::ThMLHTMLHREF() {
+ setTokenStart("<");
+ setTokenEnd(">");
- addEscapeStringSubstitute("deg", "°");
- addEscapeStringSubstitute("plusmn", "±");
- addEscapeStringSubstitute("sup2", "²");
- addEscapeStringSubstitute("sup3", "³");
- addEscapeStringSubstitute("sup1", "¹");
- addEscapeStringSubstitute("nbsp", "º");
- addEscapeStringSubstitute("pound", "£");
- addEscapeStringSubstitute("cent", "¢");
- addEscapeStringSubstitute("frac14", "¼");
- addEscapeStringSubstitute("frac12", "½");
- addEscapeStringSubstitute("frac34", "¾");
- addEscapeStringSubstitute("iquest", "¿");
- addEscapeStringSubstitute("iexcl", "¡");
- addEscapeStringSubstitute("ETH", "Ð");
- addEscapeStringSubstitute("eth", "ð");
- addEscapeStringSubstitute("THORN", "Þ");
- addEscapeStringSubstitute("thorn", "þ");
- addEscapeStringSubstitute("AElig", "Æ");
- addEscapeStringSubstitute("aelig", "æ");
- addEscapeStringSubstitute("Oslash", "Ø");
- addEscapeStringSubstitute("curren", "¤");
- addEscapeStringSubstitute("Ccedil", "Ç");
- addEscapeStringSubstitute("ccedil", "ç");
- addEscapeStringSubstitute("szlig", "ß");
- addEscapeStringSubstitute("Ntilde", "Ñ");
- addEscapeStringSubstitute("ntilde", "ñ");
- addEscapeStringSubstitute("yen", "¥");
- addEscapeStringSubstitute("not", "¬");
- addEscapeStringSubstitute("ordf", "ª");
- addEscapeStringSubstitute("uml", "¨");
- addEscapeStringSubstitute("shy", "­");
- addEscapeStringSubstitute("macr", "¯");
-*/
setTokenCaseSensitive(true);
-
- addTokenSubstitute("note", " <font color=\"#800000\"><small>(");
- addTokenSubstitute("/note", ")</small></font> ");
+ addTokenSubstitute("scripture", "<i> ");
addTokenSubstitute("/scripture", "</i> ");
}
-bool ThMLHTMLHREF::handleToken(char **buf, const char *token, DualStringMap &userData) {
+bool ThMLHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) {
const char *tok;
- if (!substituteToken(buf, token)) {
- // manually process if it wasn't a simple substitution
- if (!strncmp(token, "sync ", 5)) {
- pushString(buf, "<a href=\"");
- for (tok = token + 5; *(tok+1); tok++)
- if(*tok != '\"')
- *(*buf)++ = *tok;
- *(*buf)++ = '\"';
- *(*buf)++ = '>';
-
- //scan for value and add it to the buffer
- for (tok = token + 5; *tok; tok++) {
- if (!strncmp(tok, "value=\"", 7)) {
- tok += 7;
- for (;*tok != '\"'; tok++)
- *(*buf)++ = *tok;
- break;
- }
+ if (!substituteToken(buf, token)) { // manually process if it wasn't a simple substitution
+ MyUserData *u = (MyUserData *)userData;
+
+ XMLTag tag(token);
+ if ((!tag.isEndTag()) && (!tag.isEmpty()))
+ u->startTag = tag;
+
+ if (tag.getName() && !strcmp(tag.getName(), "sync")) {
+ SWBuf value = tag.getAttribute("value");
+ if (tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "morph")) { //&gt;
+ buf += "<small><em>(<a href=\"";
+ buf += "type=";
+ buf += tag.getAttribute("type");
+
+ //const char* value = tag.getAttribute("value");
+ buf += " value=";
+ buf += (value.length()) ? value.c_str() : "";
+ buf += "\">";
+ buf += (value.length()) ? value.c_str() : "";
+ buf += "</a>) </em></small>";
+ }
+ else if (tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "Strongs")) {
+ buf += "<small><em>&lt;<a href=\"";
+ buf += "type=";
+ buf += tag.getAttribute("type");
+
+ //const char* value = tag.getAttribute("value");
+ buf += " value=";
+ buf += (value.length()) ? value.c_str() : "";
+ buf += "\">";
+ value<<1;
+ buf += (value.length()) ? value.c_str() : "";
+ buf += "</a>&gt; </em></small>";
+ }
+ else if (tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "Dict")) {
+ if (!tag.isEndTag())
+ buf += "<b>";
+ else buf += "</b>";
}
- pushString(buf, "</a>");
+
}
-
- else if (!strncmp(token, "scripture ", 10)) {
- userData["inscriptRef"] = "true";
- pushString(buf, "<i>");
- }
-
- else if (!strncmp(token, "scripRef p", 10) || !strncmp(token, "scripRef v", 10)) {
- userData["inscriptRef"] = "true";
- pushString(buf, "<a href=\"");
- for (const char *tok = token + 9; *(tok+1); tok++)
- if(*tok != '\"')
- *(*buf)++ = *tok;
- *(*buf)++ = '\"';
- *(*buf)++ = '>';
- }
-
- // we're starting a scripRef like "<scripRef>John 3:16</scripRef>"
- else if (!strcmp(token, "scripRef")) {
- userData["inscriptRef"] = "false";
- // let's stop text from going to output
- userData["suspendTextPassThru"] = "true";
+ // <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("<a href=\"noteID=%s.%c.%s\"><small><sup>*%c</sup></small></a> ", vkey->getText(), ch, footnoteNumber.c_str(), ch);
+ }
+ u->suspendTextPassThru = true;
+ }
+ }
+ if (tag.isEndTag()) {
+ u->suspendTextPassThru = false;
+ }
}
-
- // we've ended a scripRef
- else if (!strcmp(token, "/scripRef")) {
- if (userData["inscriptRef"] == "true") { // like "<scripRef passage="John 3:16">John 3:16</scripRef>"
- userData["inscriptRef"] = "false";
- pushString(buf, "</a>");
+ // <scripRef> tag
+ else if (!strcmp(tag.getName(), "scripRef")) {
+ if (!tag.isEndTag()) {
+ if (!tag.isEmpty()) {
+ u->suspendTextPassThru = true;
+ }
}
-
- else { // like "<scripRef>John 3:16</scripRef>"
- pushString(buf, "<a href=\"passage=");
- //char *strbuf = (char *)userData["lastTextNode"].c_str();
- pushString(buf, userData["lastTextNode"].c_str());
- *(*buf)++ = '\"';
- *(*buf)++ = '>';
- pushString(buf, userData["lastTextNode"].c_str());
+ 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 += "&nbsp<a href=\"";
+ if (version.length()) {
+ buf += "version=";
+ buf += version;
+ buf += " ";
+ }
+ buf += "passage=";
+ buf += refList.c_str();
+ buf += "\">";
+ buf += u->lastTextNode.c_str();
+ buf += "</a>&nbsp";
+ }
+ 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("<a href=\"noteID=%s.x.%s\"><small><sup>*x</sup></small></a> ", vkey->getText(), footnoteNumber.c_str());
+ }
+ }
+
// let's let text resume to output again
- userData["suspendTextPassThru"] = "false";
- pushString(buf, "</a>");
+ u->suspendTextPassThru = false;
}
}
-
- else if (!strncmp(token, "div class=\"sechead\"", 19)) {
- userData["SecHead"] = "true";
- pushString(buf, "<br /><b><i>");
- }
- else if (!strncmp(token, "div class=\"title\"", 19)) {
- userData["SecHead"] = "true";
- pushString(buf, "<br /><b><i>");
- }
- else if (!strncmp(token, "/div", 4)) {
- if (userData["SecHead"] == "true") {
- pushString(buf, "</i></b><br />");
- userData["SecHead"] = "false";
+ else if (tag.getName() && !strcmp(tag.getName(), "div")) {
+ if (tag.isEndTag() && u->SecHead) {
+ buf += "</i></b><br />";
+ u->SecHead = false;
+ }
+ else if (tag.getAttribute("class")) {
+ if (!stricmp(tag.getAttribute("class"), "sechead")) {
+ u->SecHead = true;
+ buf += "<br /><b><i>";
+ }
+ else if (!stricmp(tag.getAttribute("class"), "title")) {
+ u->SecHead = true;
+ buf += "<br /><b><i>";
+ }
}
}
-
- else if (!strncmp(token, "sync type=\"Strongs\" value=\"T", 28)) {
- pushString(buf, "<a href=\"");
- for (tok = token + 5; *(tok+1); tok++)
- if(*tok != '\"')
- *(*buf)++ = *tok;
- *(*buf)++ = '\"';
- *(*buf)++ = '>';
- for (tok = token + 29; *(tok+2); tok++)
- if(*tok != '\"')
- *(*buf)++ = *tok;
- pushString(buf, "</a>");
- }
- else if (!strncmp(token, "img ", 4)) {
+ else if (tag.getName() && (!strcmp(tag.getName(), "img") || !strcmp(tag.getName(), "image"))) {
const char *src = strstr(token, "src");
if (!src) // assert we have a src attribute
return false;
- *(*buf)++ = '<';
+ buf += '<';
for (const char *c = token; *c; c++) {
if (c == src) {
for (;((*c) && (*c != '"')); c++)
- *(*buf)++ = *c;
+ buf += *c;
if (!*c) { c--; continue; }
- *(*buf)++ = '"';
+ buf += '"';
if (*(c+1) == '/') {
- pushString(buf, "file:");
- pushString(buf, module->getConfigEntry("AbsoluteDataPath"));
- if (*((*buf)-1) == '/')
+ buf += "file:";
+ buf += userData->module->getConfigEntry("AbsoluteDataPath");
+ if (buf[buf.length()-2] == '/')
c++; // skip '/'
}
continue;
}
- *(*buf)++ = *c;
+ buf += *c;
}
- *(*buf)++ = '>';
+ buf += '>';
}
- else if (!strncmp(token, "note", 4)) {
- pushString(buf, " <small><font color=\"#800000\">(");
- }
else {
- *(*buf)++ = '<';
- for (const char *tok = token; *tok; tok++)
- *(*buf)++ = *tok;
- *(*buf)++ = '>';
+ buf += '<';
+ /*for (const char *tok = token; *tok; tok++)
+ buf += *tok;*/
+ buf += token;
+ buf += '>';
//return false; // we still didn't handle token
}
}
return true;
}
+
+SWORD_NAMESPACE_END