The SWORD Project  1.9.0.svnversion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
teihtmlhref.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * teihtmlhref.cpp - TEI to HTML with hrefs filter
4  *
5  * $Id: teihtmlhref.cpp 3807 2020-09-27 12:59:54Z scribe $
6  *
7  * Copyright 2008-2013 CrossWire Bible Society (http://www.crosswire.org)
8  * CrossWire Bible Society
9  * P. O. Box 2528
10  * Tempe, AZ 85280-2528
11  *
12  * This program is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU General Public License as published by the
14  * Free Software Foundation version 2.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  */
22 
23 #include <stdlib.h>
24 #include <ctype.h>
25 #include <teihtmlhref.h>
26 #include <utilxml.h>
27 #include <swmodule.h>
28 #include <url.h>
29 #include <iostream>
30 
31 
33 
34 
36  isBiblicalText = false;
37  if (module) {
38  version = module->getName();
39  isBiblicalText = (!strcmp(module->getType(), "Biblical Texts"));
40  }
41 }
42 
43 
45  setTokenStart("<");
46  setTokenEnd(">");
47 
48  setEscapeStart("&");
49  setEscapeEnd(";");
50 
52 
53  addAllowedEscapeString("quot");
54  addAllowedEscapeString("apos");
58 
60 
61  renderNoteNumbers = false;
62 }
63 
64 bool TEIHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) {
65  // manually process if it wasn't a simple substitution
66  if (!substituteToken(buf, token)) {
67  MyUserData *u = (MyUserData *)userData;
68  XMLTag tag(token);
69 
70  if (!strcmp(tag.getName(), "p")) {
71  if ((!tag.isEndTag()) && (!tag.isEmpty())) { // non-empty start tag
72  buf += "<!P><br />";
73  }
74  else if (tag.isEndTag()) { // end tag
75  buf += "<!/P><br />";
76  //userData->supressAdjacentWhitespace = true;
77  }
78  else { // empty paragraph break marker
79  buf += "<!P><br />";
80  //userData->supressAdjacentWhitespace = true;
81  }
82  }
83 
84  // <hi>
85  else if (!strcmp(tag.getName(), "hi")) {
86  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
87  SWBuf rend = tag.getAttribute("rend");
88 
89  u->lastHi = rend;
90  if (rend == "italic" || rend == "ital")
91  buf += "<i>";
92  else if (rend == "bold")
93  buf += "<b>";
94  else if (rend == "super" || rend == "sup")
95  buf += "<sup>";
96  else if (rend == "sub")
97  buf += "<sub>";
98  else if (rend == "overline")
99  buf += "<span style=\"text-decoration:overline\">";
100  }
101  else if (tag.isEndTag()) {
102  SWBuf rend = u->lastHi;
103  if (rend == "italic" || rend == "ital")
104  buf += "</i>";
105  else if (rend == "bold")
106  buf += "</b>";
107  else if (rend == "super" || rend == "sup")
108  buf += "</sup>";
109  else if (rend == "sub")
110  buf += "</sub>";
111  else if (rend == "overline")
112  buf += "</span>";
113  }
114  }
115 
116  // <entryFree>
117  else if (!strcmp(tag.getName(), "entryFree")) {
118  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
119  SWBuf n = tag.getAttribute("n");
120  if (n != "") {
121  buf += "<b>";
122  buf += n;
123  buf += "</b>";
124  }
125  }
126  }
127 
128  // <sense>
129  else if (!strcmp(tag.getName(), "sense")) {
130  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
131  SWBuf n = tag.getAttribute("n");
132  if (n != "") {
133  buf += "<br /><b>";
134  buf += n;
135  buf += "</b> ";
136  }
137  }
138  }
139 
140  // <div>
141  else if (!strcmp(tag.getName(), "div")) {
142 
143  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
144  buf += "<!P>";
145  }
146  else if (tag.isEndTag()) {
147  }
148  }
149 
150  // <lb.../>
151  else if (!strcmp(tag.getName(), "lb")) {
152  buf += "<br />";
153  }
154 
155  // <pos>, <gen>, <case>, <gram>, <number>, <mood>, <pron>, <def>
156  else if (!strcmp(tag.getName(), "pos") ||
157  !strcmp(tag.getName(), "gen") ||
158  !strcmp(tag.getName(), "case") ||
159  !strcmp(tag.getName(), "gram") ||
160  !strcmp(tag.getName(), "number") ||
161  !strcmp(tag.getName(), "pron") /*||
162  !strcmp(tag.getName(), "def")*/) {
163  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
164  buf += "<i>";
165  }
166  else if (tag.isEndTag()) {
167  buf += "</i>";
168  }
169  }
170 
171  // <tr>
172  else if (!strcmp(tag.getName(), "tr")) {
173  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
174  buf += "<i>";
175  }
176  else if (tag.isEndTag()) {
177  buf += "</i>";
178  }
179  }
180 
181  // orth
182  else if (!strcmp(tag.getName(), "orth")) {
183  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
184  buf += "<b>";
185  }
186  else if (tag.isEndTag()) {
187  buf += "</b>";
188  }
189  }
190 
191  // <etym>, <usg>
192  else if (!strcmp(tag.getName(), "etym") ||
193  !strcmp(tag.getName(), "usg")) {
194  // do nothing here
195  }
196  else if (!strcmp(tag.getName(), "ref")) {
197  if (!tag.isEndTag()) {
198  u->suspendTextPassThru = true;
199  SWBuf target;
200  SWBuf work;
201  SWBuf ref;
202 
203  int was_osisref = false;
204  if(tag.getAttribute("osisRef"))
205  {
206  target += tag.getAttribute("osisRef");
207  was_osisref=true;
208  }
209  else if(tag.getAttribute("target"))
210  target += tag.getAttribute("target");
211 
212  if(target.size())
213  {
214  const char* the_ref = strchr(target, ':');
215 
216  if(!the_ref) {
217  // No work
218  ref = target;
219  }
220  else {
221  // Compensate for starting :
222  ref = the_ref + 1;
223 
224  int size = (int)(target.size() - ref.size() - 1);
225  work.setSize(size);
226  strncpy(work.getRawData(), target, size);
227  }
228 
229  if(was_osisref)
230  {
231  buf.appendFormatted("<a href=\"passagestudy.jsp?action=showRef&type=scripRef&value=%s&module=%s\">",
232  (ref) ? URL::encode(ref.c_str()).c_str() : "",
233  (work.size()) ? URL::encode(work.c_str()).c_str() : "");
234  }
235  else
236  {
237  // Dictionary link, or something
238  buf.appendFormatted("<a href=\"sword://%s/%s\">",
239  (work.size()) ? URL::encode(work.c_str()).c_str() : u->version.c_str(),
240  (ref) ? URL::encode(ref.c_str()).c_str() : ""
241  );
242  }
243  }
244  else
245  {
246  //std::cout << "TARGET WASN'T\n";
247  }
248 
249  }
250  else {
251  buf += u->lastTextNode.c_str();
252  buf += "</a>";
253 
254  u->suspendTextPassThru = false;
255  }
256  }
257 
258  // <note> tag
259  else if (!strcmp(tag.getName(), "note")) {
260  if (!tag.isEndTag()) {
261  if (!tag.isEmpty()) {
262  u->suspendTextPassThru = true;
263  }
264  }
265  if (tag.isEndTag()) {
266  SWBuf footnoteNumber = tag.getAttribute("swordFootnote");
267  SWBuf noteName = tag.getAttribute("n");
268 
269  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>",
270  URL::encode(footnoteNumber.c_str()).c_str(),
271  URL::encode(u->version.c_str()).c_str(),
272  URL::encode(u->key->getText()).c_str(),
273  (renderNoteNumbers ? URL::encode(noteName.c_str()).c_str() : ""));
274 
275  u->suspendTextPassThru = false;
276  }
277  }
278  // <graphic> image tag
279  else if (!strcmp(tag.getName(), "graphic")) {
280  const char *url = tag.getAttribute("url");
281  if (url) { // assert we have a url attribute
282  SWBuf filepath;
283  if (userData->module) {
284  filepath = userData->module->getConfigEntry("AbsoluteDataPath");
285  if ((filepath.size()) && (filepath[filepath.size()-1] != '/') && (url[0] != '/'))
286  filepath += '/';
287  }
288  filepath += url;
289  // images become clickable, if the UI supports showImage.
290  buf.appendFormatted("<a href=\"passagestudy.jsp?action=showImage&value=%s&module=%s\"><img src=\"file:%s\" border=\"0\" /></a>",
291  URL::encode(filepath.c_str()).c_str(),
292  URL::encode(u->version.c_str()).c_str(),
293  filepath.c_str());
294  u->suspendTextPassThru = true;
295  }
296  }
297  // <table> <row> <cell>
298  else if (!strcmp(tag.getName(), "table")) {
299  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
300  buf += "<table><tbody>\n";
301  }
302  else if (tag.isEndTag()) {
303  buf += "</tbody></table>\n";
304  u->supressAdjacentWhitespace = true;
305  }
306 
307  }
308  else if (!strcmp(tag.getName(), "row")) {
309  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
310  buf += "\t<tr>";
311  }
312  else if (tag.isEndTag()) {
313  buf += "</tr>\n";
314  }
315  }
316  else if (!strcmp(tag.getName(), "cell")) {
317  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
318  buf += "<td>";
319  }
320  else if (tag.isEndTag()) {
321  buf += "</td>";
322  }
323  }
324 
325  // <list> <item>
326  else if (!strcmp(tag.getName(), "list")) {
327  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
328 
329  SWBuf rend = tag.getAttribute("rend");
330 
331  u->lastHi = rend;
332  if (rend == "numbered") {
333  buf += "<ol>\n";
334  }
335  else if (rend == "lettered") {
336  buf += "<ol type=\"A\">\n";
337  }
338  else if (rend == "bulleted") {
339  buf += "<ul>\n";
340  }
341  else {
342  buf += "<ul class=\"list ";
343  buf += rend.c_str();
344  buf += "\">";
345  }
346  }
347  else if (tag.isEndTag()) {
348  SWBuf rend = u->lastHi;
349  if (rend == "numbered") {
350  buf += "</ol>\n>";
351  }
352  else if (rend == "lettered") {
353  buf += "</ol>\n";
354  }
355  else if (rend == "bulleted") {
356  buf += "</ul>\n";
357  }
358  else {
359  buf += "</ul>\n";
360  }
361  u->supressAdjacentWhitespace = true;
362  }
363  }
364  else if (!strcmp(tag.getName(), "item")) {
365  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
366  buf += "<li>";
367  }
368  else if (tag.isEndTag()) {
369  buf += "</li>\n";
370  }
371  }
372  else {
373  return false; // we still didn't handle token
374  }
375 
376  }
377  return true;
378 }
379 
380 
382 
const char * getName() const
Definition: swmodule.cpp:204
#define SWORD_NAMESPACE_START
Definition: defs.h:39
SWBuf & appendFormatted(const char *format,...)
Definition: swbuf.cpp:81
void setTokenEnd(const char *tokenEnd)
void addAllowedEscapeString(const char *findString)
Definition: swbuf.h:47
const char * getType() const
Definition: swmodule.cpp:232
virtual const char * getConfigEntry(const char *key) const
Definition: swmodule.cpp:1159
const SWModule * module
Definition: swbasicfilter.h:42
const char * getName() const
Definition: utilxml.h:58
SWText * module
Definition: osis2mod.cpp:105
Definition: utilxml.h:38
void setTokenCaseSensitive(bool val)
void setEscapeStart(const char *escStart)
bool isEmpty() const
Definition: utilxml.h:60
bool substituteToken(SWBuf &buf, const char *token)
virtual bool handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData)
Definition: teihtmlhref.cpp:64
virtual const char * getText() const
Definition: swkey.cpp:184
void setTokenStart(const char *tokenStart)
char * getRawData()
Definition: swbuf.h:379
const char * c_str() const
Definition: swbuf.h:158
MyUserData(const SWModule *module, const SWKey *key)
Definition: teihtmlhref.cpp:35
unsigned long size() const
Definition: swbuf.h:185
const SWKey * key
Definition: swbasicfilter.h:43
const char * getAttribute(const char *attribName, int partNum=-1, char partSplit= '|') const
Definition: utilxml.cpp:230
int size
Definition: regex.c:5043
void setEscapeStringCaseSensitive(bool val)
bool isEndTag(const char *eID=0) const
Definition: utilxml.cpp:323
void setEscapeEnd(const char *escEnd)
#define SWORD_NAMESPACE_END
Definition: defs.h:40
Definition: swkey.h:77
bool renderNoteNumbers
Definition: teihtmlhref.h:36
static const SWBuf encode(const char *urlText)
Definition: url.cpp:231
void setSize(unsigned long len)
Definition: swbuf.h:255