[sword-svn] r3069 - in trunk: include src/modules/filters

refdoc at crosswire.org refdoc at crosswire.org
Tue Mar 4 17:06:39 MST 2014


Author: refdoc
Date: 2014-03-04 17:06:39 -0700 (Tue, 04 Mar 2014)
New Revision: 3069

Modified:
   trunk/include/thmllatex.h
   trunk/src/modules/filters/thmllatex.cpp
Log:
ThML filter for LaTeX now based on xhtml - needs fleshing out



Modified: trunk/include/thmllatex.h
===================================================================
--- trunk/include/thmllatex.h	2014-03-05 00:05:47 UTC (rev 3068)
+++ trunk/include/thmllatex.h	2014-03-05 00:06:39 UTC (rev 3069)
@@ -4,7 +4,7 @@
  *
  * $Id$
  *
- * Copyright 2013 CrossWire Bible Society (http://www.crosswire.org)
+ * Copyright 2011-2013 CrossWire Bible Society (http://www.crosswire.org)
  *	CrossWire Bible Society
  *	P. O. Box 2528
  *	Tempe, AZ  85280-2528
@@ -20,20 +20,41 @@
  *
  */
 
-#ifndef THMLLATEX_H
-#define THMLLATEX_H
+#ifndef _THMLLaTeX_H
+#define _THMLLaTeX_H
 
-#include <swfilter.h>
+#include <swbasicfilter.h>
+#include <utilxml.h>
 
 SWORD_NAMESPACE_START
 
-/** this filter converts ThML text to LaTeX text
+/** this filter converts ThML text to LaTeX
  */
-class SWDLLEXPORT ThMLLaTeX : public SWFilter {
+class SWDLLEXPORT ThMLLaTeX : public SWBasicFilter {
+	SWBuf imgPrefix;
+	bool renderNoteNumbers;
+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:
 	ThMLLaTeX();
-	virtual char processText(SWBuf &text, const SWKey *key = 0, const SWModule *module = 0);
+	virtual const char *getImagePrefix() { return imgPrefix.c_str(); }
+	virtual void setImagePrefix(const char *newImgPrefix) { imgPrefix = newImgPrefix; }
+	virtual const char *getHeader() const;
+	void setRenderNoteNumbers(bool val = true) { renderNoteNumbers = val; }
 };
 
 SWORD_NAMESPACE_END
+
 #endif

Modified: trunk/src/modules/filters/thmllatex.cpp
===================================================================
--- trunk/src/modules/filters/thmllatex.cpp	2014-03-05 00:05:47 UTC (rev 3068)
+++ trunk/src/modules/filters/thmllatex.cpp	2014-03-05 00:06:39 UTC (rev 3069)
@@ -1,11 +1,10 @@
 /******************************************************************************
  *
- *  thmllatex.cpp -	SWFilter descendant to create LaTeX formatted text
- *			from ThML tags 
+ *  thmllatex.cpp -	ThML to classed LaTeX
  *
  * $Id$
  *
- * Copyright 2013 CrossWire Bible Society (http://www.crosswire.org)
+ * Copyright 2011-2013 CrossWire Bible Society (http://www.crosswire.org)
  *	CrossWire Bible Society
  *	P. O. Box 2528
  *	Tempe, AZ  85280-2528
@@ -23,225 +22,356 @@
 
 #include <stdlib.h>
 #include <thmllatex.h>
-#include <swbuf.h>
+#include <swmodule.h>
+#include <utilxml.h>
+#include <utilstr.h>
+#include <versekey.h>
+#include <url.h>
 
 SWORD_NAMESPACE_START
+ 
 
-ThMLLaTeX::ThMLLaTeX() {
+const char *ThMLLaTeX::getHeader() const {
+	return "\
+	";
 }
 
-char ThMLLaTeX::processText(SWBuf &text, const SWKey *key, const SWModule *module)
-{
-	char token[2048];
-	int tokpos = 0;
-	bool intoken = false;
-	bool ampersand = false;
 
-	const char *from;
-	SWBuf orig = text;
-	from = orig.c_str();
-	for (text = ""; *from; from++)
-	{
-		if (*from == 10 || *from == 13)
-			from++;
-		if (*from == '<') {
-			intoken = true;
-			tokpos = 0;
-			token[0] = 0;
-			token[1] = 0;
-			token[2] = 0;
-			ampersand = false;
-			continue;
-		}
-		else if (*from == '&') {
-			intoken = true;
-			tokpos = 0;
-			token[0] = 0;
-			token[1] = 0;
-			token[2] = 0;
-			ampersand = true;
-			continue;
-		}
-		if (*from == ';' && ampersand) {
-			intoken = false;
-			ampersand = false;
+ThMLLaTeX::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) {
+	if (module) {
+		version = module->getName();
+		BiblicalText = (!strcmp(module->getType(), "Biblical Texts"));
+		SecHead = false;
+	}	
+}
 
-			if (!strncmp("nbsp", token, 4)) text += ' ';
-			else if (!strncmp("quot", token, 4)) text += '"';
-			else if (!strncmp("amp", token, 3)) text += '&';
-			else if (!strncmp("lt", token, 2)) text += '<';
-			else if (!strncmp("gt", token, 2)) text += '>';
-			else if (!strncmp("brvbar", token, 6)) text += "¦";
-			else if (!strncmp("sect", token, 4)) text += "§";
-			else if (!strncmp("copy", token, 4)) text += "©";
-			else if (!strncmp("laquo", token, 5)) text += "«";
-			else if (!strncmp("reg", token, 3)) text += "®";
-			else if (!strncmp("acute", token, 5)) text += "´";
-			else if (!strncmp("para", token, 4)) text += "¶";
-			else if (!strncmp("raquo", token, 5)) text += "»";
 
-			else if (!strncmp("Aacute", token, 6)) text += "Á";
-			else if (!strncmp("Agrave", token, 6)) text += "À";
-			else if (!strncmp("Acirc", token, 5)) text += "Â";
-			else if (!strncmp("Auml", token, 4)) text += "Ä";
-			else if (!strncmp("Atilde", token, 6)) text += "Ã";
-			else if (!strncmp("Aring", token, 5)) text += "Å";
-			else if (!strncmp("aacute", token, 6)) text += "á";
-			else if (!strncmp("agrave", token, 6)) text += "à";
-			else if (!strncmp("acirc", token, 5)) text += "â";
-			else if (!strncmp("auml", token, 4)) text += "ä";
-			else if (!strncmp("atilde", token, 6)) text += "ã";
-			else if (!strncmp("aring", token, 5)) text += "å";
-			else if (!strncmp("Eacute", token, 6)) text += "É";
-			else if (!strncmp("Egrave", token, 6)) text += "È";
-			else if (!strncmp("Ecirc", token, 5)) text += "Ê";
-			else if (!strncmp("Euml", token, 4)) text += "Ë";
-			else if (!strncmp("eacute", token, 6)) text += "é";
-			else if (!strncmp("egrave", token, 6)) text += "è";
-			else if (!strncmp("ecirc", token, 5)) text += "ê";
-			else if (!strncmp("euml", token, 4)) text += "ë";
-			else if (!strncmp("Iacute", token, 6)) text += "Í";
-			else if (!strncmp("Igrave", token, 6)) text += "Ì";
-			else if (!strncmp("Icirc", token, 5)) text += "Î";
-			else if (!strncmp("Iuml", token, 4)) text += "Ï";
-			else if (!strncmp("iacute", token, 6)) text += "í";
-			else if (!strncmp("igrave", token, 6)) text += "ì";
-			else if (!strncmp("icirc", token, 5)) text += "î";
-			else if (!strncmp("iuml", token, 4)) text += "ï";
-			else if (!strncmp("Oacute", token, 6)) text += "Ó";
-			else if (!strncmp("Ograve", token, 6)) text += "Ò";
-			else if (!strncmp("Ocirc", token, 5)) text += "Ô";
-			else if (!strncmp("Ouml", token, 4)) text += "Ö";
-			else if (!strncmp("Otilde", token, 6)) text += "Õ";
-			else if (!strncmp("oacute", token, 6)) text += "ó";
-			else if (!strncmp("ograve", token, 6)) text += "ò";
-			else if (!strncmp("ocirc", token, 5)) text += "ô";
-			else if (!strncmp("ouml", token, 4)) text += "ö";
-			else if (!strncmp("otilde", token, 6)) text += "õ";
-			else if (!strncmp("Uacute", token, 6)) text += "Ú";
-			else if (!strncmp("Ugrave", token, 6)) text += "Ù";
-			else if (!strncmp("Ucirc", token, 5)) text += "Û";
-			else if (!strncmp("Uuml", token, 4)) text += "Ü";
-			else if (!strncmp("uacute", token, 6)) text += "ú";
-			else if (!strncmp("ugrave", token, 6)) text += "ù";
-			else if (!strncmp("ucirc", token, 5)) text += "û";
-			else if (!strncmp("uuml", token, 4)) text += "ü";
-			else if (!strncmp("Yacute", token, 6)) text += "Ý";
-			else if (!strncmp("yacute", token, 6)) text += "ý";
-			else if (!strncmp("yuml", token, 4)) text += "ÿ";
+ThMLLaTeX::ThMLLaTeX() {
+	setTokenStart("<");
+	setTokenEnd(">");
 
-			else if (!strncmp("deg", token, 3)) text += "°";
-			else if (!strncmp("plusmn", token, 6)) text += "±";
-			else if (!strncmp("sup2", token, 4)) text += "²";
-			else if (!strncmp("sup3", token, 4)) text += "³";
-			else if (!strncmp("sup1", token, 4)) text += "¹";
-			else if (!strncmp("nbsp", token, 4)) text += "º";
-			else if (!strncmp("pound", token, 5)) text += "£";
-			else if (!strncmp("cent", token, 4)) text += "¢";
-			else if (!strncmp("frac14", token, 6)) text += "¼";
-			else if (!strncmp("frac12", token, 6)) text += "½";
-			else if (!strncmp("frac34", token, 6)) text += "¾";
-			else if (!strncmp("iquest", token, 6)) text += "¿";
-			else if (!strncmp("iexcl", token, 5)) text += "¡";
-			else if (!strncmp("ETH", token, 3)) text += "Ð";
-			else if (!strncmp("eth", token, 3)) text += "ð";
-			else if (!strncmp("THORN", token, 5)) text += "Þ";
-			else if (!strncmp("thorn", token, 5)) text += "þ";
-			else if (!strncmp("AElig", token, 5)) text += "Æ";
-			else if (!strncmp("aelig", token, 5)) text += "æ";
-			else if (!strncmp("Oslash", token, 6)) text += "Ø";
-			else if (!strncmp("curren", token, 6)) text += "¤";
-			else if (!strncmp("Ccedil", token, 6)) text += "Ç";
-			else if (!strncmp("ccedil", token, 6)) text += "ç";
-			else if (!strncmp("szlig", token, 5)) text += "ß";
-			else if (!strncmp("Ntilde", token, 6)) text += "Ñ";
-			else if (!strncmp("ntilde", token, 6)) text += "ñ";
-			else if (!strncmp("yen", token, 3)) text += "¥";
-			else if (!strncmp("not", token, 3)) text += "¬";
-			else if (!strncmp("ordf", token, 4)) text += "ª";
-			else if (!strncmp("uml", token, 3)) text += "¨";
-			else if (!strncmp("shy", token, 3)) text += "­";
-			else if (!strncmp("macr", token, 4)) text += "¯";
-			else if (!strncmp("micro", token, 5)) text += "µ";
-			else if (!strncmp("middot", token, 6)) text += "·";
-			else if (!strncmp("cedil", token, 5)) text += "¸";
-			else if (!strncmp("ordm", token, 4)) text += "º";
-			else if (!strncmp("times", token, 5)) text += "×";
-			else if (!strncmp("divide", token, 6)) text += "÷";
-			else if (!strncmp("oslash", token, 6)) text += "ø";
-			continue;
+	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> ");
+
+	renderNoteNumbers = false;
+}
+
+
+bool ThMLLaTeX::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")) { //&gt;
+				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")) { //&gt;
+				if(value.length())
+					// empty "type=" is deliberate.
+					buf.appendFormatted("<small><em class=\"strongs\">&lt;<a href=\"passagestudy.jsp?action=showStrongs&type=&value=%s\" class=\"strongs\">%s</a>&gt;</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\">&lt;<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>&gt;</em></small>";
+			}
+			else if (tag.getAttribute("type") && !strcmp(tag.getAttribute("type"), "Dict")) {
+				buf += (tag.isEndTag() ? "</b>" : "<b>");
+			}
+				
 		}
-		else if (*from == '>' && !ampersand) {
-			intoken = false;
-			// process desired tokens
-			if (!strncmp(token, "sync type=\"Strongs\" value=\"", 27)) {
-				text += ' ';
-				text += '<';
-				for (unsigned int i = 27; token[i] != '\"'; i++)
-					text += token[i];
-				text += '>';
-				continue;
+		// <note> tag
+		else if (!strcmp(tag.getName(), "note")) {
+			if (!tag.isEndTag()) {
+				if (!tag.isEmpty()) {
+					SWBuf type = tag.getAttribute("type");
+					SWBuf footnoteNumber = tag.getAttribute("swordFootnote");
+					SWBuf noteName = tag.getAttribute("n");
+					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%s</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, 
+							(renderNoteNumbers ? URL::encode(noteName.c_str()).c_str() : ""));
+					}
+					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%s</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, 
+							(renderNoteNumbers ? URL::encode(noteName.c_str()).c_str() : ""));
+					}
+					u->suspendTextPassThru = true;
+				}
 			}
-			if (!strncmp(token, "sync type=\"morph\" value=\"", 25)) {
-				text += ' ';
-				text += '(';
-				for (unsigned int i = 25; token[i] != '\"'; i++)
-					text += token[i];
-				text += ')';
-				continue;
+			if (tag.isEndTag()) {
+				u->suspendTextPassThru = false;
 			}
-			if (!strncmp("note", token, 4)) {
-				text += " \\footnote{";
+		}
+		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 (!strncmp("title", token, 5)) {
-				text += " \\section*{";
+			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");
+					SWBuf noteName = tag.getAttribute("n");
+					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%s</sup></small></a>",
+							URL::encode(footnoteNumber.c_str()).c_str(), 
+							URL::encode(u->version.c_str()).c_str(),
+							URL::encode(vkey->getText()).c_str(), 
+							(renderNoteNumbers ? URL::encode(noteName.c_str()).c_str() : ""));
+					}
+				}
+
+				// let's let text resume to output again
+				u->suspendTextPassThru = false;
 			}
-			if (!strncmp("scripRef", token, 8)) {
-				text += " \\footnoteB{";
+		}
+		else if (tag.getName() && !strcmp(tag.getName(), "div")) {
+			if (tag.isEndTag() && u->SecHead) {
+				buf += "</i></b><br />";
+				u->SecHead = false;
 			}
-			else if (!strncmp("br", token, 2))
-				text += "\\\\";
-			else if (!strncmp("/p", token, 2))
-				text += "\\paragraph ";
-			else if (!strncmp("/note", token, 5)) {
-				text += '}';
-				text += ' ';
+			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 if (!strncmp("/scripRef", token, 9)) {
-				text += '}';
-				text += ' ';
+			else {
+				buf += tag;
 			}
-			else if (!strncmp("/title", token, 6)) {
-				text += '}';
-				text += ' ';
+		}
+		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;
 			}
-			continue;
+               buf += " border=0 /></a>";
 		}
-		if (intoken) {
-			if (tokpos < 2045)
-				token[tokpos++] = *from;
-				token[tokpos+2] = 0;
+		else {
+			buf += '<';
+			/*for (const char *tok = token; *tok; tok++)
+				buf += *tok;*/
+			buf += token;
+			buf += '>';
+			//return false;  // we still didn't handle token
 		}
-		else	text += *from;
 	}
-
-	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;
+	return true;
 }
 
 




More information about the sword-cvs mailing list