Quite a while ago, Xiphos gained the capability to post-process the *n/*x that come out of the engine so as to add the n=X identifiers that emanate out of OSIS and ThML markup. This is a fine and welcome idea, but we have run into a problem.
Some modules have single-section content that is really big. I mean, *really* big, half a megabyte at a time Really Big. Notably, EarlyFathers' /NPNF109/Subject_Index is my current problem child and proof case. The problem presented by a post-processing step of this sort is that, having the content in hand, we now need to make 2 calls to getEntryAttributes() in order to retrieve both "n" and "type" elements. Evidently, each such call requires that the engine retrieve original content from disc, and fully parse it out. Ouchie. /NPNF109/Subject_Index has almost 2500 footnotes in its 480Kbytes. Ergo, 5000 retrievals times 480Kbytes apiece = ... Ow. Ow ow ow ow ow. Some rough timing when I discovered this problem earlier this week showed that it would take -- I am not exaggerating -- just short of an hour to render this section, on the rather beastly machine I now use. 95+% of the time is being spent in the engine's retrieval; virtually no time is spent in the g_string routines that perform the actual textual appendage. So although the post-processing effect is a good one, being implemented *as* a post-processing step is a disaster. I had never noticed this downside until I ran into these pathological cases this week. The Right Way to do this is for the filters to output the n=X content on the spot. The attached patch provides this for all htmlhref and xhtml filters. I'd like to apply this (I'll do it myself, I have privs) but I wanted to make sure that adding this doesn't harm anyone else. It's a straightforward, simple change, and you can see the effect in a couple screenshots: http://karl.kleinpaste.org/xiphos/notes-xrefs-NASB.png http://karl.kleinpaste.org/xiphos/notes-xrefs-NET.png Please review and provide feedback. I'll commit the patch in a day or three if no one objects. --karl
Index: src/modules/filters/thmlxhtml.cpp =================================================================== --- src/modules/filters/thmlxhtml.cpp (revision 2675) +++ src/modules/filters/thmlxhtml.cpp (working copy) @@ -208,6 +208,7 @@ 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 { @@ -217,23 +218,25 @@ 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>", + 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); + ch, + 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</sup></small></a>", + 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); + ch, + URL::encode(noteName.c_str()).c_str()); } u->suspendTextPassThru = true; } @@ -267,6 +270,7 @@ } else { SWBuf footnoteNumber = u->startTag.getAttribute("swordFootnote"); + SWBuf noteName = tag.getAttribute("n"); VerseKey *vkey = NULL; // see if we have a VerseKey * or descendant SWTRY { @@ -276,11 +280,11 @@ 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>", + 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()); - + URL::encode(vkey->getText()).c_str(), + URL::encode(noteName.c_str()).c_str()); } } Index: src/modules/filters/gbfhtmlhref.cpp =================================================================== --- src/modules/filters/gbfhtmlhref.cpp (revision 2675) +++ src/modules/filters/gbfhtmlhref.cpp (working copy) @@ -231,6 +231,7 @@ else if (!strcmp(tag.getName(), "RF")) { 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 { @@ -240,10 +241,11 @@ 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> ", + buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=n&value=%s&module=%s&passage=%s\"><small><sup class=\"n\">*n%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()); + URL::encode(vkey->getText()).c_str(), + URL::encode(noteName.c_str()).c_str()); } u->suspendTextPassThru = true; } Index: src/modules/filters/osisxhtml.cpp =================================================================== --- src/modules/filters/osisxhtml.cpp (revision 2675) +++ src/modules/filters/osisxhtml.cpp (working copy) @@ -252,6 +252,7 @@ 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"); + SWBuf noteName = tag.getAttribute("n"); VerseKey *vkey = NULL; char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); @@ -265,22 +266,24 @@ 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>", + 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); + ch, + URL::encode(noteName.c_str()).c_str()); } 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>", + 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); + ch, + URL::encode(noteName.c_str()).c_str()); } } } Index: src/modules/filters/osishtmlhref.cpp =================================================================== --- src/modules/filters/osishtmlhref.cpp (revision 2675) +++ src/modules/filters/osishtmlhref.cpp (working copy) @@ -240,6 +240,7 @@ 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"); + SWBuf noteName = tag.getAttribute("n"); VerseKey *vkey = NULL; char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); @@ -253,22 +254,24 @@ 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>", + 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); + ch, + URL::encode(noteName.c_str()).c_str()); } 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>", + 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); + ch, + URL::encode(noteName.c_str()).c_str()); } } } Index: src/modules/filters/gbfxhtml.cpp =================================================================== --- src/modules/filters/gbfxhtml.cpp (revision 2675) +++ src/modules/filters/gbfxhtml.cpp (working copy) @@ -168,6 +168,7 @@ else if (!strcmp(tag.getName(), "RF")) { 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 { @@ -177,10 +178,11 @@ 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> ", + buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=n&value=%s&module=%s&passage=%s\"><small><sup class=\"n\">*n%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()); + URL::encode(vkey->getText()).c_str(), + URL::encode(noteName.c_str()).c_str()); } u->suspendTextPassThru = true; } Index: src/modules/filters/thmlhtmlhref.cpp =================================================================== --- src/modules/filters/thmlhtmlhref.cpp (revision 2675) +++ src/modules/filters/thmlhtmlhref.cpp (working copy) @@ -206,6 +206,7 @@ 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 { @@ -215,23 +216,25 @@ 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>", + 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); + ch, + 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</sup></small></a>", + 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); + ch, + URL::encode(noteName.c_str()).c_str()); } u->suspendTextPassThru = true; } @@ -265,6 +268,7 @@ } else { SWBuf footnoteNumber = u->startTag.getAttribute("swordFootnote"); + SWBuf noteName = tag.getAttribute("n"); VerseKey *vkey = NULL; // see if we have a VerseKey * or descendant SWTRY { @@ -274,11 +278,11 @@ 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>", + 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()); - + URL::encode(vkey->getText()).c_str(), + URL::encode(noteName.c_str()).c_str()); } } Index: src/modules/filters/teihtmlhref.cpp =================================================================== --- src/modules/filters/teihtmlhref.cpp (revision 2675) +++ src/modules/filters/teihtmlhref.cpp (working copy) @@ -259,11 +259,13 @@ } if (tag.isEndTag()) { SWBuf footnoteNumber = tag.getAttribute("swordFootnote"); + SWBuf noteName = tag.getAttribute("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>", + buf.appendFormatted("<a href=\"passagestudy.jsp?action=showNote&type=n&value=%s&module=%s&passage=%s\"><small><sup class=\"n\">*n%s</sup></small></a>", URL::encode(footnoteNumber.c_str()).c_str(), URL::encode(u->version.c_str()).c_str(), - URL::encode(u->key->getText()).c_str()); + URL::encode(u->key->getText()).c_str(), + URL::encode(noteName.c_str()).c_str()); u->suspendTextPassThru = false; }
_______________________________________________ sword-devel mailing list: sword-devel@crosswire.org http://www.crosswire.org/mailman/listinfo/sword-devel Instructions to unsubscribe/change your settings at above page