The SWORD Project  1.9.0.svnversion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
osishtmlhref.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * osishtmlhref.cpp - OSIS to HTML with hrefs filter
4  *
5  * $Id: osishtmlhref.cpp 3714 2020-04-10 23:43:12Z scribe $
6  *
7  * Copyright 2003-2014 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 <osishtmlhref.h>
26 #include <utilxml.h>
27 #include <utilstr.h>
28 #include <versekey.h>
29 #include <swmodule.h>
30 #include <url.h>
31 #include <stringmgr.h>
32 #include <stack>
33 
35 
36 namespace {
37  typedef std::stack<SWBuf> TagStack;
38 // though this might be slightly slower, possibly causing an extra bool check, this is a renderFilter
39 // so speed isn't the absolute highest priority, and this is a very minor possible hit
40 static inline void outText(const char *t, SWBuf &o, BasicFilterUserData *u) { if (!u->suspendTextPassThru) o += t; else u->lastSuspendSegment += t; }
41 static inline void outText(char t, SWBuf &o, BasicFilterUserData *u) { if (!u->suspendTextPassThru) o += t; else u->lastSuspendSegment += t; }
42 
43 void processLemma(bool suspendTextPassThru, XMLTag &tag, SWBuf &buf) {
44  const char *attrib;
45  const char *val;
46  if ((attrib = tag.getAttribute("lemma"))) {
47  int count = tag.getAttributePartCount("lemma", ' ');
48  int i = (count > 1) ? 0 : -1; // -1 for whole value cuz it's faster, but does the same thing as 0
49  do {
50  attrib = tag.getAttribute("lemma", i, ' ');
51  if (i < 0) i = 0; // to handle our -1 condition
52  val = strchr(attrib, ':');
53  val = (val) ? (val + 1) : attrib;
54  SWBuf gh;
55  if(*val == 'G')
56  gh = "Greek";
57  if(*val == 'H')
58  gh = "Hebrew";
59  const char *val2 = val;
60  if ((strchr("GH", *val)) && (isdigit(val[1])))
61  val2++;
62  //if ((!strcmp(val2, "3588")) && (lastText.length() < 1))
63  // show = false;
64  //else {
65  if (!suspendTextPassThru) {
66  buf.appendFormatted("<small><em class=\"strongs\">&lt;<a href=\"passagestudy.jsp?action=showStrongs&type=%s&value=%s\" class=\"strongs\">%s</a>&gt;</em></small>",
67  (gh.length()) ? gh.c_str() : "",
68  URL::encode(val2).c_str(),
69  val2);
70  }
71  //}
72 
73  } while (++i < count);
74  }
75 }
76 
77 void processMorph(bool suspendTextPassThru, XMLTag &tag, SWBuf &buf) {
78  const char * attrib;
79  const char *val;
80  if ((attrib = tag.getAttribute("morph"))) { // && (show)) {
81  SWBuf savelemma = tag.getAttribute("savlm");
82  //if ((strstr(savelemma.c_str(), "3588")) && (lastText.length() < 1))
83  // show = false;
84  //if (show) {
85  int count = tag.getAttributePartCount("morph", ' ');
86  int i = (count > 1) ? 0 : -1; // -1 for whole value cuz it's faster, but does the same thing as 0
87  do {
88  attrib = tag.getAttribute("morph", i, ' ');
89  if (i < 0) i = 0; // to handle our -1 condition
90  val = strchr(attrib, ':');
91  val = (val) ? (val + 1) : attrib;
92  const char *val2 = val;
93  if ((*val == 'T') && (strchr("GH", val[1])) && (isdigit(val[2])))
94  val2+=2;
95  if (!suspendTextPassThru) {
96  buf.appendFormatted("<small><em class=\"morph\">(<a href=\"passagestudy.jsp?action=showMorph&type=%s&value=%s\" class=\"morph\">%s</a>)</em></small>",
97  URL::encode(tag.getAttribute("morph")).c_str(),
98  URL::encode(val).c_str(),
99  val2);
100  }
101  } while (++i < count);
102  //}
103  }
104 }
105 } // end anonymous namespace
106 
107 // TODO: this bridge pattern is to preserve binary compat on 1.6.x
109 public:
112 };
113 
115  inXRefNote = false;
116  suspendLevel = 0;
117  tagStacks = new TagStacks();
118  wordsOfChristStart = "<font color=\"red\"> ";
119  wordsOfChristEnd = "</font> ";
120  osisQToTick = true; // default
121  isBiblicalText = false;
122  if (module) {
123  osisQToTick = ((!module->getConfigEntry("OSISqToTick")) || (strcmp(module->getConfigEntry("OSISqToTick"), "false")));
124  version = module->getName();
125  isBiblicalText = (!strcmp(module->getType(), "Biblical Texts"));
126  }
127 }
128 
130  delete tagStacks;
131 }
132 
134  setTokenStart("<");
135  setTokenEnd(">");
136 
137  setEscapeStart("&");
138  setEscapeEnd(";");
139 
142 
143  addAllowedEscapeString("quot");
144  addAllowedEscapeString("apos");
145  addAllowedEscapeString("amp");
148 
149  setTokenCaseSensitive(true);
150 
151  // addTokenSubstitute("lg", "<br />");
152  // addTokenSubstitute("/lg", "<br />");
153 
154  morphFirst = false;
155  renderNoteNumbers = false;
156 }
157 
158 
159 bool OSISHTMLHREF::handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData) {
160  MyUserData *u = (MyUserData *)userData;
161  SWBuf scratch;
162  bool sub = (u->suspendTextPassThru) ? substituteToken(scratch, token) : substituteToken(buf, token);
163  if (!sub) {
164  // manually process if it wasn't a simple substitution
165  XMLTag tag(token);
166 
167  // <w> tag
168  if (!strcmp(tag.getName(), "w")) {
169 
170  // start <w> tag
171  if ((!tag.isEmpty()) && (!tag.isEndTag())) {
172  u->w = token;
173  }
174 
175  // end or empty <w> tag
176  else {
177  bool endTag = tag.isEndTag();
178  SWBuf lastText;
179  //bool show = true; // to handle unplaced article in kjv2003-- temporary till combined
180 
181  if (endTag) {
182  tag = u->w.c_str();
183  lastText = u->lastTextNode.c_str();
184  }
185  else lastText = "stuff";
186 
187  const char *attrib;
188  const char *val;
189  if ((attrib = tag.getAttribute("xlit"))) {
190  val = strchr(attrib, ':');
191  val = (val) ? (val + 1) : attrib;
192  outText(" ", buf, u);
193  outText(val, buf, u);
194  }
195  if ((attrib = tag.getAttribute("gloss"))) {
196  // I'm sure this is not the cleanest way to do it, but it gets the job done
197  // for rendering ruby chars properly ^_^
198  buf -= lastText.length();
199 
200  outText("<ruby><rb>", buf, u);
201  outText(lastText, buf, u);
202  outText("</rb><rp>(</rp><rt>", buf, u);
203  val = strchr(attrib, ':');
204  val = (val) ? (val + 1) : attrib;
205  outText(val, buf, u);
206  outText("</rt><rp>)</rp></ruby>", buf, u);
207  }
208  if (!morphFirst) {
209  processLemma(u->suspendTextPassThru, tag, buf);
210  processMorph(u->suspendTextPassThru, tag, buf);
211  }
212  else {
213  processMorph(u->suspendTextPassThru, tag, buf);
214  processLemma(u->suspendTextPassThru, tag, buf);
215  }
216  if ((attrib = tag.getAttribute("POS"))) {
217  val = strchr(attrib, ':');
218  val = (val) ? (val + 1) : attrib;
219  outText(" ", buf, u);
220  outText(val, buf, u);
221  }
222 
223  /*if (endTag)
224  buf += "}";*/
225  }
226  }
227 
228  // <note> tag
229  else if (!strcmp(tag.getName(), "note")) {
230  if (!tag.isEndTag()) {
231  SWBuf type = tag.getAttribute("type");
232  bool strongsMarkup = (type == "x-strongsMarkup" || type == "strongsMarkup"); // the latter is deprecated
233  if (strongsMarkup) {
234  tag.setEmpty(false); // handle bug in KJV2003 module where some note open tags were <note ... />
235  }
236 
237  if (!tag.isEmpty()) {
238 
239  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
240  SWBuf footnoteNumber = tag.getAttribute("swordFootnote");
241  SWBuf noteName = tag.getAttribute("n");
242  char ch = ((tag.getAttribute("type") && ((!strcmp(tag.getAttribute("type"), "crossReference")) || (!strcmp(tag.getAttribute("type"), "x-cross-ref")))) ? 'x':'n');
243 
244  u->inXRefNote = true; // Why this change? Ben Morgan: Any note can have references in, so we need to set this to true for all notes
245 // u->inXRefNote = (ch == 'x');
246  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>",
247  ch,
248  URL::encode(footnoteNumber.c_str()).c_str(),
249  URL::encode(u->version.c_str()).c_str(),
250  URL::encode(u->vkey ? u->vkey->getText() : u->key->getText()).c_str(),
251  ch,
252  ch,
253  (renderNoteNumbers ? noteName.c_str() : ""));
254  }
255  }
256  u->suspendTextPassThru = (++u->suspendLevel);
257  }
258  if (tag.isEndTag()) {
259  u->suspendTextPassThru = (--u->suspendLevel);
260  u->inXRefNote = false;
261  u->lastSuspendSegment = ""; // fix/work-around for nasb divineName in note bug
262  }
263  }
264 
265  // <p> paragraph and <lg> linegroup tags
266  else if (!strcmp(tag.getName(), "p") || !strcmp(tag.getName(), "lg")) {
267  if ((!tag.isEndTag()) && (!tag.isEmpty())) { // non-empty start tag
268  outText("<!P><br />", buf, u);
269  }
270  else if (tag.isEndTag()) { // end tag
271  outText("<!/P><br />", buf, u);
272  userData->supressAdjacentWhitespace = true;
273  }
274  else { // empty paragraph break marker
275  outText("<!P><br />", buf, u);
276  userData->supressAdjacentWhitespace = true;
277  }
278  }
279 
280  // Milestoned paragraphs, created by osis2mod
281  // <div type="paragraph" sID.../>
282  // <div type="paragraph" eID.../>
283  else if (tag.isEmpty() && !strcmp(tag.getName(), "div") && tag.getAttribute("type") && (!strcmp(tag.getAttribute("type"), "x-p") || !strcmp(tag.getAttribute("type"), "paragraph"))) {
284  // <div type="paragraph" sID... />
285  if (tag.getAttribute("sID")) { // non-empty start tag
286  outText("<!P><br />", buf, u);
287  }
288  // <div type="paragraph" eID... />
289  else if (tag.getAttribute("eID")) {
290  outText("<!/P><br />", buf, u);
291  userData->supressAdjacentWhitespace = true;
292  }
293  }
294 
295  // <reference> tag
296  else if (!strcmp(tag.getName(), "reference")) {
297  if (!u->inXRefNote) { // only show these if we're not in an xref note
298  if (!tag.isEndTag()) {
299  SWBuf target;
300  SWBuf work;
301  SWBuf ref;
302  bool is_scripRef = false;
303 
304  target = tag.getAttribute("osisRef");
305  const char* the_ref = strchr(target, ':');
306 
307  if(!the_ref) {
308  // No work
309  ref = target;
310  is_scripRef = true;
311  }
312  else {
313  // Compensate for starting :
314  ref = the_ref + 1;
315 
316  int size = (int)(target.size() - ref.size() - 1);
317  work.setSize(size);
318  strncpy(work.getRawData(), target, size);
319 
320  // For Bible:Gen.3.15 or Bible.vulgate:Gen.3.15
321  if(!strncmp(work, "Bible", 5))
322  is_scripRef = true;
323  }
324 
325  if(is_scripRef)
326  {
327  buf.appendFormatted("<a href=\"passagestudy.jsp?action=showRef&type=scripRef&value=%s&module=\">",
328  URL::encode(ref.c_str()).c_str()
329 // (work.size()) ? URL::encode(work.c_str()).c_str() : "")
330  );
331  }
332  else
333  {
334  // Dictionary link, or something
335  buf.appendFormatted("<a href=\"sword://%s/%s\">",
336  URL::encode(work.c_str()).c_str(),
337  URL::encode(ref.c_str()).c_str()
338  );
339  }
340  }
341  else {
342  outText("</a>", buf, u);
343  }
344  }
345  }
346 
347  // <l> poetry, etc
348  else if (!strcmp(tag.getName(), "l")) {
349  // end line marker
350  if (tag.getAttribute("eID")) {
351  outText("<br />", buf, u);
352  }
353  // <l/> without eID or sID
354  // Note: this is improper osis. This should be <lb/>
355  else if (tag.isEmpty() && !tag.getAttribute("sID")) {
356  outText("<br />", buf, u);
357  }
358  // end of the line
359  else if (tag.isEndTag()) {
360  outText("<br />", buf, u);
361  }
362  }
363 
364  // <lb.../>
365  else if (!strcmp(tag.getName(), "lb") && (!tag.getAttribute("type") || strcmp(tag.getAttribute("type"), "x-optional"))) {
366  outText("<br />", buf, u);
367  userData->supressAdjacentWhitespace = true;
368  }
369  // <milestone type="line"/>
370  // <milestone type="x-p"/>
371  // <milestone type="cQuote" marker="x"/>
372  else if ((!strcmp(tag.getName(), "milestone")) && (tag.getAttribute("type"))) {
373  if (!strcmp(tag.getAttribute("type"), "line")) {
374  outText("<br />", buf, u);
375  if (tag.getAttribute("subType") && !strcmp(tag.getAttribute("subType"), "x-PM")) {
376  outText("<br />", buf, u);
377  }
378  userData->supressAdjacentWhitespace = true;
379  }
380  else if (!strcmp(tag.getAttribute("type"),"x-p")) {
381  if (tag.getAttribute("marker"))
382  outText(tag.getAttribute("marker"), buf, u);
383  else outText("<!p>", buf, u);
384  }
385  else if (!strcmp(tag.getAttribute("type"), "cQuote")) {
386  const char *tmp = tag.getAttribute("marker");
387  bool hasMark = tmp;
388  SWBuf mark = tmp;
389  tmp = tag.getAttribute("level");
390  int level = (tmp) ? atoi(tmp) : 1;
391 
392  // first check to see if we've been given an explicit mark
393  if (hasMark)
394  outText(mark, buf, u);
395  // finally, alternate " and ', if config says we should supply a mark
396  else if (u->osisQToTick)
397  outText((level % 2) ? '\"' : '\'', buf, u);
398  }
399  }
400 
401  // <title>
402  else if (!strcmp(tag.getName(), "title")) {
403  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
404  outText("<b>", buf, u);
405  }
406  else if (tag.isEndTag()) {
407  outText("</b><br />", buf, u);
408  }
409  }
410 
411  // <list>
412  else if (!strcmp(tag.getName(), "list")) {
413  if((!tag.isEndTag()) && (!tag.isEmpty())) {
414  outText("<ul>", buf, u);
415  }
416  else if (tag.isEndTag()) {
417  outText("</ul>", buf, u);
418  }
419  }
420 
421  // <item>
422  else if (!strcmp(tag.getName(), "item")) {
423  if((!tag.isEndTag()) && (!tag.isEmpty())) {
424  outText("<li>", buf, u);
425  }
426  else if (tag.isEndTag()) {
427  outText("</li>", buf, u);
428  }
429  }
430  // <catchWord> & <rdg> tags (italicize)
431  else if (!strcmp(tag.getName(), "rdg") || !strcmp(tag.getName(), "catchWord")) {
432  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
433  outText("<i>", buf, u);
434  }
435  else if (tag.isEndTag()) {
436  outText("</i>", buf, u);
437  }
438  }
439 
440  // divineName
441  else if (!strcmp(tag.getName(), "divineName")) {
442  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
443  u->suspendTextPassThru = (++u->suspendLevel);
444  }
445  else if (tag.isEndTag()) {
446  SWBuf lastText = u->lastSuspendSegment.c_str();
447  u->suspendTextPassThru = (--u->suspendLevel);
448  if (lastText.size()) {
449  lastText.toUpper();
450  scratch.setFormatted("%c<font size=\"-1\">%s</font>", lastText[0], lastText.c_str()+1);
451 
452  const unsigned char *tmpBuf = (const unsigned char *)lastText.c_str();
453  getUniCharFromUTF8(&tmpBuf);
454  int char_length = (int)(tmpBuf - (const unsigned char *)lastText.c_str());
455  scratch.setFormatted("%.*s<font size=\"-1\">%s</font>",
456  char_length,
457  lastText.c_str(),
458  lastText.c_str() + char_length
459  );
460 
461  outText(scratch.c_str(), buf, u);
462  }
463  }
464  }
465 
466  // <hi> text highlighting
467  else if (!strcmp(tag.getName(), "hi")) {
468  SWBuf type = tag.getAttribute("type");
469  // handle tei rend attribute
470  if (!type.length()) type = tag.getAttribute("rend");
471  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
472  if (type == "bold" || type == "b" || type == "x-b") {
473  outText("<b>", buf, u);
474  }
475  else if (type == "ol" || type == "overline" || type == "x-overline") {
476  outText("<span style=\"text-decoration:overline\">", buf, u);
477  }
478  else if (type == "super") {
479  outText("<sup>", buf, u);
480  }
481  else if (type == "sub") {
482  outText("<sub>", buf, u);
483  }
484  else { // all other types
485  outText("<i>", buf, u);
486  }
487  u->tagStacks->hiStack.push(tag.toString());
488  }
489  else if (tag.isEndTag()) {
490  SWBuf type = "";
491  if (!u->tagStacks->hiStack.empty()) {
492  XMLTag tag(u->tagStacks->hiStack.top());
493  u->tagStacks->hiStack.pop();
494  type = tag.getAttribute("type");
495  if (!type.length()) type = tag.getAttribute("rend");
496  }
497  if (type == "bold" || type == "b" || type == "x-b") {
498  outText("</b>", buf, u);
499  }
500  else if (type == "ol") {
501  outText("</span>", buf, u);
502  }
503  else if (type == "super") {
504  outText("</sup>", buf, u);
505  }
506  else if (type == "sub") {
507  outText("</sub>", buf, u);
508  }
509  else {
510  outText("</i>", buf, u);
511  }
512  }
513  }
514 
515  // <q> quote
516  // Rules for a quote element:
517  // If the tag is empty with an sID or an eID then use whatever it specifies for quoting.
518  // Note: empty elements without sID or eID are ignored.
519  // If the tag is <q> then use it's specifications and push it onto a stack for </q>
520  // If the tag is </q> then use the pushed <q> for specification
521  // If there is a marker attribute, possibly empty, this overrides osisQToTick.
522  // If osisQToTick, then output the marker, using level to determine the type of mark.
523  else if (!strcmp(tag.getName(), "q")) {
524  SWBuf type = tag.getAttribute("type");
525  SWBuf who = tag.getAttribute("who");
526  const char *tmp = tag.getAttribute("level");
527  int level = (tmp) ? atoi(tmp) : 1;
528  tmp = tag.getAttribute("marker");
529  bool hasMark = tmp;
530  SWBuf mark = tmp;
531 
532  // open <q> or <q sID... />
533  if ((!tag.isEmpty() && !tag.isEndTag()) || (tag.isEmpty() && tag.getAttribute("sID"))) {
534  // if <q> then remember it for the </q>
535  if (!tag.isEmpty()) {
536  u->tagStacks->quoteStack.push(tag.toString());
537  }
538 
539  // Do this first so quote marks are included as WoC
540  if (who == "Jesus")
541  outText(u->wordsOfChristStart, buf, u);
542 
543  // first check to see if we've been given an explicit mark
544  if (hasMark)
545  outText(mark, buf, u);
546  //alternate " and '
547  else if (u->osisQToTick)
548  outText((level % 2) ? '\"' : '\'', buf, u);
549  }
550  // close </q> or <q eID... />
551  else if ((tag.isEndTag()) || (tag.isEmpty() && tag.getAttribute("eID"))) {
552  // if it is </q> then pop the stack for the attributes
553  if (tag.isEndTag() && !u->tagStacks->quoteStack.empty()) {
554  XMLTag qTag(u->tagStacks->quoteStack.top());
555  u->tagStacks->quoteStack.pop();
556 
557  type = qTag.getAttribute("type");
558  who = qTag.getAttribute("who");
559  tmp = qTag.getAttribute("level");
560  level = (tmp) ? atoi(tmp) : 1;
561  tmp = qTag.getAttribute("marker");
562  hasMark = tmp;
563  mark = tmp;
564  }
565 
566  // first check to see if we've been given an explicit mark
567  if (hasMark)
568  outText(mark, buf, u);
569  // finally, alternate " and ', if config says we should supply a mark
570  else if (u->osisQToTick)
571  outText((level % 2) ? '\"' : '\'', buf, u);
572 
573  // Do this last so quote marks are included as WoC
574  if (who == "Jesus")
575  outText(u->wordsOfChristEnd, buf, u);
576  }
577  }
578 
579  // <transChange>
580  else if (!strcmp(tag.getName(), "transChange")) {
581  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
582  SWBuf type = tag.getAttribute("type");
583  u->lastTransChange = type;
584 
585  // just do all transChange tags this way for now
586  if ((type == "added") || (type == "supplied"))
587  outText("<i>", buf, u);
588  else if (type == "tenseChange")
589  outText( "*", buf, u);
590  }
591  else if (tag.isEndTag()) {
592  SWBuf type = u->lastTransChange;
593  if ((type == "added") || (type == "supplied"))
594  outText("</i>", buf, u);
595  }
596  else { // empty transChange marker?
597  }
598  }
599 
600  // image
601  else if (!strcmp(tag.getName(), "figure")) {
602  const char *src = tag.getAttribute("src");
603  if (!src) // assert we have a src attribute
604  return false;
605 
606  SWBuf filepath;
607  if (userData->module) {
608  filepath = userData->module->getConfigEntry("AbsoluteDataPath");
609  if ((filepath.size()) && (filepath[filepath.size()-1] != '/') && (src[0] != '/'))
610  filepath += '/';
611  }
612  filepath += src;
613 
614  // images become clickable, if the UI supports showImage.
615  outText("<a href=\"passagestudy.jsp?action=showImage&value=", buf, u);
616  outText(URL::encode(filepath.c_str()).c_str(), buf, u);
617  outText("&module=", buf, u);
618  outText(URL::encode(u->version.c_str()).c_str(), buf, u);
619  outText("\">", buf, u);
620 
621  outText("<img src=\"file:", buf, u);
622  outText(filepath, buf, u);
623  outText("\" border=\"0\" />", buf, u);
624 
625  outText("</a>", buf, u);
626  }
627 
628  else {
629  return false; // we still didn't handle token
630  }
631  }
632  return true;
633 }
634 
635 
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
unsigned long length() const
Definition: swbuf.h:197
const char * getType() const
Definition: swmodule.cpp:232
void setEmpty(bool value)
Definition: utilxml.h:66
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
const char * toString() const
Definition: utilxml.cpp:285
void setTokenCaseSensitive(bool val)
bool renderNoteNumbers
Definition: osishtmlhref.h:36
void setEscapeStart(const char *escStart)
bool isEmpty() const
Definition: utilxml.h:60
bool substituteToken(SWBuf &buf, const char *token)
const VerseKey * vkey
Definition: swbasicfilter.h:44
virtual const char * getText() const
Definition: versekey.cpp:1242
virtual const char * getText() const
Definition: swkey.cpp:184
std::stack< SWBuf > TagStack
MyUserData(const SWModule *module, const SWKey *key)
void processLemma(bool suspendTextPassThru, XMLTag &tag, SWBuf &buf)
void setTokenStart(const char *tokenStart)
char * getRawData()
Definition: swbuf.h:379
const char * c_str() const
Definition: swbuf.h:158
void setPassThruNumericEscapeString(bool val)
static void outText(const char *t, SWBuf &o, BasicFilterUserData *u)
void processMorph(bool suspendTextPassThru, XMLTag &tag, SWBuf &buf)
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
SWBuf & toUpper()
Definition: swbuf.cpp:132
void setEscapeStringCaseSensitive(bool val)
bool isEndTag(const char *eID=0) const
Definition: utilxml.cpp:323
virtual bool handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData)
void setEscapeEnd(const char *escEnd)
#define SWORD_NAMESPACE_END
Definition: defs.h:40
SWBuf & setFormatted(const char *format,...)
Definition: swbuf.cpp:50
Definition: swkey.h:77
static const SWBuf encode(const char *urlText)
Definition: url.cpp:231
SW_u32 getUniCharFromUTF8(const unsigned char **buf, bool skipValidation=false)
Definition: utilstr.h:88
void setSize(unsigned long len)
Definition: swbuf.h:255
int getAttributePartCount(const char *attribName, char partSplit= '|') const
Definition: utilxml.cpp:218