You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
359 lines
11 KiB
359 lines
11 KiB
/***************************************************************************
|
|
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 <utilxml.h>
|
|
#include <versekey.h>
|
|
#include <swmodule.h>
|
|
|
|
#include <ntqstring.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
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", "<br />");
|
|
addTokenSubstitute("/lg", "<br />");
|
|
|
|
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);
|
|
|
|
// <w> tag
|
|
if (!strcmp(tag.getName(), "w")) {
|
|
if ((!tag.isEmpty()) && (!tag.isEndTag())) {
|
|
// start <w> tag
|
|
u->w = token;
|
|
} else {
|
|
// end <w> 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(" <span class='strongs'><<a href=\"%2\">%1</a>></span> ")
|
|
.arg(val+1)
|
|
.arg(swordUrlForSearch(GREEKSTRONGS, val+1, m_swordoptions))
|
|
.utf8());
|
|
} else if (*val == 'H') {
|
|
buf.append(TQString(" <span class='strongs'><<a href=\"%2\">%1</a>></span> ")
|
|
.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(" <span class='morph'>(<a href=\"%2\">%1</a>)</span> ")
|
|
.arg(val)
|
|
.arg(swordUrlForSearch(GREEKMORPH, val, m_swordoptions))
|
|
.utf8());
|
|
} else if ((*val == 'T')) {
|
|
if (val[1] == 'G') {
|
|
buf.append(TQString(" <span class='morph'>(<a href=\"%2\">%1</a>)</span> ")
|
|
.arg(val+1)
|
|
.arg(swordUrlForSearch(GREEKMORPH, val+1, m_swordoptions))
|
|
.utf8());
|
|
} else if (val[1] == 'H') {
|
|
buf.append(TQString(" <span class='morph'>(<a href=\"%2\">%1</a>)</span> ")
|
|
.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);
|
|
}
|
|
}
|
|
}
|
|
|
|
// <note> 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");
|
|
VerseKey *vkey;
|
|
// see if we have a VerseKey * or descendant
|
|
try {
|
|
vkey = SWDYNAMIC_CAST(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("<a href=\"noteID=%s.%c.%s\"><small><sup>*%c</sup></small></a> ", vkey->getText(), ch, footnoteNumber.c_str(), ch);
|
|
}
|
|
}
|
|
u->suspendTextPassThru = true;
|
|
}
|
|
}
|
|
if (tag.isEndTag()) {
|
|
u->suspendTextPassThru = false;
|
|
}
|
|
}
|
|
|
|
// <p> paragraph tag
|
|
else if (!strcmp(tag.getName(), "p")) {
|
|
if ((!tag.isEndTag()) && (!tag.isEmpty())) { // non-empty start tag
|
|
buf += "<p>";
|
|
}
|
|
else if (tag.isEndTag()) { // end tag
|
|
buf += "</P>";
|
|
userData->supressAdjacentWhitespace = true;
|
|
}
|
|
else { // empty paragraph break marker
|
|
buf += "<br />";
|
|
userData->supressAdjacentWhitespace = true;
|
|
}
|
|
}
|
|
|
|
// FIXME - needs to be modified for Kio-Sword
|
|
// <reference> tag
|
|
else if (!strcmp(tag.getName(), "reference")) {
|
|
if ((!tag.isEndTag()) && (!tag.isEmpty())) {
|
|
buf += "<a href=\"\">";
|
|
}
|
|
else if (tag.isEndTag()) {
|
|
buf += "</a>";
|
|
}
|
|
}
|
|
|
|
// <l> poetry, etc
|
|
else if (!strcmp(tag.getName(), "l")) {
|
|
if (tag.isEmpty()) {
|
|
buf += "<br />";
|
|
}
|
|
else if (tag.isEndTag()) {
|
|
buf += "<br />";
|
|
}
|
|
else if (tag.getAttribute("sID")) { // empty line marker
|
|
buf += "<br />";
|
|
}
|
|
}
|
|
|
|
// <milestone type="line"/>
|
|
else if ((!strcmp(tag.getName(), "milestone")) && (tag.getAttribute("type")) && (!strcmp(tag.getAttribute("type"), "line"))) {
|
|
buf += "<br />";
|
|
userData->supressAdjacentWhitespace = true;
|
|
}
|
|
|
|
// <title>
|
|
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;
|
|
}
|
|
}
|