1 /******************************************************************************
2  *
3  *  gbfrtf.cpp -	SWFilter descendant to convert all GBF tags to RTF tags
4  *
5  * $Id: gbfrtf.cpp 3427 2016-07-03 14:30:33Z scribe $
6  *
7  * Copyright 1997-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 <gbfrtf.h>
24 #include <utilstr.h>
25 #include <ctype.h>
26 #include <swbuf.h>
27 
28 SWORD_NAMESPACE_START
29 
GBFRTF()30 GBFRTF::GBFRTF() {
31 }
32 
33 
processText(SWBuf & text,const SWKey * key,const SWModule * module)34 char GBFRTF::processText(SWBuf &text, const SWKey *key, const SWModule *module)
35 {
36 	char token[2048];
37 	char val[128];
38 	char *valto;
39 	char *num;
40 	int tokpos = 0;
41 	bool intoken = false;
42 	const char *tok;
43 	SWBuf strongnum;
44 	SWBuf strongtense;
45 	bool hideText = false;
46 	int wordCount = 0;
47 
48 	const char *from;
49 	SWBuf orig = text;
50 	from = orig.c_str();
51 	for (text = ""; *from; from++) {
52 		if (*from == '<') {
53 			wordCount = 0;
54 			intoken = true;
55 			tokpos = 0;
56 			token[0] = 0;
57 			token[1] = 0;
58 			token[2] = 0;
59 			continue;
60 		}
61 		if (*from == '>') {
62 			intoken = false;
63 						// process desired tokens
64 			// deal with OSIS note tags.  Just hide till OSISRTF
65 			if (!strncmp(token, "note ", 5)) {
66 				hideText = true;
67 			}
68 			if (!strncmp(token, "/note", 5)) {
69 				hideText = false;
70 			}
71 
72 			switch (*token) {
73 			case 'w':	// OSIS Word (temporary until OSISRTF is done)
74 				strongnum = "";
75 				strongtense = "";
76 				valto = val;
77 				num = strstr(token, "lemma=\"x-Strongs:");
78 				if (num) {
79 					for (num+=17; ((*num) && (*num != '\"')); num++)
80 						*valto++ = *num;
81 					*valto = 0;
82 					if (atoi((!isdigit(*val))?val+1:val) < 5627) {
83 						// normal strongs number
84 						strongnum += "{\\cf3 \\sub <";
85 						for (tok = (!isdigit(*val))?val+1:val; *tok; tok++)
86 							strongnum += *tok;
87 						strongnum += ">}";
88 					}
89 					/*	forget these for now
90 					else {
91 						// verb morph
92 						sprintf(wordstr, "%03d", word-1);
93 						module->getEntryAttributes()["Word"][wordstr]["Morph"] = val;
94 					}
95 					*/
96 				}
97 				else {
98 					num = strstr(token, "lemma=\"strong:");
99 					if (num) {
100 						for (num+=14; ((*num) && (*num != '\"')); num++)
101 							*valto++ = *num;
102 						*valto = 0;
103 						if (atoi((!isdigit(*val))?val+1:val) < 5627) {
104 							// normal strongs number
105 							strongnum += "{\\cf3 \\sub <";
106 							for (tok = (!isdigit(*val))?val+1:val; *tok; tok++)
107 								strongnum += *tok;
108 							strongnum += ">}";
109 						}
110 						/*	forget these for now
111 						else {
112 							// verb morph
113 							sprintf(wordstr, "%03d", word-1);
114 							module->getEntryAttributes()["Word"][wordstr]["Morph"] = val;
115 						}
116 						*/
117 					}
118 				}
119 				valto = val;
120 				num = strstr(token, "morph=\"x-Robinson:");
121 				if (num) {
122 					for (num+=18; ((*num) && (*num != '\"')); num++)
123 						*valto++ = *num;
124 					*valto = 0;
125 					// normal robinsons tense
126 					strongtense += "{\\cf4 \\sub (";
127 					for (tok = val; *tok; tok++)
128 						strongtense += *tok;
129 					strongtense += ")}";
130 				}
131 				continue;
132 
133 			case '/':
134 				if (token[1] == 'w') {
135 					if ((wordCount > 0) || (strongnum != "{\\cf3 \\sub <3588>}")) {
136 						//for (i = 0; i < strongnum.length(); i++)
137 							text += strongnum;
138 					//for (i = 0; i < strongtense.length(); i++)
139 						text += strongtense;
140 					}
141 				}
142 				continue;
143 
144 			case 'W':	// Strongs
145 				switch(token[1]) {
146 				case 'G':               // Greek
147 				case 'H':               // Hebrew
148 					text += "{\\cf3 \\sub <";
149 					for (tok = token + 2; *tok; tok++)
150 						text += *tok;
151 					text += ">}";
152 					continue;
153 
154 				case 'T':               // Tense
155 					text += "{\\cf4 \\sub (";
156 					bool separate = false;
157 					for (tok = token + 2; *tok; tok++) {
158 						if (separate) {
159 							text += "; ";
160 							separate = false;
161 						}
162 						switch (*tok) {
163 						case 'G':
164 						case 'H':
165 							for (tok++; *tok; tok++) {
166 								if (isdigit(*tok)) {
167 									text += *tok;
168 									separate = true;
169 								}
170 								else {
171 									tok--;
172 									break;
173 								}
174 							}
175 							break;
176 						default:
177 							for (; *tok; tok++) {
178 							       text += *tok;
179 							}
180 						}
181 					}
182 					text += ")}";
183 					continue;
184 				}
185 				break;
186 			case 'R':
187 				switch(token[1]) {
188 				case 'X':
189 					text += "<a href=\"\">";
190 				  continue;
191 				case 'x':
192 					text += "</a>";
193 				  continue;
194 				case 'F':               // footnote begin
195 					text += "{\\i1 \\sub [ ";
196 					continue;
197 				case 'f':               // footnote end
198 					text += " ] }";
199 					continue;
200 				}
201 				break;
202 			case 'F':			// font tags
203 				switch(token[1]) {
204 				case 'I':		// italic start
205 					text += "\\i1 ";
206 					continue;
207 				case 'i':		// italic end
208 					text += "\\i0 ";
209 					continue;
210 				case 'B':		// bold start
211 					text += "\\b1 ";
212 					continue;
213 				case 'b':		// bold end
214 					text += "\\b0 ";
215 					continue;
216 				case 'N':
217 					text += '{';
218 					if (!strnicmp(token+2, "Symbol", 6))
219 						text += "\\f7 ";
220                                         if (!strnicmp(token+2, "Courier", 7))
221 						text += "\\f8 ";
222 					continue;
223 				case 'n':
224 					text += '}';
225 					continue;
226 				case 'S':
227 					text += "{\\super ";
228 					continue;
229 				case 's':
230 					text += '}';
231 					continue;
232 				case 'R':
233 					text += "{\\cf6 ";
234 					continue;
235 				case 'r':
236 					text += '}';
237 					continue;
238 				case 'O':
239 				case 'C':
240 					text += "\\scaps1 ";
241 					continue;
242 				case 'o':
243 				case 'c':
244 					text += "\\scaps0 ";
245 					continue;
246 				case 'V':
247 					text += "{\\sub ";
248 					continue;
249 				case 'v':
250 					text += '}';
251 					continue;
252 				case 'U':
253 					text += "\\ul1 ";
254 					continue;
255 				case 'u':
256 					text += "\\ul0 ";
257 					continue;
258 				}
259 				break;
260 			case 'C':			// special character tags
261 				switch(token[1]) {
262 				case 'A':               // ASCII value
263 					text += (char)atoi(&token[2]);
264 					continue;
265 				case 'G':
266 					text += '>';
267 					continue;
268 				case 'L':               // line break
269 					text += "\\line ";
270 					continue;
271 				case 'M':               // new paragraph
272 					text += "\\par ";
273 					continue;
274 				case 'T':
275 					text += '<';
276 				}
277 				break;
278 			case 'T':			// title formatting
279 			  switch(token[1])
280 			    {
281 			    case 'T':               // Book title begin
282 					text += "{\\large ";
283 				 continue;
284 			    case 't':
285 				 text += '}';
286 				 continue;
287 			    case 'S':
288 					text += "\\par {\\i1\\b1 ";
289 			      continue;
290 			    case 's':
291 					text += "}\\par ";
292 			      continue;
293 			    }
294 			  break;
295 			case 'J':	// Strongs
296 				switch(token[1]) {
297 				case 'L':
298 					text += "\\ql ";
299 				case 'C':
300 					text += "\\qc ";
301 				case 'R':
302 					text += "\\qr ";
303                                 case 'F':
304                                 	text += "\\qj ";
305                                 }
306 			}
307 			continue;
308 		}
309 		if (intoken) {
310 			if (tokpos < 2045) {
311 				token[tokpos++] = *from;
312 				// TODO: why is this + 2 ?
313 				token[tokpos+2] = 0;
314 			}
315 		}
316 		else {
317 			if (!hideText) {
318 				wordCount++;
319 				text += *from;
320 			}
321 		}
322 	}
323 	return 0;
324 }
325 
326 SWORD_NAMESPACE_END
327 
328