/***************************************************************************
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 ;
}
}