/*************************************************************************** File: ks_osishtml.cpp Project: Kio-Sword -- An ioslave for SWORD and KDE Copyright: Copyright (C) 2004-2005 Luke Plant and CrossWire Bible Society 2003 (file based on osishtmlhref.cpp and osiscgi.cpp) ***************************************************************************/ /*************************************************************************** * 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; either version 2 of the License, or * * (at your option) any later version. * * * * 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. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "ks_osishtml.h" #include "utils.h" #include #include #include #include #include using namespace sword; namespace KioSword { OSISHTML::MyUserData::MyUserData(const SWModule *module, const SWKey *key) : BasicFilterUserData(module, key) { osisQToTick = ((!module->getConfigEntry("OSISqToTick")) || (strcmp(module->getConfigEntry("OSISqToTick"), "false"))); } OSISHTML::OSISHTML() { setTokenStart("<"); setTokenEnd(">"); setEscapeStart("&"); setEscapeEnd(";"); setEscapeStringCaseSensitive(true); addEscapeStringSubstitute("amp", "&"); addEscapeStringSubstitute("apos", "'"); addEscapeStringSubstitute("lt", "<"); addEscapeStringSubstitute("gt", ">"); addEscapeStringSubstitute("quot", "\""); addTokenSubstitute("lg", "
"); addTokenSubstitute("/lg", "
"); setTokenCaseSensitive(true); } bool OSISHTML::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) { // manually process if it wasn't a simple substitution if (!substituteToken(buf, token)) { MyUserData *u = (MyUserData *)userData; XMLTag tag(token); // tag if (!strcmp(tag.getName(), "w")) { if ((!tag.isEmpty()) && (!tag.isEndTag())) { // start tag u->w = token; } else { // end tag const char *attrib; const char *val; if (tag.isEndTag()) tag = u->w.c_str(); if ((attrib = tag.getAttribute("xlit"))) { val = strchr(attrib, ':'); val = (val) ? (val + 1) : attrib; buf.appendFormatted(" %s", val); } if ((attrib = tag.getAttribute("gloss"))) { val = strchr(attrib, ':'); val = (val) ? (val + 1) : attrib; buf.appendFormatted(" %s", 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; if (*val == 'G') { buf.append(TQString(" <%1> ") .arg(val+1) .arg(swordUrlForSearch(GREEKSTRONGS, val+1, m_swordoptions)) .utf8()); } else if (*val == 'H') { buf.append(TQString(" <%1> ") .arg(val+1) .arg(swordUrlForSearch(HEBREWSTRONGS, val+1, m_swordoptions)) .utf8()); } } while (++i < count); } if ((attrib = tag.getAttribute("morph"))) { 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; if (!strncmp(attrib, "x-Robinson",10)) { //robinson codes buf.append(TQString(" (%1) ") .arg(val) .arg(swordUrlForSearch(GREEKMORPH, val, m_swordoptions)) .utf8()); } else if ((*val == 'T')) { if (val[1] == 'G') { buf.append(TQString(" (%1) ") .arg(val+1) .arg(swordUrlForSearch(GREEKMORPH, val+1, m_swordoptions)) .utf8()); } else if (val[1] == 'H') { buf.append(TQString(" (%1) ") .arg(val+1) .arg(swordUrlForSearch(HEBREWMORPH, val+1, m_swordoptions)) .utf8()); } } } while (++i < count); } if ((attrib = tag.getAttribute("POS"))) { val = strchr(attrib, ':'); val = (val) ? (val + 1) : attrib; buf.appendFormatted(" %s", val); } } } // tag // FIXME - needs to be modified for Kio-Sword else if (!strcmp(tag.getName(), "note")) { if (!tag.isEndTag()) { if (!tag.isEmpty()) { SWBuf type = tag.getAttribute("type"); if (type != "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"); const VerseKey *vkey; // see if we have a VerseKey * or descendant try { vkey = SWDYNAMIC_CAST(const VerseKey, u->key); } catch ( ... ) { } if (vkey) { char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n'); buf.appendFormatted("*%c ", vkey->getText(), ch, footnoteNumber.c_str(), ch); } } u->suspendTextPassThru = true; } } if (tag.isEndTag()) { u->suspendTextPassThru = false; } } //

paragraph tag else if (!strcmp(tag.getName(), "p")) { if ((!tag.isEndTag()) && (!tag.isEmpty())) { // non-empty start tag buf += "

"; } else if (tag.isEndTag()) { // end tag buf += "

"; userData->supressAdjacentWhitespace = true; } else { // empty paragraph break marker buf += "
"; userData->supressAdjacentWhitespace = true; } } // FIXME - needs to be modified for Kio-Sword // tag else if (!strcmp(tag.getName(), "reference")) { if ((!tag.isEndTag()) && (!tag.isEmpty())) { buf += ""; } else if (tag.isEndTag()) { buf += ""; } } // poetry, etc else if (!strcmp(tag.getName(), "l")) { if (tag.isEmpty()) { buf += "
"; } else if (tag.isEndTag()) { buf += "
"; } else if (tag.getAttribute("sID")) { // empty line marker buf += "
"; } } // else if ((!strcmp(tag.getName(), "milestone")) && (tag.getAttribute("type")) && (!strcmp(tag.getAttribute("type"), "line"))) { buf += "
"; userData->supressAdjacentWhitespace = true; } // else if (!strcmp(tag.getName(), "title")) { if ((!tag.isEndTag()) && (!tag.isEmpty())) { buf += "<div class='title'>"; } else if (tag.isEndTag()) { buf += "</div>"; } } // <hi> hi? hi contrast? else if (!strcmp(tag.getName(), "hi")) { SWBuf type = tag.getAttribute("type"); if ((!tag.isEndTag()) && (!tag.isEmpty())) { if (type == "b" || type == "x-b") { buf += "<b>"; u->inBold = true; } else { // all other types buf += "<i>"; u->inBold = false; } } else if (tag.isEndTag()) { if(u->inBold) { buf += "</b>"; u->inBold = false; } else buf += "</i>"; } else { // empty hi marker // what to do? is this even valid? } } // <q> quote else if (!strcmp(tag.getName(), "q")) { SWBuf type = tag.getAttribute("type"); SWBuf who = tag.getAttribute("who"); const char *lev = tag.getAttribute("level"); int level = (lev) ? atoi(lev) : 1; if ((!tag.isEndTag()) && (!tag.isEmpty())) { /*buf += "{";*/ //alternate " and ' if (u->osisQToTick) buf += (level % 2) ? '\"' : '\''; if (who == "Jesus") buf += "<span class='jesusquote'>"; else buf += "<span class='quote'>"; } else if (tag.isEndTag()) { buf += "</span>"; //alternate " and ' if (u->osisQToTick) buf += (level % 2) ? '\"' : '\''; } else { // empty quote marker //alternate " and ' if (u->osisQToTick) buf += (level % 2) ? '\"' : '\''; } } // <transChange> else if (!strcmp(tag.getName(), "transChange")) { SWBuf type = tag.getAttribute("type"); if ((!tag.isEndTag()) && (!tag.isEmpty())) { // just do all transChange tags this way for now // if (type == "supplied") buf += "<i>"; } else if (tag.isEndTag()) { buf += "</i>"; } else { // empty transChange marker? } } // FIXME - remove for Kio-Sword? // image else if (!strcmp(tag.getName(), "figure")) { const char *src = tag.getAttribute("src"); if (!src) // assert we have a src attribute return false; char* filepath = new char[strlen(u->module->getConfigEntry("AbsoluteDataPath")) + strlen(token)]; *filepath = 0; strcpy(filepath, userData->module->getConfigEntry("AbsoluteDataPath")); strcat(filepath, src); // we do this because BibleCS looks for this EXACT format for an image tag buf+="<image src=\""; buf+=filepath; buf+="\" />"; /* char imgc; for (c = filepath + strlen(filepath); c > filepath && *c != '.'; c--); c++; FILE* imgfile; if (strcasecmp(c, "jpg") || stricmp(c, "jpeg")) { imgfile = fopen(filepath, "r"); if (imgfile != NULL) { buf += "{\\nonshppict {\\pict\\jpegblip "; while (feof(imgfile) != EOF) { buf.appendFormatted("%2x", fgetc(imgfile)); } fclose(imgfile); buf += "}}"; } } else if (strcasecmp(c, "png")) { buf += "{\\*\\shppict {\\pict\\pngblip "; buf += "}}"; } */ delete [] filepath; } else { return false; // we still didn't handle token } } return true; } }