The SWORD Project  1.9.0.svnversion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
osisfootnotes.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * osisfootnotes.cpp - SWFilter descendant to hide or show footnotes
4  * in an OSIS module
5  *
6  * $Id: osisfootnotes.cpp 2980 2013-09-14 21:51:47Z scribe $
7  *
8  * Copyright 2003-2013 CrossWire Bible Society (http://www.crosswire.org)
9  * CrossWire Bible Society
10  * P. O. Box 2528
11  * Tempe, AZ 85280-2528
12  *
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by the
15  * Free Software Foundation version 2.
16  *
17  * This program is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * General Public License for more details.
21  *
22  */
23 
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <osisfootnotes.h>
27 #include <swmodule.h>
28 #include <swbuf.h>
29 #include <versekey.h>
30 #include <utilxml.h>
31 #include <utilstr.h>
32 
33 
35 
36 namespace {
37 
38  static const char oName[] = "Footnotes";
39  static const char oTip[] = "Toggles Footnotes On and Off if they exist";
40 
41  static const StringList *oValues() {
42  static const SWBuf choices[3] = {"Off", "On", ""};
43  static const StringList oVals(&choices[0], &choices[2]);
44  return &oVals;
45  }
46 }
47 
48 
50 }
51 
52 
54 }
55 
56 
57 char OSISFootnotes::processText(SWBuf &text, const SWKey *key, const SWModule *module) {
58  SWBuf token;
59  bool intoken = false;
60  bool hide = false;
61  SWBuf tagText;
62  XMLTag startTag;
63  SWBuf refs = "";
64  int footnoteNum = 1;
65  char buf[254];
66  SWKey *p = (module) ? module->createKey() : (key) ? key->clone() : new VerseKey();
67  VerseKey *parser = SWDYNAMIC_CAST(VerseKey, p);
68  if (!parser) {
69  delete p;
70  parser = new VerseKey();
71  }
72  *parser = key->getText();
73 
74  SWBuf orig = text;
75  const char *from = orig.c_str();
76 
77  XMLTag tag;
78  bool strongsMarkup = false;
79 
80 
81  for (text = ""; *from; ++from) {
82 
83  // remove all newlines temporarily to fix kjv2003 module
84  if ((*from == 10) || (*from == 13)) {
85  if ((text.length()>1) && (text[text.length()-2] != ' ') && (*(from+1) != ' '))
86  text.append(' ');
87  continue;
88  }
89 
90 
91  if (*from == '<') {
92  intoken = true;
93  token = "";
94  continue;
95  }
96 
97 
98 
99  if (*from == '>') { // process tokens
100  intoken = false;
101  if (!strncmp(token, "note", 4) || !strncmp(token.c_str(), "/note", 5)) {
102  tag = token;
103 
104  if (!tag.isEndTag()) {
105  if (tag.getAttribute("type") && (!strcmp("x-strongsMarkup", tag.getAttribute("type"))
106  || !strcmp("strongsMarkup", tag.getAttribute("type"))) // deprecated
107  ) {
108  tag.setEmpty(false); // handle bug in KJV2003 module where some note open tags were <note ... />
109  strongsMarkup = true;
110  }
111 
112  if (!tag.isEmpty()) {
113 // if ((!tag.isEmpty()) || (SWBuf("strongsMarkup") == tag.getAttribute("type"))) {
114  refs = "";
115  startTag = tag;
116  hide = true;
117  tagText = "";
118  continue;
119  }
120  }
121  if (hide && tag.isEndTag()) {
122  if (module->isProcessEntryAttributes() && !strongsMarkup) { //don`t parse strongsMarkup to EntryAttributes as Footnote
123  sprintf(buf, "%i", footnoteNum++);
124  StringList attributes = startTag.getAttributeNames();
125  for (StringList::const_iterator it = attributes.begin(); it != attributes.end(); it++) {
126  module->getEntryAttributes()["Footnote"][buf][it->c_str()] = startTag.getAttribute(it->c_str());
127  }
128  module->getEntryAttributes()["Footnote"][buf]["body"] = tagText;
129  startTag.setAttribute("swordFootnote", buf);
130  if ((startTag.getAttribute("type")) && (!strcmp(startTag.getAttribute("type"), "crossReference"))) {
131  if (!refs.length())
132  refs = parser->parseVerseList(tagText.c_str(), *parser, true).getRangeText();
133  module->getEntryAttributes()["Footnote"][buf]["refList"] = refs.c_str();
134  }
135  }
136  hide = false;
137  if (option || (startTag.getAttribute("type") && !strcmp(startTag.getAttribute("type"), "crossReference"))) { // we want the tag in the text; crossReferences are handled by another filter
138  text.append(startTag);
139 // text.append(tagText); // we don't put the body back in because it is retrievable from EntryAttributes["Footnotes"][]["body"].
140  }
141  else continue;
142  }
143  strongsMarkup = false;
144  }
145 
146  // if not a heading token, keep token in text
147  //if ((!strcmp(tag.getName(), "reference")) && (!tag.isEndTag())) {
148  // SWBuf osisRef = tag.getAttribute("osisRef");
149  if (!strncmp(token, "reference", 9)) {
150  if (refs.length()) {
151  refs.append("; ");
152  }
153 
154  const char* attr = strstr(token.c_str() + 9, "osisRef=\"");
155  const char* end = attr ? strchr(attr+9, '"') : 0;
156 
157  if (attr && end) {
158  refs.append(attr+9, end-(attr+9));
159  }
160  }
161  if (!hide) {
162  text.append('<');
163  text.append(token);
164  text.append('>');
165  }
166  else {
167  tagText.append('<');
168  tagText.append(token);
169  tagText.append('>');
170  }
171  continue;
172  }
173  if (intoken) { //copy token
174  token.append(*from);
175  }
176  else if (!hide) { //copy text which is not inside a token
177  text.append(*from);
178  }
179  else tagText.append(*from);
180  }
181  delete parser;
182  return 0;
183 }
184 
186 
#define SWORD_NAMESPACE_START
Definition: defs.h:39
Definition: swbuf.h:47
unsigned long length() const
Definition: swbuf.h:197
void setEmpty(bool value)
Definition: utilxml.h:66
const char * setAttribute(const char *attribName, const char *attribValue, int partNum=-1, char partSplit= '|')
Definition: utilxml.cpp:248
SWText * module
Definition: osis2mod.cpp:105
Definition: utilxml.h:38
bool isEmpty() const
Definition: utilxml.h:60
static const StringList * oValues()
virtual SWKey * clone() const
Definition: swkey.cpp:75
virtual const char * getText() const
Definition: swkey.cpp:184
const StringList getAttributeNames() const
Definition: utilxml.cpp:188
virtual char processText(SWBuf &text, const SWKey *key=0, const SWModule *module=0)
const char * c_str() const
Definition: swbuf.h:158
std::list< SWBuf > StringList
Definition: swmodule.cpp:91
SWBuf & append(const char *str, long max=-1)
Definition: swbuf.h:274
static const char oName[]
virtual ListKey parseVerseList(const char *buf, const char *defaultKey=0, bool expandRange=false, bool useChapterAsVerse=false)
Definition: versekey.cpp:515
#define SWDYNAMIC_CAST(className, object)
Definition: defs.h:47
virtual ~OSISFootnotes()
virtual bool isProcessEntryAttributes() const
Definition: swmodule.h:832
virtual AttributeTypeList & getEntryAttributes() const
Definition: swmodule.h:817
static const char * choices[4]
const char * getAttribute(const char *attribName, int partNum=-1, char partSplit= '|') const
Definition: utilxml.cpp:230
static const char oTip[]
bool isEndTag(const char *eID=0) const
Definition: utilxml.cpp:323
#define SWORD_NAMESPACE_END
Definition: defs.h:40
virtual SWKey * createKey() const
Definition: swmodule.cpp:173
Definition: swkey.h:77