1 /******************************************************************************
2  *
3  *  thmlstrongs.cpp -	SWFilter descendant to hide or show Strong's number
4  *			in a ThML module
5  *
6  * $Id: thmlstrongs.cpp 3515 2017-11-01 11:38:09Z scribe $
7  *
8  * Copyright 2001-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 <thmlstrongs.h>
27 #include <swmodule.h>
28 #include <utilstr.h>
29 #include <ctype.h>
30 
31 
32 SWORD_NAMESPACE_START
33 
34 namespace {
35 
36 	static const char oName[] = "Strong's Numbers";
37 	static const char oTip[]  = "Toggles Strong's Numbers On and Off if they exist";
38 
oValues()39 	static const StringList *oValues() {
40 		static const SWBuf choices[3] = {"Off", "On", ""};
41 		static const StringList oVals(&choices[0], &choices[2]);
42 		return &oVals;
43 	}
44 }
45 
46 
ThMLStrongs()47 ThMLStrongs::ThMLStrongs() : SWOptionFilter(oName, oTip, oValues()) {
48 }
49 
50 
~ThMLStrongs()51 ThMLStrongs::~ThMLStrongs() {
52 }
53 
54 
processText(SWBuf & text,const SWKey * key,const SWModule * module)55 char ThMLStrongs::processText(SWBuf &text, const SWKey *key, const SWModule *module) {
56 	char token[2048]; // cheese.  Fix.
57 	const char *from;
58 	int tokpos = 0;
59 	bool intoken = false;
60 	bool lastspace = false;
61 	int word = 1;
62 	char val[128];
63 	char wordstr[11];
64 	char *valto;
65 	char *ch;
66 	unsigned int textStart = 0, textEnd = 0;
67 	SWBuf tmp;
68 	bool newText = false;
69 
70 	SWBuf orig = text;
71 	from = orig.c_str();
72 
73 	for (text = ""; *from; from++) {
74 		if (*from == '<') {
75 			intoken = true;
76 			tokpos = 0;
77 			token[0] = 0;
78 			token[1] = 0;
79 			token[2] = 0;
80 			textEnd = (unsigned int)text.length();
81 			continue;
82 		}
83 		if (*from == '>') {	// process tokens
84 			intoken = false;
85 			if (!strnicmp(token, "sync type=\"Strongs\" ", 20)) {	// Strongs
86 				if (module->isProcessEntryAttributes()) {
87 					valto = val;
88 					for (unsigned int i = 27; token[i] != '\"' && i < 150; i++)
89 						*valto++ = token[i];
90 					*valto = 0;
91 					if (atoi((!isdigit(*val))?val+1:val) < 5627) {
92 						// normal strongs number
93 						sprintf(wordstr, "%03d", word);
94 						module->getEntryAttributes()["Word"][wordstr]["PartCount"] = "1";
95 						module->getEntryAttributes()["Word"][wordstr]["Lemma"] = val;
96 						module->getEntryAttributes()["Word"][wordstr]["LemmaClass"] = "strong";
97 						tmp = "";
98 						tmp.append(text.c_str()+textStart, (int)(textEnd - textStart));
99 						module->getEntryAttributes()["Word"][wordstr]["Text"] = tmp;
100 						newText = true;
101 					}
102 					else {
103 /*
104 						// verb morph
105 						sprintf(wordstr, "%03d", word);
106 						module->getEntryAttributes()["Word"][wordstr]["Morph"] = val;
107 						module->getEntryAttributes()["Word"][wordstr]["MorphClass"] = "OLBMorph";
108 */
109 						word--;	// for now, completely ignore this word attribute.
110 					}
111 					word++;
112 				}
113 
114 				if (!option) {	// if we don't want strongs
115 					if ((from[1] == ' ') || (from[1] == ',') || (from[1] == ';') || (from[1] == '.') || (from[1] == '?') || (from[1] == '!') || (from[1] == ')') || (from[1] == '\'') || (from[1] == '\"')) {
116 						if (lastspace)
117 							text--;
118 					}
119 					if (newText) {textStart = (unsigned int)text.length(); newText = false; }
120 					continue;
121 				}
122 			}
123 			if (module->isProcessEntryAttributes()) {
124 				if (!strncmp(token, "sync type=\"morph\"", 17)) {
125 					for (ch = token+17; *ch; ch++) {
126 						if (!strncmp(ch, "class=\"", 7)) {
127 							valto = val;
128 							for (unsigned int i = 7; ch[i] != '\"' && i < 127; i++)
129 								*valto++ = ch[i];
130 							*valto = 0;
131 							sprintf(wordstr, "%03d", word-1);
132 							if ((!stricmp(val, "Robinsons")) || (!stricmp(val, "Robinson"))) {
133 								strcpy(val, "robinson");
134 							}
135 							module->getEntryAttributes()["Word"][wordstr]["MorphClass"] = val;
136 						}
137 						if (!strncmp(ch, "value=\"", 7)) {
138 							valto = val;
139 							for (unsigned int i = 7; ch[i] != '\"' && i < 127; i++)
140 								*valto++ = ch[i];
141 							*valto = 0;
142 							sprintf(wordstr, "%03d", word-1);
143 							module->getEntryAttributes()["Word"][wordstr]["Morph"] = val;
144 						}
145 					}
146 					newText = true;
147 				}
148 			}
149 			// if not a strongs token, keep token in text
150 			text += '<';
151 			text += token;
152 			text += '>';
153 			if (newText) {textStart = (unsigned int)text.length(); newText = false; }
154 			continue;
155 		}
156 		if (intoken) {
157 			if (tokpos < 2045) {
158 				token[tokpos++] = *from;
159 				// TODO: why is this + 2 ?
160 				token[tokpos+2] = 0;
161 			}
162 		}
163 		else {
164 			text += *from;
165 			lastspace = (*from == ' ');
166 		}
167 	}
168 	return 0;
169 }
170 
171 SWORD_NAMESPACE_END
172