The SWORD Project  1.9.0.svnversion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
teilatex.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * teilatex.cpp - TEI to LATEX filter
4  *
5  * $Id: teilatex.cpp 3698 2020-02-05 20:15:59Z refdoc $
6  *
7  * Copyright 2012-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 <teilatex.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 TEILaTeX::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 += "";
73  }
74  else if (tag.isEndTag()) { // end tag
75  buf += "//\n";
76  //userData->supressAdjacentWhitespace = true;
77  }
78  else { // empty paragraph break marker
79  buf += "//\n";
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 += "\\it{";
92  else if (rend == "bold")
93  buf += "\\bd{";
94  else if (rend == "super" || rend == "sup")
95  buf += "^{";
96  else if (rend == "sub")
97  buf += "_{";
98  else if (rend == "overline")
99  buf += "\\overline{";
100 
101  }
102  else if (tag.isEndTag()) {
103  buf += "}";
104  }
105  }
106 
107  // <entryFree>
108  else if (!strcmp(tag.getName(), "entryFree")) {
109  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
110  SWBuf n = tag.getAttribute("n");
111  if (n != "") {
112  buf += "\\teiEntryFree{";
113  buf += n;
114  buf += "}";
115  }
116  }
117  }
118 
119  // <sense>
120  else if (!strcmp(tag.getName(), "sense")) {
121  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
122  SWBuf n = tag.getAttribute("n");
123  if (n != "") {
124  buf += "\n\\teiSense{";
125  buf += n;
126  buf += "}";
127  }
128  }
129  }
130 
131  // <div>
132  else if (!strcmp(tag.getName(), "div")) {
133 
134  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
135  buf += "";
136  }
137  else if (tag.isEndTag()) {
138  }
139  }
140 
141  // <lb.../>
142  else if (!strcmp(tag.getName(), "lb")) {
143  buf += "//\n";
144  }
145 
146  // <pos>, <gen>, <case>, <gram>, <number>, <mood>, <pron>, <def>
147  else if (!strcmp(tag.getName(), "pos") ||
148  !strcmp(tag.getName(), "gen") ||
149  !strcmp(tag.getName(), "case") ||
150  !strcmp(tag.getName(), "gram") ||
151  !strcmp(tag.getName(), "number") ||
152  !strcmp(tag.getName(), "pron") ||
153  !strcmp(tag.getName(), "tr") ||
154  !strcmp(tag.getName(), "orth") ||
155  !strcmp(tag.getName(), "etym") ||
156  !strcmp(tag.getName(), "usg") ||
157 
158 
159  !strcmp(tag.getName(), "def")) {
160  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
161  buf += "\\tei";
162  buf += tag.getName();
163  buf += "{";
164  }
165  else if (tag.isEndTag()) {
166  buf += "}";
167  }
168  }
169 
170  else if (!strcmp(tag.getName(), "ref")) {
171  if (!tag.isEndTag()) {
172  u->suspendTextPassThru = true;
173  SWBuf target;
174  SWBuf work;
175  SWBuf ref;
176 
177  int was_osisref = false;
178  if(tag.getAttribute("osisRef"))
179  {
180  target += tag.getAttribute("osisRef");
181  was_osisref=true;
182  }
183  else if(tag.getAttribute("target"))
184  target += tag.getAttribute("target");
185 
186  if(target.size())
187  {
188  const char* the_ref = strchr(target, ':');
189 
190  if(!the_ref) {
191  // No work
192  ref = target;
193  }
194  else {
195  // Compensate for starting :
196  ref = the_ref + 1;
197 
198  int size = target.size() - ref.size() - 1;
199  work.setSize(size);
200  strncpy(work.getRawData(), target, size);
201  }
202 
203  if(was_osisref)
204  {
205  buf.appendFormatted("\\swordref{%s}{%s}{",
206  (ref) ? ref.c_str() : "",
207  (work.size()) ? work.c_str() : "" );
208  }
209  else
210  {
211  // Dictionary link, or something
212  buf.appendFormatted("\\sworddictref{%s}{%s}{",
213  (work.size()) ? work.c_str() : u->version.c_str(),
214  (ref) ? ref.c_str() : ""
215  );
216  }
217  }
218  else
219  {
220  //std::cout << "TARGET WASN'T\n";
221  }
222 
223  }
224  else {
225  buf += u->lastTextNode.c_str();
226  buf += "}";
227 
228  u->suspendTextPassThru = false;
229  }
230  }
231 
232  // <note> tag
233  else if (!strcmp(tag.getName(), "note")) {
234  if (!tag.isEndTag()) {
235  if (!tag.isEmpty()) {
236  u->suspendTextPassThru = true;
237  }
238  }
239  if (tag.isEndTag()) {
240  SWBuf footnoteNumber = tag.getAttribute("swordFootnote");
241  SWBuf noteName = tag.getAttribute("n");
242  SWBuf footnoteBody = "";
243  if (u->module){
244  footnoteBody += u->module->getEntryAttributes()["Footnote"][footnoteNumber]["body"];
245  }
246 
247  buf.appendFormatted("\\swordfootnote{%s}{%s}{%s}{%s}{",
248  footnoteNumber.c_str(),
249  u->version.c_str(),
250  u->key->getText(),
251  renderNoteNumbers ? noteName.c_str() : "");
252  if (u->module) {
253  buf += u->module->renderText(footnoteBody).c_str();
254  }
255  u->suspendTextPassThru = false;
256  }
257  }
258 
259  // <graphic> image tag
260  else if (!strcmp(tag.getName(), "graphic")) {
261  const char *url = tag.getAttribute("url");
262  if (url) { // assert we have a url attribute
263  SWBuf filepath;
264  if (userData->module) {
265  filepath = userData->module->getConfigEntry("AbsoluteDataPath");
266  if ((filepath.size()) && (filepath[filepath.size()-1] != '/') && (url[0] != '/'))
267  filepath += '/';
268  }
269  filepath += url;
270 
271  buf.appendFormatted("\\figure{\\includegraphics{%s}}",
272  filepath.c_str());
273  u->suspendTextPassThru = false;
274 
275  }
276  }
277 
278  // <table> <row> <cell>
279  else if (!strcmp(tag.getName(), "table")) {
280  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
281  buf += "\n\\begin{tabular}";
282  }
283  else if (tag.isEndTag()) {
284  buf += "\n\\end{tabular}";
285  ++u->consecutiveNewlines;
286  u->supressAdjacentWhitespace = true;
287  }
288 
289  }
290  else if (!strcmp(tag.getName(), "row")) {
291  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
292  buf += "\n";
293  u->firstCell = true;
294  }
295  else if (tag.isEndTag()) {
296  buf += "//";
297  u->firstCell = false;
298  }
299 
300  }
301  else if (!strcmp(tag.getName(), "cell")) {
302  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
303  if (u->firstCell == false) {
304  buf += " & ";
305  }
306  else {
307  u->firstCell = false;
308  }
309  }
310  else if (tag.isEndTag()) {
311  buf += "";
312  }
313  }
314  // <list> <item>
315  else if (!strcmp(tag.getName(), "list")) {
316  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
317 
318  SWBuf rend = tag.getAttribute("rend");
319 
320  u->lastHi = rend;
321  if (rend == "numbered") {
322  buf += "\\begin{enumerate}\n";
323  }
324  else if (rend == "bulleted") {
325  buf += "\\begin{itemize}\n";
326  }
327  else {
328  buf += "\\begin{list-";
329  buf += rend.c_str();
330  buf += "}\n";
331  }
332  }
333  else if (tag.isEndTag()) {
334  SWBuf rend = u->lastHi;
335  if (rend == "numbered") {
336  buf += "\\end{enumerate}\n>";
337  }
338  else if (rend == "bulleted") {
339  buf += "\\end{itemize}\n";
340 
341  }
342  else {
343  buf += "\\end{list-";
344  buf += rend;
345  buf += "}\n";
346  }
347  u->supressAdjacentWhitespace = true;
348  }
349  }
350  else if (!strcmp(tag.getName(), "item")) {
351  if ((!tag.isEndTag()) && (!tag.isEmpty())) {
352  buf += "\\item";
353  }
354  }
355  else {
356  return false; // we still didn't handle token
357  }
358 
359 
360  }
361  return true;
362 }
363 
364 
366 
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)
bool renderNoteNumbers
Definition: teilatex.h:36
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)
SWBuf renderText(const char *buf, int len=-1, bool render=true) const
Definition: swmodule.cpp:1038
bool isEmpty() const
Definition: utilxml.h:60
bool substituteToken(SWBuf &buf, const char *token)
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
virtual bool handleToken(SWBuf &buf, const char *token, BasicFilterUserData *userData)
Definition: teilatex.cpp:64
unsigned long size() const
Definition: swbuf.h:185
const SWKey * key
Definition: swbasicfilter.h:43
virtual AttributeTypeList & getEntryAttributes() const
Definition: swmodule.h:817
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
TEILaTeX()
Definition: teilatex.cpp:44
void setEscapeEnd(const char *escEnd)
#define SWORD_NAMESPACE_END
Definition: defs.h:40
Definition: swkey.h:77
MyUserData(const SWModule *module, const SWKey *key)
Definition: teilatex.cpp:35
void setSize(unsigned long len)
Definition: swbuf.h:255