[sword-svn] r2628 - in trunk: examples/cmdline include src/mgr src/modules/filters tests
scribe at crosswire.org
scribe at crosswire.org
Tue Jun 28 13:40:34 MST 2011
Author: scribe
Date: 2011-06-28 13:40:34 -0700 (Tue, 28 Jun 2011)
New Revision: 2628
Added:
trunk/include/gbfxhtml.h
trunk/include/osisxhtml.h
trunk/include/thmlxhtml.h
trunk/src/modules/filters/gbfxhtml.cpp
trunk/src/modules/filters/osisxhtml.cpp
trunk/src/modules/filters/thmlxhtml.cpp
Modified:
trunk/examples/cmdline/lookup.cpp
trunk/include/defs.h
trunk/include/gbfwebif.h
trunk/include/osiswebif.h
trunk/include/swfilter.h
trunk/include/thmlwebif.h
trunk/src/mgr/markupfiltmgr.cpp
trunk/src/modules/filters/Makefile.am
trunk/src/modules/filters/gbfwebif.cpp
trunk/src/modules/filters/osishtmlhref.cpp
trunk/src/modules/filters/osiswebif.cpp
trunk/src/modules/filters/thmlwebif.cpp
trunk/tests/Makefile.am
Log:
Added new filter set XHTML
Modified: trunk/examples/cmdline/lookup.cpp
===================================================================
--- trunk/examples/cmdline/lookup.cpp 2011-06-23 10:24:07 UTC (rev 2627)
+++ trunk/examples/cmdline/lookup.cpp 2011-06-28 20:40:34 UTC (rev 2628)
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <swmgr.h>
#include <swmodule.h>
+#include <swfilter.h>
#include <markupfiltmgr.h>
#include <versekey.h>
@@ -38,6 +39,7 @@
using sword::AttributeList;
using sword::AttributeValue;
using sword::VerseKey;
+using sword::FilterList;
int main(int argc, char **argv)
{
@@ -87,6 +89,11 @@
std::cout << target->getRawEntry();
std::cout << "\n";
std::cout << "==Render=Entry============\n";
+ FilterList::const_iterator first = target->getRenderFilters().begin();
+ if (first != target->getRenderFilters().end()) {
+ std::cout << (*first)->getHeader();
+ std::cout << "\n";
+ }
std::cout << target->RenderText();
std::cout << "\n";
std::cout << "==========================\n";
Modified: trunk/include/defs.h
===================================================================
--- trunk/include/defs.h 2011-06-23 10:24:07 UTC (rev 2627)
+++ trunk/include/defs.h 2011-06-28 20:40:34 UTC (rev 2628)
@@ -109,7 +109,7 @@
#endif
enum {DIRECTION_LTR = 0, DIRECTION_RTL, DIRECTION_BIDI};
-enum {FMT_UNKNOWN = 0, FMT_PLAIN, FMT_THML, FMT_GBF, FMT_HTML, FMT_HTMLHREF, FMT_RTF, FMT_OSIS, FMT_WEBIF, FMT_TEI};
+enum {FMT_UNKNOWN = 0, FMT_PLAIN, FMT_THML, FMT_GBF, FMT_HTML, FMT_HTMLHREF, FMT_RTF, FMT_OSIS, FMT_WEBIF, FMT_TEI, FMT_XHTML};
enum {ENC_UNKNOWN = 0, ENC_LATIN1, ENC_UTF8, ENC_UTF16, ENC_RTF, ENC_HTML};
SWORD_NAMESPACE_END
Modified: trunk/include/gbfwebif.h
===================================================================
--- trunk/include/gbfwebif.h 2011-06-23 10:24:07 UTC (rev 2627)
+++ trunk/include/gbfwebif.h 2011-06-28 20:40:34 UTC (rev 2628)
@@ -21,13 +21,13 @@
#ifndef GBFWEBIF_H
#define GBFWEBIF_H
-#include <gbfhtmlhref.h>
+#include <gbfxhtml.h>
SWORD_NAMESPACE_START
-/** this filter converts GBF text to HTML text with hrefs
+/** this filter converts GBF text to classed XHTML for web interfaces
*/
-class SWDLLEXPORT GBFWEBIF : public GBFHTMLHREF {
+class SWDLLEXPORT GBFWEBIF : public GBFXHTML {
const SWBuf baseURL;
const SWBuf passageStudyURL;
Added: trunk/include/gbfxhtml.h
===================================================================
--- trunk/include/gbfxhtml.h (rev 0)
+++ trunk/include/gbfxhtml.h 2011-06-28 20:40:34 UTC (rev 2628)
@@ -0,0 +1,48 @@
+/******************************************************************************
+ *
+ * gbfxhtmlhref.h
+ *
+ * Copyright 2011 CrossWire Bible Society (http://www.crosswire.org)
+ * CrossWire Bible Society
+ * P. O. Box 2528
+ * Tempe, AZ 85280-2528
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#ifndef GBFXHTML_H
+#define GBFXHTML_H
+
+#include <swbasicfilter.h>
+
+SWORD_NAMESPACE_START
+
+/** this filter converts GBF text to classed XHTML text
+ */
+class SWDLLEXPORT GBFXHTML : public SWBasicFilter {
+protected:
+ class MyUserData : public BasicFilterUserData {
+ public:
+ MyUserData(const SWModule *module, const SWKey *key);
+ bool hasFootnotePreTag;
+ SWBuf version;
+ };
+ virtual BasicFilterUserData *createUserData(const SWModule *module, const SWKey *key) {
+ return new MyUserData(module, key);
+ }
+ virtual bool handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData);
+public:
+ GBFXHTML();
+ virtual const char *getHeader() const;
+};
+
+SWORD_NAMESPACE_END
+#endif
Modified: trunk/include/osiswebif.h
===================================================================
--- trunk/include/osiswebif.h 2011-06-23 10:24:07 UTC (rev 2627)
+++ trunk/include/osiswebif.h 2011-06-28 20:40:34 UTC (rev 2628)
@@ -21,13 +21,13 @@
#ifndef OSISWEBIF_H
#define OSISWEBIF_H
-#include <osishtmlhref.h>
+#include <osisxhtml.h>
SWORD_NAMESPACE_START
/** this filter converts OSIS text to HTML text with hrefs
*/
-class SWDLLEXPORT OSISWEBIF : public OSISHTMLHREF {
+class SWDLLEXPORT OSISWEBIF : public OSISXHTML {
const SWBuf baseURL;
const SWBuf passageStudyURL;
bool javascript;
Added: trunk/include/osisxhtml.h
===================================================================
--- trunk/include/osisxhtml.h (rev 0)
+++ trunk/include/osisxhtml.h 2011-06-28 20:40:34 UTC (rev 2628)
@@ -0,0 +1,65 @@
+/******************************************************************************
+ *
+ * osisxhtml.h
+ *
+ * Copyright 2011 CrossWire Bible Society (http://www.crosswire.org)
+ * CrossWire Bible Society
+ * P. O. Box 2528
+ * Tempe, AZ 85280-2528
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#ifndef OSISXHTML_H
+#define OSISXHTML_H
+
+#include <swbasicfilter.h>
+
+SWORD_NAMESPACE_START
+
+/** this filter converts OSIS text to classed XHTML
+ */
+class SWDLLEXPORT OSISXHTML : public SWBasicFilter {
+private:
+ bool morphFirst;
+protected:
+ // used by derived classes so we have it in the header
+ class TagStacks;
+ class SWDLLEXPORT MyUserData : public BasicFilterUserData {
+ public:
+ bool osisQToTick;
+ bool inBold; // TODO: obsolete. left for binary compat for 1.6.x
+ bool inXRefNote;
+ bool BiblicalText;
+ int suspendLevel;
+ SWBuf wordsOfChristStart;
+ SWBuf wordsOfChristEnd;
+ TagStacks *tagStacks; // TODO: modified to wrap all TagStacks necessary for this filter until 1.7.x
+// TagStack *hiStack; // TODO: commented out for binary compat for 1.6.x wrapped in tagStacks until 1.7.x
+ SWBuf lastTransChange;
+ SWBuf w;
+ SWBuf fn;
+ SWBuf version;
+ MyUserData(const SWModule *module, const SWKey *key);
+ ~MyUserData();
+ };
+ virtual BasicFilterUserData *createUserData(const SWModule *module, const SWKey *key) {
+ return new MyUserData(module, key);
+ }
+ virtual bool handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData);
+public:
+ OSISXHTML();
+ void setMorphFirst(bool val = true) { morphFirst = val; }
+ virtual const char *getHeader() const;
+};
+
+SWORD_NAMESPACE_END
+#endif
Modified: trunk/include/swfilter.h
===================================================================
--- trunk/include/swfilter.h 2011-06-23 10:24:07 UTC (rev 2627)
+++ trunk/include/swfilter.h 2011-06-28 20:40:34 UTC (rev 2628)
@@ -42,13 +42,21 @@
public:
virtual ~SWFilter() {}
- /** This is the main filter function
+ /** This method processes and appropriately modifies the text given it
+ * for a particular filter task
+ *
* @param text The text to be filtered/converted
* @param key Current key That was used.
* @param module Current module.
* @return 0
*/
virtual char processText(SWBuf &text, const SWKey *key = 0, const SWModule *module = 0) = 0;
+
+ /** This method can supply a header associated with the processing done with this filter.
+ * A typical example is a suggested CSS style block for classed containers.
+ * @param text The text to be filtered/converted
+ */
+ virtual const char *getHeader() const { return ""; }
};
SWORD_NAMESPACE_END
Modified: trunk/include/thmlwebif.h
===================================================================
--- trunk/include/thmlwebif.h 2011-06-23 10:24:07 UTC (rev 2627)
+++ trunk/include/thmlwebif.h 2011-06-28 20:40:34 UTC (rev 2628)
@@ -21,13 +21,13 @@
#ifndef _ThMLWEBIF_H
#define _ThMLWEBIF_H
-#include <thmlhtmlhref.h>
+#include <thmlxhtml.h>
SWORD_NAMESPACE_START
/** this filter converts ThML text to HTML text with hrefs
*/
-class SWDLLEXPORT ThMLWEBIF : public ThMLHTMLHREF {
+class SWDLLEXPORT ThMLWEBIF : public ThMLXHTML {
const SWBuf baseURL;
const SWBuf passageStudyURL;
@@ -36,5 +36,7 @@
public:
ThMLWEBIF();
};
+
SWORD_NAMESPACE_END
-#endif /* _ThMLWEBIF_H */
+
+#endif
Added: trunk/include/thmlxhtml.h
===================================================================
--- trunk/include/thmlxhtml.h (rev 0)
+++ trunk/include/thmlxhtml.h 2011-06-28 20:40:34 UTC (rev 2628)
@@ -0,0 +1,56 @@
+/******************************************************************************
+ *
+ * $Id: thmlhtmlhref.h 2157 2008-05-13 23:37:56Z scribe $
+ *
+ * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org)
+ * CrossWire Bible Society
+ * P. O. Box 2528
+ * Tempe, AZ 85280-2528
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#ifndef _THMLXHTML_H
+#define _THMLXHTML_H
+
+#include <swbasicfilter.h>
+#include <utilxml.h>
+
+SWORD_NAMESPACE_START
+
+/** this filter converts ThML text to classed XHTML
+ */
+class SWDLLEXPORT ThMLXHTML : public SWBasicFilter {
+ SWBuf imgPrefix;
+protected:
+ class MyUserData : public BasicFilterUserData {
+ public:
+ MyUserData(const SWModule *module, const SWKey *key);//: BasicFilterUserData(module, key) {}
+ bool inscriptRef;
+ bool SecHead;
+ bool BiblicalText;
+ SWBuf version;
+ XMLTag startTag;
+ };
+ virtual BasicFilterUserData *createUserData(const SWModule *module, const SWKey *key) {
+ return new MyUserData(module, key);
+ }
+ virtual bool handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData);
+public:
+ ThMLXHTML();
+ virtual const char *getImagePrefix() { return imgPrefix.c_str(); }
+ virtual void setImagePrefix(const char *newImgPrefix) { imgPrefix = newImgPrefix; }
+ virtual const char *getHeader() const;
+};
+
+SWORD_NAMESPACE_END
+
+#endif
Modified: trunk/src/mgr/markupfiltmgr.cpp
===================================================================
--- trunk/src/mgr/markupfiltmgr.cpp 2011-06-23 10:24:07 UTC (rev 2627)
+++ trunk/src/mgr/markupfiltmgr.cpp 2011-06-28 20:40:34 UTC (rev 2628)
@@ -43,6 +43,9 @@
#include <thmlwebif.h>
#include <osiswebif.h>
#include <swmodule.h>
+#include <thmlxhtml.h>
+#include <gbfxhtml.h>
+#include <osisxhtml.h>
#include <markupfiltmgr.h>
@@ -288,6 +291,13 @@
fromosis = NULL;
fromtei = NULL;
break;
+ case FMT_XHTML:
+ fromplain = NULL;
+ fromthml = new ThMLXHTML();
+ fromgbf = new GBFXHTML();
+ fromosis = new OSISXHTML();
+ fromtei = NULL;
+ break;
}
}
Modified: trunk/src/modules/filters/Makefile.am
===================================================================
--- trunk/src/modules/filters/Makefile.am 2011-06-23 10:24:07 UTC (rev 2627)
+++ trunk/src/modules/filters/Makefile.am 2011-06-28 20:40:34 UTC (rev 2628)
@@ -5,6 +5,7 @@
GBFFIL = $(filtersdir)/gbfhtml.cpp
GBFFIL += $(filtersdir)/gbfhtmlhref.cpp
+GBFFIL += $(filtersdir)/gbfxhtml.cpp
GBFFIL += $(filtersdir)/gbfwebif.cpp
GBFFIL += $(filtersdir)/gbfplain.cpp
GBFFIL += $(filtersdir)/gbfrtf.cpp
@@ -26,6 +27,7 @@
THMLFIL += $(filtersdir)/thmlrtf.cpp
THMLFIL += $(filtersdir)/thmlhtml.cpp
THMLFIL += $(filtersdir)/thmlhtmlhref.cpp
+THMLFIL += $(filtersdir)/thmlxhtml.cpp
THMLFIL += $(filtersdir)/thmlwebif.cpp
THMLFIL += $(filtersdir)/thmlwordjs.cpp
@@ -42,6 +44,7 @@
OSISFIL = $(filtersdir)/osisheadings.cpp
OSISFIL += $(filtersdir)/osisfootnotes.cpp
OSISFIL += $(filtersdir)/osishtmlhref.cpp
+OSISFIL += $(filtersdir)/osisxhtml.cpp
OSISFIL += $(filtersdir)/osiswebif.cpp
OSISFIL += $(filtersdir)/osismorph.cpp
OSISFIL += $(filtersdir)/osisstrongs.cpp
Modified: trunk/src/modules/filters/gbfwebif.cpp
===================================================================
--- trunk/src/modules/filters/gbfwebif.cpp 2011-06-23 10:24:07 UTC (rev 2627)
+++ trunk/src/modules/filters/gbfwebif.cpp 2011-06-28 20:40:34 UTC (rev 2628)
@@ -29,9 +29,6 @@
SWORD_NAMESPACE_START
GBFWEBIF::GBFWEBIF() : baseURL(""), passageStudyURL(baseURL + "passagestudy.jsp") {
-//all is done in GBFHTMLHREF since it inherits form this class
- addTokenSubstitute("FR", "<span class=\"wordsOfJesus\">"); // words of Jesus begin
- addTokenSubstitute("Fr", "</span>");
}
bool GBFWEBIF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) {
@@ -189,7 +186,7 @@
}
else {
- return GBFHTMLHREF::handleToken(buf, token, userData);
+ return GBFXHTML::handleToken(buf, token, userData);
}
}
return true;
Added: trunk/src/modules/filters/gbfxhtml.cpp
===================================================================
--- trunk/src/modules/filters/gbfxhtml.cpp (rev 0)
+++ trunk/src/modules/filters/gbfxhtml.cpp 2011-06-28 20:40:34 UTC (rev 2628)
@@ -0,0 +1,232 @@
+/******************************************************************************
+ *
+ * gbfxhtml.cpp - GBF to classed XHTML
+ *
+ *
+ * Copyright 2011 CrossWire Bible Society (http://www.crosswire.org)
+ * CrossWire Bible Society
+ * P. O. Box 2528
+ * Tempe, AZ 85280-2528
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
+
+
+#include <stdlib.h>
+#include <gbfxhtml.h>
+#include <swmodule.h>
+#include <utilxml.h>
+#include <versekey.h>
+#include <ctype.h>
+#include <url.h>
+
+SWORD_NAMESPACE_START
+
+const char *GBFXHTML::getHeader() const {
+ return "\
+ .wordsOfJesus {\
+ color: red;\
+ }\
+ ";
+}
+
+GBFXHTML::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) {
+ if (module) {
+ version = module->Name();
+ }
+}
+
+GBFXHTML::GBFXHTML() {
+ setTokenStart("<");
+ setTokenEnd(">");
+
+ setTokenCaseSensitive(true);
+
+ //addTokenSubstitute("Rf", ")</small></font>");
+ addTokenSubstitute("FA", "<font color=\"#800000\">"); // for ASV footnotes to mark text
+ addTokenSubstitute("Rx", "</a>");
+ addTokenSubstitute("FI", "<i>"); // italics begin
+ addTokenSubstitute("Fi", "</i>");
+ addTokenSubstitute("FB", "<b>"); // bold begin
+ addTokenSubstitute("Fb", "</b>");
+ addTokenSubstitute("FR", "<span class=\"wordsOfJesus\">"); // words of Jesus begin
+ addTokenSubstitute("Fr", "</span>");
+ addTokenSubstitute("FU", "<u>"); // underline begin
+ addTokenSubstitute("Fu", "</u>");
+ addTokenSubstitute("FO", "<cite>"); // Old Testament quote begin
+ addTokenSubstitute("Fo", "</cite>");
+ addTokenSubstitute("FS", "<sup>"); // Superscript begin// Subscript begin
+ addTokenSubstitute("Fs", "</sup>");
+ addTokenSubstitute("FV", "<sub>"); // Subscript begin
+ addTokenSubstitute("Fv", "</sub>");
+ addTokenSubstitute("TT", "<big>"); // Book title begin
+ addTokenSubstitute("Tt", "</big>");
+ addTokenSubstitute("PP", "<cite>"); // poetry begin
+ addTokenSubstitute("Pp", "</cite>");
+ addTokenSubstitute("Fn", "</font>"); // font end
+ addTokenSubstitute("CL", "<br />"); // new line
+ addTokenSubstitute("CM", "<!P><br />"); // paragraph <!P> is a non showing comment that can be changed in the front end to <P> if desired
+ addTokenSubstitute("CG", ""); // ???
+ addTokenSubstitute("CT", ""); // ???
+ addTokenSubstitute("JR", "<div align=\"right\">"); // right align begin
+ addTokenSubstitute("JC", "<div align=\"center\">"); // center align begin
+ addTokenSubstitute("JL", "</div>"); // align end
+
+}
+
+
+bool GBFXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) {
+ const char *tok;
+ MyUserData *u = (MyUserData *)userData;
+
+ if (!substituteToken(buf, token)) {
+ XMLTag tag(token);
+
+ if (!strncmp(token, "WG", 2)) { // strong's numbers
+ //buf += " <small><em><<a href=\"type=Strongs value=";
+ buf += " <small><em class=\"strongs\"><<a href=\"passagestudy.jsp?action=showStrongs&type=Greek&value=";
+ for (tok = token+2; *tok; tok++)
+ //if(token[i] != '\"')
+ buf += *tok;
+ buf += "\" class=\"strongs\">";
+ for (tok = token + 2; *tok; tok++)
+ //if(token[i] != '\"')
+ buf += *tok;
+ buf += "</a>></em></small>";
+ }
+ else if (!strncmp(token, "WH", 2)) { // strong's numbers
+ //buf += " <small><em><<a href=\"type=Strongs value=";
+ buf += " <small><em class=\"strongs\"><<a href=\"passagestudy.jsp?action=showStrongs&type=Hebrew&value=";
+ for (tok = token+2; *tok; tok++)
+ //if(token[i] != '\"')
+ buf += *tok;
+ buf += "\" class=\"strongs\">";
+ for (tok = token + 2; *tok; tok++)
+ //if(token[i] != '\"')
+ buf += *tok;
+ buf += "</a>></em></small>";
+ }
+ else if (!strncmp(token, "WTG", 3)) { // strong's numbers tense
+ //buf += " <small><em>(<a href=\"type=Strongs value=";
+ buf += " <small><em class=\"strongs\">(<a href=\"passagestudy.jsp?action=showStrongs&type=Greek&value=";
+ for (tok = token + 3; *tok; tok++)
+ if(*tok != '\"')
+ buf += *tok;
+ buf += "\" class=\"strongs\">";
+ for (tok = token + 3; *tok; tok++)
+ if(*tok != '\"')
+ buf += *tok;
+ buf += "</a>)</em></small>";
+ }
+ else if (!strncmp(token, "WTH", 3)) { // strong's numbers tense
+ //buf += " <small><em>(<a href=\"type=Strongs value=";
+ buf += " <small><em class=\"strongs\">(<a href=\"passagestudy.jsp?action=showStrongs&type=Hebrew&value=";
+ for (tok = token + 3; *tok; tok++)
+ if(*tok != '\"')
+ buf += *tok;
+ buf += "\" class=\"strongs\">";
+ for (tok = token + 3; *tok; tok++)
+ if(*tok != '\"')
+ buf += *tok;
+ buf += "</a>)</em></small>";
+ }
+
+ else if (!strncmp(token, "WT", 2) && strncmp(token, "WTH", 3) && strncmp(token, "WTG", 3)) { // morph tags
+ //buf += " <small><em>(<a href=\"type=morph class=none value=";
+ buf += " <small><em class=\"morph\">(<a href=\"passagestudy.jsp?action=showMorph&type=Greek&value=";
+
+ for (tok = token + 2; *tok; tok++)
+ if(*tok != '\"')
+ buf += *tok;
+ buf += "\" class=\"morph\">";
+ for (tok = token + 2; *tok; tok++)
+ if(*tok != '\"')
+ buf += *tok;
+ buf += "</a>)</em></small>";
+ }
+
+ else if (!strcmp(tag.getName(), "RX")) {
+ buf += "<a href=\"";
+ for (tok = token + 3; *tok; tok++) {
+ if(*tok != '<' && *tok+1 != 'R' && *tok+2 != 'x') {
+ buf += *tok;
+ }
+ else {
+ break;
+ }
+ }
+ buf += "\">";
+ }
+ else if (!strcmp(tag.getName(), "RF")) {
+ SWBuf type = tag.getAttribute("type");
+ SWBuf footnoteNumber = tag.getAttribute("swordFootnote");
+ VerseKey *vkey = NULL;
+ // see if we have a VerseKey * or descendant
+ SWTRY {
+ vkey = SWDYNAMIC_CAST(VerseKey, u->key);
+ }
+ SWCATCH ( ... ) { }
+ 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=\"passagestudy.jsp?action=showNote&type=n&value=%s&module=%s&passage=%s\"><small><sup class=\"n\">*n</sup></small></a> ",
+ URL::encode(footnoteNumber.c_str()).c_str(),
+ URL::encode(u->version.c_str()).c_str(),
+ URL::encode(vkey->getText()).c_str());
+ }
+ u->suspendTextPassThru = true;
+ }
+ else if (!strcmp(tag.getName(), "Rf")) {
+ u->suspendTextPassThru = false;
+ }
+/*
+ else if (!strncmp(token, "RB", 2)) {
+ buf += "<i> ";
+ u->hasFootnotePreTag = true;
+ }
+
+ else if (!strncmp(token, "Rf", 2)) {
+ buf += " <a href=\"note=";
+ buf += u->lastTextNode.c_str();
+ buf += "\">";
+ buf += "<small><sup>*n</sup></small></a> ";
+ // let's let text resume to output again
+ u->suspendTextPassThru = false;
+ }
+
+ else if (!strncmp(token, "RF", 2)) {
+ if (u->hasFootnotePreTag) {
+ u->hasFootnotePreTag = false;
+ buf += "</i> ";
+ }
+ u->suspendTextPassThru = true;
+ }
+*/
+ else if (!strncmp(token, "FN", 2)) {
+ buf += "<font face=\"";
+ for (tok = token + 2; *tok; tok++)
+ if(*tok != '\"')
+ buf += *tok;
+ buf += "\">";
+ }
+
+ else if (!strncmp(token, "CA", 2)) { // ASCII value
+ buf += (char)atoi(&token[2]);
+ }
+
+ else {
+ return false;
+ }
+ }
+ return true;
+}
+
+SWORD_NAMESPACE_END
Modified: trunk/src/modules/filters/osishtmlhref.cpp
===================================================================
--- trunk/src/modules/filters/osishtmlhref.cpp 2011-06-23 10:24:07 UTC (rev 2627)
+++ trunk/src/modules/filters/osishtmlhref.cpp 2011-06-28 20:40:34 UTC (rev 2628)
@@ -36,60 +36,6 @@
namespace {
typedef std::stack<SWBuf> TagStack;
-}
-
-// TODO: this bridge pattern is to preserve binary compat on 1.6.x
-class OSISHTMLHREF::TagStacks {
-public:
- TagStack quoteStack;
- TagStack hiStack;
-};
-
-OSISHTMLHREF::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) {
- inXRefNote = false;
- suspendLevel = 0;
- tagStacks = new TagStacks();
- wordsOfChristStart = "<font color=\"red\"> ";
- wordsOfChristEnd = "</font> ";
- if (module) {
- osisQToTick = ((!module->getConfigEntry("OSISqToTick")) || (strcmp(module->getConfigEntry("OSISqToTick"), "false")));
- version = module->Name();
- BiblicalText = (!strcmp(module->Type(), "Biblical Texts"));
- }
- else {
- osisQToTick = true; // default
- version = "";
- }
-}
-
-OSISHTMLHREF::MyUserData::~MyUserData() {
- delete tagStacks;
-}
-
-OSISHTMLHREF::OSISHTMLHREF() {
- setTokenStart("<");
- setTokenEnd(">");
-
- setEscapeStart("&");
- setEscapeEnd(";");
-
- setEscapeStringCaseSensitive(true);
- setPassThruNumericEscapeString(true);
-
- addAllowedEscapeString("quot");
- addAllowedEscapeString("apos");
- addAllowedEscapeString("amp");
- addAllowedEscapeString("lt");
- addAllowedEscapeString("gt");
-
- setTokenCaseSensitive(true);
-
- // addTokenSubstitute("lg", "<br />");
- // addTokenSubstitute("/lg", "<br />");
-
- morphFirst = false;
-}
-
// though this might be slightly slower, possibly causing an extra bool check, this is a renderFilter
// so speed isn't the absolute highest priority, and this is a very minor possible hit
static inline void outText(const char *t, SWBuf &o, BasicFilterUserData *u) { if (!u->suspendTextPassThru) o += t; else u->lastSuspendSegment += t; }
@@ -157,7 +103,61 @@
//}
}
}
+} // end anonymous namespace
+// TODO: this bridge pattern is to preserve binary compat on 1.6.x
+class OSISHTMLHREF::TagStacks {
+public:
+ TagStack quoteStack;
+ TagStack hiStack;
+};
+
+OSISHTMLHREF::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) {
+ inXRefNote = false;
+ suspendLevel = 0;
+ tagStacks = new TagStacks();
+ wordsOfChristStart = "<font color=\"red\"> ";
+ wordsOfChristEnd = "</font> ";
+ if (module) {
+ osisQToTick = ((!module->getConfigEntry("OSISqToTick")) || (strcmp(module->getConfigEntry("OSISqToTick"), "false")));
+ version = module->Name();
+ BiblicalText = (!strcmp(module->Type(), "Biblical Texts"));
+ }
+ else {
+ osisQToTick = true; // default
+ version = "";
+ }
+}
+
+OSISHTMLHREF::MyUserData::~MyUserData() {
+ delete tagStacks;
+}
+
+OSISHTMLHREF::OSISHTMLHREF() {
+ setTokenStart("<");
+ setTokenEnd(">");
+
+ setEscapeStart("&");
+ setEscapeEnd(";");
+
+ setEscapeStringCaseSensitive(true);
+ setPassThruNumericEscapeString(true);
+
+ addAllowedEscapeString("quot");
+ addAllowedEscapeString("apos");
+ addAllowedEscapeString("amp");
+ addAllowedEscapeString("lt");
+ addAllowedEscapeString("gt");
+
+ setTokenCaseSensitive(true);
+
+ // addTokenSubstitute("lg", "<br />");
+ // addTokenSubstitute("/lg", "<br />");
+
+ morphFirst = false;
+}
+
+
bool OSISHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) {
MyUserData *u = (MyUserData *)userData;
SWBuf scratch;
Modified: trunk/src/modules/filters/osiswebif.cpp
===================================================================
--- trunk/src/modules/filters/osiswebif.cpp 2011-06-23 10:24:07 UTC (rev 2627)
+++ trunk/src/modules/filters/osiswebif.cpp 2011-06-28 20:40:34 UTC (rev 2628)
@@ -39,8 +39,6 @@
BasicFilterUserData *OSISWEBIF::createUserData(const SWModule *module, const SWKey *key) {
MyUserData *u = new MyUserData(module, key);
- u->wordsOfChristStart = "<span class=\"wordsOfJesus\"> ";
- u->wordsOfChristEnd = "</span> ";
return u;
}
@@ -50,7 +48,8 @@
SWBuf scratch;
bool sub = (u->suspendTextPassThru) ? substituteToken(scratch, token) : substituteToken(buf, token);
if (!sub) {
- // manually process if it wasn't a simple substitution
+
+ // manually process if it wasn't a simple substitution
XMLTag tag(token);
// <w> tag
@@ -165,43 +164,10 @@
}
}
- // <title>
- else if (!strcmp(tag.getName(), "title")) {
- if ((!tag.isEndTag()) && (!tag.isEmpty())) {
- buf += "<h3>";
- }
- else if (tag.isEndTag()) {
- buf += "</h3>";
- }
- }
- // Milestoned paragraphs, created by osis2mod
- // <div type="paragraph" sID.../>
- // <div type="paragraph" eID.../>
- else if (tag.isEmpty() && !strcmp(tag.getName(), "div") && tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "paragraph")) {
- // This is properly handled by base class.
- return OSISHTMLHREF::handleToken(buf, token, userData);
- }
-
- // ok to leave these in
- else if (!strcmp(tag.getName(), "div")) {
- buf += tag;
- }
- else if (!strcmp(tag.getName(), "span")) {
- buf += tag;
- }
- else if (!strcmp(tag.getName(), "br")) {
- buf += tag;
- }
-
// handled appropriately in base class
- // <catchWord> & <rdg> tags (italicize)
- // <hi> text highlighting
- // <q> quote
- // <milestone type="cQuote" marker="x"/>
- // <transChange>
else {
- return OSISHTMLHREF::handleToken(buf, token, userData);
+ return OSISXHTML::handleToken(buf, token, userData);
}
}
return true;
Added: trunk/src/modules/filters/osisxhtml.cpp
===================================================================
--- trunk/src/modules/filters/osisxhtml.cpp (rev 0)
+++ trunk/src/modules/filters/osisxhtml.cpp 2011-06-28 20:40:34 UTC (rev 2628)
@@ -0,0 +1,644 @@
+/******************************************************************************
+ *
+ * osisxhtml - Render filter for classed XHTML
+ * of an OSIS module.
+ *
+ *
+ * Copyright 2011 CrossWire Bible Society (http://www.crosswire.org)
+ * CrossWire Bible Society
+ * P. O. Box 2528
+ * Tempe, AZ 85280-2528
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <osisxhtml.h>
+#include <utilxml.h>
+#include <utilstr.h>
+#include <versekey.h>
+#include <swmodule.h>
+#include <url.h>
+#include <stringmgr.h>
+#include <stack>
+
+SWORD_NAMESPACE_START
+
+const char *OSISXHTML::getHeader() const {
+ return "\
+ .divineName {\
+ font-variant: small-caps;\
+ }\
+ .wordsOfJesus {\
+ color: red;\
+ }\
+ ";
+}
+
+
+namespace {
+ typedef std::stack<SWBuf> TagStack;
+
+// though this might be slightly slower, possibly causing an extra bool check, this is a renderFilter
+// so speed isn't the absolute highest priority, and this is a very minor possible hit
+static inline void outText(const char *t, SWBuf &o, BasicFilterUserData *u) { if (!u->suspendTextPassThru) o += t; else u->lastSuspendSegment += t; }
+static inline void outText(char t, SWBuf &o, BasicFilterUserData *u) { if (!u->suspendTextPassThru) o += t; else u->lastSuspendSegment += t; }
+
+void processLemma(bool suspendTextPassThru, XMLTag &tag, SWBuf &buf) {
+ const char *attrib;
+ const char *val;
+ if ((attrib = tag.getAttribute("lemma"))) {
+ int count = tag.getAttributePartCount("lemma", ' ');
+ int i = (count > 1) ? 0 : -1; // -1 for whole value cuz it's faster, but does the same thing as 0
+ do {
+ attrib = tag.getAttribute("lemma", i, ' ');
+ if (i < 0) i = 0; // to handle our -1 condition
+ val = strchr(attrib, ':');
+ val = (val) ? (val + 1) : attrib;
+ SWBuf gh;
+ if(*val == 'G')
+ gh = "Greek";
+ if(*val == 'H')
+ gh = "Hebrew";
+ const char *val2 = val;
+ if ((strchr("GH", *val)) && (isdigit(val[1])))
+ val2++;
+ //if ((!strcmp(val2, "3588")) && (lastText.length() < 1))
+ // show = false;
+ //else {
+ if (!suspendTextPassThru) {
+ buf.appendFormatted("<small><em class=\"strongs\"><<a href=\"passagestudy.jsp?action=showStrongs&type=%s&value=%s\" class=\"strongs\">%s</a>></em></small>",
+ (gh.length()) ? gh.c_str() : "",
+ URL::encode(val2).c_str(),
+ val2);
+ }
+ //}
+
+ } while (++i < count);
+ }
+}
+
+void processMorph(bool suspendTextPassThru, XMLTag &tag, SWBuf &buf) {
+ const char * attrib;
+ const char *val;
+ if ((attrib = tag.getAttribute("morph"))) { // && (show)) {
+ SWBuf savelemma = tag.getAttribute("savlm");
+ //if ((strstr(savelemma.c_str(), "3588")) && (lastText.length() < 1))
+ // show = false;
+ //if (show) {
+ int count = tag.getAttributePartCount("morph", ' ');
+ int i = (count > 1) ? 0 : -1; // -1 for whole value cuz it's faster, but does the same thing as 0
+ do {
+ attrib = tag.getAttribute("morph", i, ' ');
+ if (i < 0) i = 0; // to handle our -1 condition
+ val = strchr(attrib, ':');
+ val = (val) ? (val + 1) : attrib;
+ const char *val2 = val;
+ if ((*val == 'T') && (strchr("GH", val[1])) && (isdigit(val[2])))
+ val2+=2;
+ if (!suspendTextPassThru) {
+ buf.appendFormatted("<small><em class=\"morph\">(<a href=\"passagestudy.jsp?action=showMorph&type=%s&value=%s\" class=\"morph\">%s</a>)</em></small>",
+ URL::encode(tag.getAttribute("morph")).c_str(),
+ URL::encode(val).c_str(),
+ val2);
+ }
+ } while (++i < count);
+ //}
+ }
+}
+} // end anonymous namespace
+
+
+// TODO: this bridge pattern is to preserve binary compat on 1.6.x
+class OSISXHTML::TagStacks {
+public:
+ TagStack quoteStack;
+ TagStack hiStack;
+};
+
+OSISXHTML::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) {
+ inXRefNote = false;
+ suspendLevel = 0;
+ tagStacks = new TagStacks();
+ wordsOfChristStart = "<span class=\"wordsOfJesus\"> ";
+ wordsOfChristEnd = "</span> ";
+ if (module) {
+ osisQToTick = ((!module->getConfigEntry("OSISqToTick")) || (strcmp(module->getConfigEntry("OSISqToTick"), "false")));
+ version = module->Name();
+ BiblicalText = (!strcmp(module->Type(), "Biblical Texts"));
+ }
+ else {
+ osisQToTick = true; // default
+ version = "";
+ }
+}
+
+OSISXHTML::MyUserData::~MyUserData() {
+ delete tagStacks;
+}
+
+OSISXHTML::OSISXHTML() {
+ setTokenStart("<");
+ setTokenEnd(">");
+
+ setEscapeStart("&");
+ setEscapeEnd(";");
+
+ setEscapeStringCaseSensitive(true);
+ setPassThruNumericEscapeString(true);
+
+ addAllowedEscapeString("quot");
+ addAllowedEscapeString("apos");
+ addAllowedEscapeString("amp");
+ addAllowedEscapeString("lt");
+ addAllowedEscapeString("gt");
+
+ setTokenCaseSensitive(true);
+
+ // addTokenSubstitute("lg", "<br />");
+ // addTokenSubstitute("/lg", "<br />");
+
+ morphFirst = false;
+}
+
+bool OSISXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) {
+ MyUserData *u = (MyUserData *)userData;
+ SWBuf scratch;
+ bool sub = (u->suspendTextPassThru) ? substituteToken(scratch, token) : substituteToken(buf, token);
+ if (!sub) {
+ // manually process if it wasn't a simple substitution
+ XMLTag tag(token);
+
+ // <w> tag
+ if (!strcmp(tag.getName(), "w")) {
+
+ // start <w> tag
+ if ((!tag.isEmpty()) && (!tag.isEndTag())) {
+ u->w = token;
+ }
+
+ // end or empty <w> tag
+ else {
+ bool endTag = tag.isEndTag();
+ SWBuf lastText;
+ //bool show = true; // to handle unplaced article in kjv2003-- temporary till combined
+
+ if (endTag) {
+ tag = u->w.c_str();
+ lastText = u->lastTextNode.c_str();
+ }
+ else lastText = "stuff";
+
+ const char *attrib;
+ const char *val;
+ if ((attrib = tag.getAttribute("xlit"))) {
+ val = strchr(attrib, ':');
+ val = (val) ? (val + 1) : attrib;
+ outText(" ", buf, u);
+ outText(val, buf, u);
+ }
+ if ((attrib = tag.getAttribute("gloss"))) {
+ // I'm sure this is not the cleanest way to do it, but it gets the job done
+ // for rendering ruby chars properly ^_^
+ buf -= lastText.length();
+
+ outText("<ruby><rb>", buf, u);
+ outText(lastText, buf, u);
+ val = strchr(attrib, ':');
+ val = (val) ? (val + 1) : attrib;
+ outText("</rb><rp>(</rp><rt>", buf, u);
+ outText(val, buf, u);
+ outText("</rt><rp>)</rp></ruby>", buf, u);
+ }
+ if (!morphFirst) {
+ processLemma(u->suspendTextPassThru, tag, buf);
+ processMorph(u->suspendTextPassThru, tag, buf);
+ }
+ else {
+ processMorph(u->suspendTextPassThru, tag, buf);
+ processLemma(u->suspendTextPassThru, tag, buf);
+ }
+ if ((attrib = tag.getAttribute("POS"))) {
+ val = strchr(attrib, ':');
+ val = (val) ? (val + 1) : attrib;
+ outText(" ", buf, u);
+ outText(val, buf, u);
+ }
+
+ /*if (endTag)
+ buf += "}";*/
+ }
+ }
+
+ // <note> tag
+ else if (!strcmp(tag.getName(), "note")) {
+ if (!tag.isEndTag()) {
+ SWBuf type = tag.getAttribute("type");
+ bool strongsMarkup = (type == "x-strongsMarkup" || type == "strongsMarkup"); // the latter is deprecated
+ if (strongsMarkup) {
+ tag.setEmpty(false); // handle bug in KJV2003 module where some note open tags were <note ... />
+ }
+
+ if (!tag.isEmpty()) {
+
+ if (!strongsMarkup) { // leave strong's markup notes out, in the future we'll probably have different option filters to turn different note types on or off
+ SWBuf footnoteNumber = tag.getAttribute("swordFootnote");
+ VerseKey *vkey = NULL;
+ char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n');
+
+ u->inXRefNote = true; // Why this change? Ben Morgan: Any note can have references in, so we need to set this to true for all notes
+// u->inXRefNote = (ch == 'x');
+
+ // see if we have a VerseKey * or descendant
+ SWTRY {
+ vkey = SWDYNAMIC_CAST(VerseKey, u->key);
+ }
+ SWCATCH ( ... ) { }
+ if (vkey) {
+ //printf("URL = %s\n",URL::encode(vkey->getText()).c_str());
+ buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=%c&value=%s&module=%s&passage=%s\"><small><sup class=\"%c\">*%c</sup></small></a>",
+ ch,
+ URL::encode(footnoteNumber.c_str()).c_str(),
+ URL::encode(u->version.c_str()).c_str(),
+ URL::encode(vkey->getText()).c_str(),
+ ch,
+ ch);
+ }
+ else {
+ buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=%c&value=%s&module=%s&passage=%s\"><small><sup class=\"%c\">*%c</sup></small></a>",
+ ch,
+ URL::encode(footnoteNumber.c_str()).c_str(),
+ URL::encode(u->version.c_str()).c_str(),
+ URL::encode(u->key->getText()).c_str(),
+ ch,
+ ch);
+ }
+ }
+ }
+ u->suspendTextPassThru = (++u->suspendLevel);
+ }
+ if (tag.isEndTag()) {
+ u->suspendTextPassThru = (--u->suspendLevel);
+ u->inXRefNote = false;
+ u->lastSuspendSegment = ""; // fix/work-around for nasb devineName in note bug
+ }
+ }
+
+ // <p> paragraph and <lg> linegroup tags
+ else if (!strcmp(tag.getName(), "p") || !strcmp(tag.getName(), "lg")) {
+ if ((!tag.isEndTag()) && (!tag.isEmpty())) { // non-empty start tag
+ outText("<!P><br />", buf, u);
+ }
+ else if (tag.isEndTag()) { // end tag
+ outText("<!/P><br />", buf, u);
+ userData->supressAdjacentWhitespace = true;
+ }
+ else { // empty paragraph break marker
+ outText("<!P><br />", buf, u);
+ userData->supressAdjacentWhitespace = true;
+ }
+ }
+
+ // Milestoned paragraphs, created by osis2mod
+ // <div type="paragraph" sID.../>
+ // <div type="paragraph" eID.../>
+ else if (tag.isEmpty() && !strcmp(tag.getName(), "div") && tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "paragraph")) {
+ // <div type="paragraph" sID... />
+ if (tag.getAttribute("sID")) { // non-empty start tag
+ outText("<!P><br />", buf, u);
+ }
+ // <div type="paragraph" eID... />
+ else if (tag.getAttribute("eID")) {
+ outText("<!/P><br />", buf, u);
+ userData->supressAdjacentWhitespace = true;
+ }
+ }
+
+ // <reference> tag
+ else if (!strcmp(tag.getName(), "reference")) {
+ if (!u->inXRefNote) { // only show these if we're not in an xref note
+ if (!tag.isEndTag()) {
+ SWBuf target;
+ SWBuf work;
+ SWBuf ref;
+ bool is_scripRef = false;
+
+ target = tag.getAttribute("osisRef");
+ const char* the_ref = strchr(target, ':');
+
+ if(!the_ref) {
+ // No work
+ ref = target;
+ is_scripRef = true;
+ }
+ else {
+ // Compensate for starting :
+ ref = the_ref + 1;
+
+ int size = target.size() - ref.size() - 1;
+ work.setSize(size);
+ strncpy(work.getRawData(), target, size);
+
+ // For Bible:Gen.3.15 or Bible.vulgate:Gen.3.15
+ if(!strncmp(work, "Bible", 5))
+ is_scripRef = true;
+ }
+
+ if(is_scripRef)
+ {
+ buf.appendFormatted("<a href=\"passagestudy.jsp?action=showRef&type=scripRef&value=%s&module=\">",
+ URL::encode(ref.c_str()).c_str()
+// (work.size()) ? URL::encode(work.c_str()).c_str() : "")
+ );
+ }
+ else
+ {
+ // Dictionary link, or something
+ buf.appendFormatted("<a href=\"sword://%s/%s\">",
+ URL::encode(work.c_str()).c_str(),
+ URL::encode(ref.c_str()).c_str()
+ );
+ }
+ }
+ else {
+ outText("</a>", buf, u);
+ }
+ }
+ }
+
+ // <l> poetry, etc
+ else if (!strcmp(tag.getName(), "l")) {
+ // end line marker
+ if (tag.getAttribute("eID")) {
+ outText("<br />", buf, u);
+ }
+ // <l/> without eID or sID
+ // Note: this is improper osis. This should be <lb/>
+ else if (tag.isEmpty() && !tag.getAttribute("sID")) {
+ outText("<br />", buf, u);
+ }
+ // end of the line
+ else if (tag.isEndTag()) {
+ outText("<br />", buf, u);
+ }
+ }
+
+ // <lb.../>
+ else if (!strcmp(tag.getName(), "lb")) {
+ outText("<br />", buf, u);
+ userData->supressAdjacentWhitespace = true;
+ }
+ // <milestone type="line"/>
+ // <milestone type="x-p"/>
+ // <milestone type="cQuote" marker="x"/>
+ else if ((!strcmp(tag.getName(), "milestone")) && (tag.getAttribute("type"))) {
+ if (!strcmp(tag.getAttribute("type"), "line")) {
+ outText("<br />", buf, u);
+ if (tag.getAttribute("subType") && !strcmp(tag.getAttribute("subType"), "x-PM")) {
+ outText("<br />", buf, u);
+ }
+ userData->supressAdjacentWhitespace = true;
+ }
+ else if (!strcmp(tag.getAttribute("type"),"x-p")) {
+ if (tag.getAttribute("marker"))
+ outText(tag.getAttribute("marker"), buf, u);
+ else outText("<!p>", buf, u);
+ }
+ else if (!strcmp(tag.getAttribute("type"), "cQuote")) {
+ const char *tmp = tag.getAttribute("marker");
+ bool hasMark = tmp;
+ SWBuf mark = tmp;
+ tmp = tag.getAttribute("level");
+ int level = (tmp) ? atoi(tmp) : 1;
+
+ // first check to see if we've been given an explicit mark
+ if (hasMark)
+ outText(mark, buf, u);
+ // finally, alternate " and ', if config says we should supply a mark
+ else if (u->osisQToTick)
+ outText((level % 2) ? '\"' : '\'', buf, u);
+ }
+ }
+
+ // <title>
+ else if (!strcmp(tag.getName(), "title")) {
+ if ((!tag.isEndTag()) && (!tag.isEmpty())) {
+ buf += "<h3>";
+ }
+ else if (tag.isEndTag()) {
+ buf += "</h3>";
+ }
+ }
+
+ // <list>
+ else if (!strcmp(tag.getName(), "list")) {
+ if((!tag.isEndTag()) && (!tag.isEmpty())) {
+ outText("<ul>", buf, u);
+ }
+ else if (tag.isEndTag()) {
+ outText("</ul>", buf, u);
+ }
+ }
+
+ // <item>
+ else if (!strcmp(tag.getName(), "item")) {
+ if((!tag.isEndTag()) && (!tag.isEmpty())) {
+ outText("<li>", buf, u);
+ }
+ else if (tag.isEndTag()) {
+ outText("</li>", buf, u);
+ }
+ }
+ // <catchWord> & <rdg> tags (italicize)
+ else if (!strcmp(tag.getName(), "rdg") || !strcmp(tag.getName(), "catchWord")) {
+ if ((!tag.isEndTag()) && (!tag.isEmpty())) {
+ outText("<i>", buf, u);
+ }
+ else if (tag.isEndTag()) {
+ outText("</i>", buf, u);
+ }
+ }
+
+ // divineName
+ else if (!strcmp(tag.getName(), "divineName")) {
+ if ((!tag.isEndTag()) && (!tag.isEmpty())) {
+ u->suspendTextPassThru = (++u->suspendLevel);
+ }
+ else if (tag.isEndTag()) {
+ SWBuf lastText = u->lastSuspendSegment.c_str();
+ u->suspendTextPassThru = (--u->suspendLevel);
+ if (lastText.size()) {
+ scratch.setFormatted("<span class=\"divineName\">%s</span>", lastText.c_str());
+ outText(scratch.c_str(), buf, u);
+ }
+ }
+ }
+
+ // <hi> text highlighting
+ else if (!strcmp(tag.getName(), "hi")) {
+ SWBuf type = tag.getAttribute("type");
+ if ((!tag.isEndTag()) && (!tag.isEmpty())) {
+ if (type == "bold" || type == "b" || type == "x-b") {
+ outText("<b>", buf, u);
+ }
+ else { // all other types
+ outText("<i>", buf, u);
+ }
+ u->tagStacks->hiStack.push(tag.toString());
+ }
+ else if (tag.isEndTag()) {
+ SWBuf type = "";
+ if (!u->tagStacks->hiStack.empty()) {
+ XMLTag tag(u->tagStacks->hiStack.top());
+ u->tagStacks->hiStack.pop();
+ type = tag.getAttribute("type");
+ }
+ if (type == "bold" || type == "b" || type == "x-b") {
+ outText("</b>", buf, u);
+ }
+ else outText("</i>", buf, u);
+ }
+ }
+
+ // <q> quote
+ // Rules for a quote element:
+ // If the tag is empty with an sID or an eID then use whatever it specifies for quoting.
+ // Note: empty elements without sID or eID are ignored.
+ // If the tag is <q> then use it's specifications and push it onto a stack for </q>
+ // If the tag is </q> then use the pushed <q> for specification
+ // If there is a marker attribute, possibly empty, this overrides osisQToTick.
+ // If osisQToTick, then output the marker, using level to determine the type of mark.
+ else if (!strcmp(tag.getName(), "q")) {
+ SWBuf type = tag.getAttribute("type");
+ SWBuf who = tag.getAttribute("who");
+ const char *tmp = tag.getAttribute("level");
+ int level = (tmp) ? atoi(tmp) : 1;
+ tmp = tag.getAttribute("marker");
+ bool hasMark = tmp;
+ SWBuf mark = tmp;
+
+ // open <q> or <q sID... />
+ if ((!tag.isEmpty() && !tag.isEndTag()) || (tag.isEmpty() && tag.getAttribute("sID"))) {
+ // if <q> then remember it for the </q>
+ if (!tag.isEmpty()) {
+ u->tagStacks->quoteStack.push(tag.toString());
+ }
+
+ // Do this first so quote marks are included as WoC
+ if (who == "Jesus")
+ outText(u->wordsOfChristStart, buf, u);
+
+ // first check to see if we've been given an explicit mark
+ if (hasMark)
+ outText(mark, buf, u);
+ //alternate " and '
+ else if (u->osisQToTick)
+ outText((level % 2) ? '\"' : '\'', buf, u);
+ }
+ // close </q> or <q eID... />
+ else if ((tag.isEndTag()) || (tag.isEmpty() && tag.getAttribute("eID"))) {
+ // if it is </q> then pop the stack for the attributes
+ if (tag.isEndTag() && !u->tagStacks->quoteStack.empty()) {
+ XMLTag qTag(u->tagStacks->quoteStack.top());
+ u->tagStacks->quoteStack.pop();
+
+ type = qTag.getAttribute("type");
+ who = qTag.getAttribute("who");
+ tmp = qTag.getAttribute("level");
+ level = (tmp) ? atoi(tmp) : 1;
+ tmp = qTag.getAttribute("marker");
+ hasMark = tmp;
+ mark = tmp;
+ }
+
+ // first check to see if we've been given an explicit mark
+ if (hasMark)
+ outText(mark, buf, u);
+ // finally, alternate " and ', if config says we should supply a mark
+ else if (u->osisQToTick)
+ outText((level % 2) ? '\"' : '\'', buf, u);
+
+ // Do this last so quote marks are included as WoC
+ if (who == "Jesus")
+ outText(u->wordsOfChristEnd, buf, u);
+ }
+ }
+
+ // <transChange>
+ else if (!strcmp(tag.getName(), "transChange")) {
+ if ((!tag.isEndTag()) && (!tag.isEmpty())) {
+ SWBuf type = tag.getAttribute("type");
+ u->lastTransChange = type;
+
+ // just do all transChange tags this way for now
+ if ((type == "added") || (type == "supplied"))
+ outText("<i>", buf, u);
+ else if (type == "tenseChange")
+ buf += "*";
+ }
+ else if (tag.isEndTag()) {
+ SWBuf type = u->lastTransChange;
+ if ((type == "added") || (type == "supplied"))
+ outText("</i>", buf, u);
+ }
+ else { // empty transChange marker?
+ }
+ }
+
+ // image
+ else if (!strcmp(tag.getName(), "figure")) {
+ const char *src = tag.getAttribute("src");
+ if (!src) // assert we have a src attribute
+ return false;
+
+ SWBuf filepath;
+ if (userData->module) {
+ filepath = userData->module->getConfigEntry("AbsoluteDataPath");
+ if ((filepath.size()) && (filepath[filepath.size()-1] != '/') && (src[0] != '/'))
+ filepath += '/';
+ }
+ filepath += src;
+
+ // images become clickable, if the UI supports showImage.
+ outText("<a href=\"passagestudy.jsp?action=showImage&value=", buf, u);
+ outText(URL::encode(filepath.c_str()).c_str(), buf, u);
+ outText("&module=", buf, u);
+ outText(URL::encode(u->version.c_str()).c_str(), buf, u);
+ outText("\">", buf, u);
+
+ outText("<img src=\"file:", buf, u);
+ outText(filepath, buf, u);
+ outText("\" border=\"0\" />", buf, u);
+
+ outText("</a>", buf, u);
+ }
+
+ // ok to leave these in
+ else if (!strcmp(tag.getName(), "div")) {
+ buf += tag;
+ }
+ else if (!strcmp(tag.getName(), "span")) {
+ buf += tag;
+ }
+ else if (!strcmp(tag.getName(), "br")) {
+ buf += tag;
+ }
+
+ else {
+ return false; // we still didn't handle token
+ }
+ }
+ return true;
+}
+
+
+SWORD_NAMESPACE_END
Modified: trunk/src/modules/filters/thmlwebif.cpp
===================================================================
--- trunk/src/modules/filters/thmlwebif.cpp 2011-06-23 10:24:07 UTC (rev 2627)
+++ trunk/src/modules/filters/thmlwebif.cpp 2011-06-28 20:40:34 UTC (rev 2628)
@@ -31,7 +31,6 @@
SWORD_NAMESPACE_START
ThMLWEBIF::ThMLWEBIF() : baseURL(""), passageStudyURL(baseURL + "passagestudy.jsp") {
- //all's done in ThMLHTMLHREF
}
bool ThMLWEBIF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) {
@@ -100,7 +99,7 @@
}
}
else {
- return ThMLHTMLHREF::handleToken(buf,token,userData);
+ return ThMLXHTML::handleToken(buf, token, userData);
}
}
return true;
Added: trunk/src/modules/filters/thmlxhtml.cpp
===================================================================
--- trunk/src/modules/filters/thmlxhtml.cpp (rev 0)
+++ trunk/src/modules/filters/thmlxhtml.cpp 2011-06-28 20:40:34 UTC (rev 2628)
@@ -0,0 +1,369 @@
+/******************************************************************************
+ *
+ * thmlxhtml - ThML to classed XHTML
+ *
+ *
+ * Copyright 2011 CrossWire Bible Society (http://www.crosswire.org)
+ * CrossWire Bible Society
+ * P. O. Box 2528
+ * Tempe, AZ 85280-2528
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ */
+
+#include <stdlib.h>
+#include <thmlxhtml.h>
+#include <swmodule.h>
+#include <utilxml.h>
+#include <utilstr.h>
+#include <versekey.h>
+#include <url.h>
+
+SWORD_NAMESPACE_START
+
+const char *ThMLXHTML::getHeader() const {
+ return "\
+ ";
+}
+
+ThMLXHTML::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) {
+ if (module) {
+ version = module->Name();
+ BiblicalText = (!strcmp(module->Type(), "Biblical Texts"));
+ SecHead = false;
+ }
+}
+
+
+ThMLXHTML::ThMLXHTML() {
+ setTokenStart("<");
+ setTokenEnd(">");
+
+ setEscapeStart("&");
+ setEscapeEnd(";");
+
+ setEscapeStringCaseSensitive(true);
+ setPassThruNumericEscapeString(true);
+
+ addAllowedEscapeString("quot");
+ addAllowedEscapeString("amp");
+ addAllowedEscapeString("lt");
+ addAllowedEscapeString("gt");
+
+ addAllowedEscapeString("nbsp");
+ addAllowedEscapeString("brvbar"); // "Š"
+ addAllowedEscapeString("sect"); // "§"
+ addAllowedEscapeString("copy"); // "©"
+ addAllowedEscapeString("laquo"); // "«"
+ addAllowedEscapeString("reg"); // "®"
+ addAllowedEscapeString("acute"); // "Ž"
+ addAllowedEscapeString("para"); // "¶"
+ addAllowedEscapeString("raquo"); // "»"
+
+ addAllowedEscapeString("Aacute"); // "Á"
+ addAllowedEscapeString("Agrave"); // "À"
+ addAllowedEscapeString("Acirc"); // "Â"
+ addAllowedEscapeString("Auml"); // "Ä"
+ addAllowedEscapeString("Atilde"); // "Ã"
+ addAllowedEscapeString("Aring"); // "Å"
+ addAllowedEscapeString("aacute"); // "á"
+ addAllowedEscapeString("agrave"); // "à"
+ addAllowedEscapeString("acirc"); // "â"
+ addAllowedEscapeString("auml"); // "ä"
+ addAllowedEscapeString("atilde"); // "ã"
+ addAllowedEscapeString("aring"); // "å"
+ addAllowedEscapeString("Eacute"); // "É"
+ addAllowedEscapeString("Egrave"); // "È"
+ addAllowedEscapeString("Ecirc"); // "Ê"
+ addAllowedEscapeString("Euml"); // "Ë"
+ addAllowedEscapeString("eacute"); // "é"
+ addAllowedEscapeString("egrave"); // "è"
+ addAllowedEscapeString("ecirc"); // "ê"
+ addAllowedEscapeString("euml"); // "ë"
+ addAllowedEscapeString("Iacute"); // "Í"
+ addAllowedEscapeString("Igrave"); // "Ì"
+ addAllowedEscapeString("Icirc"); // "Î"
+ addAllowedEscapeString("Iuml"); // "Ï"
+ addAllowedEscapeString("iacute"); // "í"
+ addAllowedEscapeString("igrave"); // "ì"
+ addAllowedEscapeString("icirc"); // "î"
+ addAllowedEscapeString("iuml"); // "ï"
+ addAllowedEscapeString("Oacute"); // "Ó"
+ addAllowedEscapeString("Ograve"); // "Ò"
+ addAllowedEscapeString("Ocirc"); // "Ô"
+ addAllowedEscapeString("Ouml"); // "Ö"
+ addAllowedEscapeString("Otilde"); // "Õ"
+ addAllowedEscapeString("oacute"); // "ó"
+ addAllowedEscapeString("ograve"); // "ò"
+ addAllowedEscapeString("ocirc"); // "ô"
+ addAllowedEscapeString("ouml"); // "ö"
+ addAllowedEscapeString("otilde"); // "õ"
+ addAllowedEscapeString("Uacute"); // "Ú"
+ addAllowedEscapeString("Ugrave"); // "Ù"
+ addAllowedEscapeString("Ucirc"); // "Û"
+ addAllowedEscapeString("Uuml"); // "Ü"
+ addAllowedEscapeString("uacute"); // "ú"
+ addAllowedEscapeString("ugrave"); // "ù"
+ addAllowedEscapeString("ucirc"); // "û"
+ addAllowedEscapeString("uuml"); // "ü"
+ addAllowedEscapeString("Yacute"); // "Ý"
+ addAllowedEscapeString("yacute"); // "ý"
+ addAllowedEscapeString("yuml"); // "ÿ"
+
+ addAllowedEscapeString("deg"); // "°"
+ addAllowedEscapeString("plusmn"); // "±"
+ addAllowedEscapeString("sup2"); // "²"
+ addAllowedEscapeString("sup3"); // "³"
+ addAllowedEscapeString("sup1"); // "¹"
+ addAllowedEscapeString("nbsp"); // "º"
+ addAllowedEscapeString("pound"); // "£"
+ addAllowedEscapeString("cent"); // "¢"
+ addAllowedEscapeString("frac14"); // "Œ"
+ addAllowedEscapeString("frac12"); // "œ"
+ addAllowedEscapeString("frac34"); // "Ÿ"
+ addAllowedEscapeString("iquest"); // "¿"
+ addAllowedEscapeString("iexcl"); // "¡"
+ addAllowedEscapeString("ETH"); // "Ð"
+ addAllowedEscapeString("eth"); // "ð"
+ addAllowedEscapeString("THORN"); // "Þ"
+ addAllowedEscapeString("thorn"); // "þ"
+ addAllowedEscapeString("AElig"); // "Æ"
+ addAllowedEscapeString("aelig"); // "æ"
+ addAllowedEscapeString("Oslash"); // "Ø"
+ addAllowedEscapeString("curren"); // "€"
+ addAllowedEscapeString("Ccedil"); // "Ç"
+ addAllowedEscapeString("ccedil"); // "ç"
+ addAllowedEscapeString("szlig"); // "ß"
+ addAllowedEscapeString("Ntilde"); // "Ñ"
+ addAllowedEscapeString("ntilde"); // "ñ"
+ addAllowedEscapeString("yen"); // "¥"
+ addAllowedEscapeString("not"); // "¬"
+ addAllowedEscapeString("ordf"); // "ª"
+ addAllowedEscapeString("uml"); // "š"
+ addAllowedEscapeString("shy"); // ""
+ addAllowedEscapeString("macr"); // "¯"
+
+ addAllowedEscapeString("micro"); // "µ"
+ addAllowedEscapeString("middot"); // "·"
+ addAllowedEscapeString("cedil"); // "ž"
+ addAllowedEscapeString("ordm"); // "º"
+ addAllowedEscapeString("times"); // "×"
+ addAllowedEscapeString("divide"); // "÷"
+ addAllowedEscapeString("oslash"); // "ø"
+
+ setTokenCaseSensitive(true);
+// addTokenSubstitute("scripture", "<i> ");
+ addTokenSubstitute("/scripture", "</i> ");
+}
+
+
+bool ThMLXHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) {
+ 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")) { //>
+ if(value.length())
+ buf.appendFormatted("<small><em class=\"morph\">(<a href=\"passagestudy.jsp?action=showMorph&type=Greek&value=%s\" class=\"morph\">%s</a>)</em></small>",
+ URL::encode(value.c_str()).c_str(),
+ value.c_str());
+ }
+ else if (tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "lemma")) { //>
+ if(value.length())
+ // empty "type=" is deliberate.
+ buf.appendFormatted("<small><em class=\"strongs\"><<a href=\"passagestudy.jsp?action=showStrongs&type=&value=%s\" class=\"strongs\">%s</a>></em></small>",
+ URL::encode(value.c_str()).c_str(),
+ value.c_str());
+ }
+ else if (tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "Strongs")) {
+ char ch = *value;
+ value<<1;
+ buf.appendFormatted("<small><em class=\"strongs\"><<a href=\"passagestudy.jsp?action=showStrongs&type=%s&value=%s\" class=\"strongs\">",
+ ((ch == 'H') ? "Hebrew" : "Greek"),
+ URL::encode(value.c_str()).c_str());
+ buf += (value.length()) ? value.c_str() : "";
+ buf += "</a>></em></small>";
+ }
+ else if (tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "Dict")) {
+ buf += (tag.isEndTag() ? "</b>" : "<b>");
+ }
+
+ }
+ // <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 = NULL;
+ // see if we have a VerseKey * or descendant
+ SWTRY {
+ vkey = SWDYNAMIC_CAST(VerseKey, u->key);
+ }
+ SWCATCH ( ... ) { }
+ 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=\"passagestudy.jsp?action=showNote&type=%c&value=%s&module=%s&passage=%s\"><small><sup class=\"%c\">*%c</sup></small></a>",
+ ch,
+ URL::encode(footnoteNumber.c_str()).c_str(),
+ URL::encode(u->version.c_str()).c_str(),
+ URL::encode(vkey->getText()).c_str(),
+ ch,
+ ch);
+ }
+ else {
+ char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n');
+ buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=%c&value=%s&module=%s&passage=%s\"><small><sup class=\"%c\">*%c</sup></small></a>",
+ ch,
+ URL::encode(footnoteNumber.c_str()).c_str(),
+ URL::encode(u->version.c_str()).c_str(),
+ URL::encode(u->key->getText()).c_str(),
+ ch,
+ ch);
+ }
+ u->suspendTextPassThru = true;
+ }
+ }
+ if (tag.isEndTag()) {
+ u->suspendTextPassThru = false;
+ }
+ }
+ else if (!strcmp(tag.getName(), "scripture")) {
+ buf += (tag.isEndTag() ? "</i>" : "<i>");
+ }
+ // <scripRef> tag
+ 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.appendFormatted("<a href=\"passagestudy.jsp?action=showRef&type=scripRef&value=%s&module=%s\">",
+ (refList.length()) ? URL::encode(refList.c_str()).c_str() : "",
+ (version.length()) ? URL::encode(version.c_str()).c_str() : "");
+ buf += u->lastTextNode.c_str();
+ buf += "</a>";
+ }
+ else {
+ SWBuf footnoteNumber = u->startTag.getAttribute("swordFootnote");
+ VerseKey *vkey = NULL;
+ // see if we have a VerseKey * or descendant
+ SWTRY {
+ vkey = SWDYNAMIC_CAST(VerseKey, u->key);
+ }
+ SWCATCH ( ... ) {}
+ 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());
+ buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=x&value=%s&module=%s&passage=%s\"><small><sup class=\"x\">*x</sup></small></a>",
+ URL::encode(footnoteNumber.c_str()).c_str(),
+ URL::encode(u->version.c_str()).c_str(),
+ URL::encode(vkey->getText()).c_str());
+
+ }
+ }
+
+ // let's let text resume to output again
+ u->suspendTextPassThru = 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 {
+ buf += tag;
+ }
+ }
+ else {
+ buf += tag;
+ }
+ }
+ 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;
+
+ const char *c, *d;
+ if (((c = strchr(src+3, '"')) == NULL) ||
+ ((d = strchr( ++c , '"')) == NULL)) // identify endpoints.
+ return false; // abandon hope.
+
+ SWBuf imagename = "file:";
+ if (*c == '/') // as below, inside for loop.
+ imagename += userData->module->getConfigEntry("AbsoluteDataPath");
+ while (c != d) // move bits into the name.
+ imagename += *(c++);
+
+ // images become clickable, if the UI supports showImage.
+ buf.appendFormatted("<a href=\"passagestudy.jsp?action=showImage&value=%s&module=%s\"><",
+ URL::encode(imagename.c_str()).c_str(),
+ URL::encode(u->version.c_str()).c_str());
+
+ for (c = token; *c; c++) {
+ if ((*c == '/') && (*(c+1) == '\0'))
+ continue;
+ if (c == src) {
+ for (;((*c) && (*c != '"')); c++)
+ buf += *c;
+
+ if (!*c) { c--; continue; }
+
+ buf += '"';
+ if (*(c+1) == '/') {
+ buf += "file:";
+ buf += userData->module->getConfigEntry("AbsoluteDataPath");
+ if (buf[buf.length()-2] == '/')
+ c++; // skip '/'
+ }
+ continue;
+ }
+ buf += *c;
+ }
+ buf += " border=0 /></a>";
+ }
+ else {
+ 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
Modified: trunk/tests/Makefile.am
===================================================================
--- trunk/tests/Makefile.am 2011-06-23 10:24:07 UTC (rev 2627)
+++ trunk/tests/Makefile.am 2011-06-28 20:40:34 UTC (rev 2628)
@@ -7,7 +7,7 @@
SUBDIRS = cppunit
-noinst_PROGRAMS = utf8norm ciphertest keytest mgrtest parsekey versekeytest vtreekeytest versemgrtest listtest casttest \
+noinst_PROGRAMS = utf8norm ciphertest keytest mgrtest parsekey versekeytest vtreekeytest versemgrtest listtest casttest bibliography\
modtest compnone complzss localetest introtest indextest configtest keycast \
romantest testblocks filtertest rawldidxtest lextest swaptest \
swbuftest xmltest webiftest striptest
@@ -66,8 +66,8 @@
webiftest_SOURCES = webiftest.cpp
striptest_SOURCES = striptest.cpp
xmltest_SOURCES = xmltest.cpp
+bibliography_SOURCES = bibliography.cpp
-
EXTRA_DIST =
include bcppmake/Makefile.am
include testsuite/Makefile.am
More information about the sword-cvs
mailing list