aboutsummaryrefslogblamecommitdiffstats
path: root/src/modules/filters/gbfosis.cpp
blob: 43161d4b9f8a768e3c4b46d2a8c836a9f2bc7be7 (plain) (tree)
























































































































































































































































































































                                                                                                                                                                                  
/******************************************************************************
 *
 * gbfstrongs -	SWFilter decendant to hide or show strongs number
 *			in a GBF module.
 */


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <gbfosis.h>
#include <swmodule.h>
#include <versekey.h>
#include <stdarg.h>
#ifndef __GNUC__
#else
#include <unixstr.h>
#endif


GBFOSIS::GBFOSIS() {
}


GBFOSIS::~GBFOSIS() {
}


char GBFOSIS::ProcessText(char *text, int maxlen, const SWKey *key, const SWModule *module) {

	char *to, *from, token[2048]; // cheese.  Fix.
	int tokpos = 0;
	bool intoken = false;
	int len;
	bool lastspace = false;
	int word = 1;
	char val[128];
	char buf[128];
	char wordstr[5];
	char *valto;
	char *ch;
	char *textStart, *textEnd;
	char *wordStart, *wordEnd;
	bool newText = false;
	bool newWord = false;
	string tmp;
	bool suspendTextPassThru = false;
	bool keepToken = false;

	len = strlen(text) + 1;	// shift string to right of buffer
	if (len < maxlen) {
		memmove(&text[maxlen - len], text, len);
		from = &text[maxlen - len];
	}
	else	from = text;
	
	textStart = from;
	wordStart = text;

	// -------------------------------

	for (to = text; *from; from++) {
		if (*from == '<') {
			intoken = true;
			tokpos = 0;
			token[0] = 0;
			token[1] = 0;
			token[2] = 0;
			textEnd = from-1;
			wordEnd = to;
			continue;
		}
		if (*from == '>') {	// process tokens
			intoken = false;
			keepToken = false;
			suspendTextPassThru = false;
			newWord = true;


			while (wordStart < (text+maxlen)) {
//				if (strchr(" ,;.?!()'\"", *wordStart))
				if (strchr(";, .:?!()'\"", *wordStart))
					wordStart++;
				else break;
			}
			while (wordEnd > wordStart) {
				if (strchr(" ,;.:?!()'\"", *wordEnd))
					wordEnd--;
				else break;
			}

			// Scripture Reference
			if (!strncmp(token, "scripRef", 8)) {
	//			pushString(buf, "<reference work=\"Bible.KJV\" reference=\"");
				suspendTextPassThru = true;
				newText = true;
			}
			else	if (!strncmp(token, "/scripRef", 9)) {
				tmp = "";
				tmp.append(textStart, (int)(textEnd - textStart)+1);
				pushString(&to, convertToOSIS(tmp.c_str(), key));
				suspendTextPassThru = false;
			}

			// Footnote
			if (!strcmp(token, "RF")) {
	//			pushString(buf, "<reference work=\"Bible.KJV\" reference=\"");
				suspendTextPassThru = true;
				newText = true;
			}
			else	if (!strcmp(token, "Rf")) {
				tmp = "<note type=\"x-StudyNote\"><notePart type=\"x-MainText\">";
				tmp.append(textStart, (int)(textEnd - textStart)+1);
				tmp += "</notePart></note>";
				pushString(&to, tmp.c_str());
				suspendTextPassThru = false;
			}

			// Figure
			else	if (!strncmp(token, "img ", 4)) {
				const char *src = strstr(token, "src");
				if (!src)		// assert we have a src attribute
					return false;

				pushString(&to, "<figure src=\"");
				const char *c;
				for (c = src;((*c) && (*c != '"')); c++);

				/* uncomment for SWORD absolute path logic
				if (*(c+1) == '/') {
					pushString(buf, "file:");
					pushString(buf, module->getConfigEntry("AbsoluteDataPath"));
					if (*((*buf)-1) == '/')
						c++;		// skip '/'
				}
				end of uncomment for asolute path logic */

				for (c++;((*c) && (*c != '"')); c++)
					*to++ = *c;

				pushString(&to, "\" />");
				return true;
			}

			// Strongs numbers
			else if (*token == 'W' && (token[1] == 'G' || token[1] == 'H')) {	// Strongs
				if (module->isProcessEntryAttributes()) {
					valto = val;
					for (unsigned int i = 1; ((token[i]) && (i < 150)); i++)
						*valto++ = token[i];
					*valto = 0;
					// normal strongs number
					strstrip(val);
					if (!strncmp(wordStart, "<w ", 3)) {
						sprintf(buf, "lemma=\"x-Strong:%s\" ", val);
						memmove(wordStart+3+strlen(buf), wordStart+3, (to-wordStart)+1);
						memcpy(wordStart+3, buf, strlen(buf));
						to+=strlen(buf);
					}
					else {
						sprintf(buf, "<w lemma=\"x-Strong:%s\">", val);
						memmove(wordStart+strlen(buf), wordStart, (to-wordStart)+1);
						memcpy(wordStart, buf, strlen(buf));
						to+=strlen(buf);
						pushString(&to, "</w>");
						module->getEntryAttributes()["Word"][wordstr]["Strongs"] = val;
					}
				}
			}

			// Morphology
			else if (*token == 'W' && token[1] == 'T' && (token[2] == 'G' || token[2] == 'H')) {	// Strongs
				valto = val;
				for (unsigned int i = 1; ((token[i]) && (i < 150)); i++)
					*valto++ = token[i];
				*valto = 0;
				strstrip(val);
				if (!strncmp(wordStart, "<w ", 3)) {
					sprintf(buf, "morph=\"x-%s:%s\" ", "StrongsMorph", val);
					memmove(wordStart+3+strlen(buf), wordStart+3, (to-wordStart)+1);
					memcpy(wordStart+3, buf, strlen(buf));
					to+=strlen(buf);
				}
				else {
					sprintf(buf, "<w morph=\"x-%s:%s\">", "StrongsMorph", val);
					memmove(wordStart+strlen(buf), wordStart, (to-wordStart)+1);
					memcpy(wordStart, buf, strlen(buf));
					to+=strlen(buf);
					pushString(&to, "</w>");
				}
			}

			if (!keepToken) {	// if we don't want strongs
				if (from[1] && strchr(" ,;.:?!()'\"", from[1])) {
					if (lastspace)
						to--;
				}
				if (newText) {textStart = from+1; newText = false; }
//				if (newWord) {wordStart = to; newWord = false; }
				continue;
			}
			// if not a strongs token, keep token in text
			*to++ = '<';
			for (char *tok = token; *tok; tok++)
				*to++ = *tok;
			*to++ = '>';
			if (newText) {textStart = to; newWord = false; }
//			if (newWord) {wordStart = to; newWord = false; }
			continue;
		}
		if (intoken) {
			if ((tokpos < 2045) && ((*from != 10)&&(*from != 13))) {
				token[tokpos++] = *from;
				token[tokpos+2] = 0;
			}
		}
		else	{
			if (newWord && (*from != ' ')) {wordStart = to; newWord = false; memset(to, 0, 10); }
			if (!suspendTextPassThru) {
				*to++ = *from;
				lastspace = (*from == ' ');
			}
		}
	}

	VerseKey *vkey = SWDYNAMIC_CAST(VerseKey, key);
	if (vkey) {
		char ref[254];
		if (vkey->Verse())
			sprintf(ref, "<verseStart ref=\"%s\" />", vkey->getOSISRef());
		else if (vkey->Chapter())
			sprintf(ref, "<chapterStart ref=\"%s\" />", vkey->getOSISRef());
		else if (vkey->Book())
			sprintf(ref, "<bookStart ref=\"%s\" />", vkey->getOSISRef());
		else *ref = 0;
		if (*ref) {
			memmove(text+strlen(ref), text, maxlen-strlen(ref)-1);
			memcpy(text, ref, strlen(ref));
			to+=strlen(ref);
			if (vkey->Verse()) {
				VerseKey tmp;
				tmp = *vkey;
				tmp.AutoNormalize(0);
				tmp.Headings(1);
				sprintf(ref, "<verseEnd ref=\"%s\" />", vkey->getOSISRef());
				pushString(&to, ref);
				tmp = MAXVERSE;
				if (*vkey == tmp) {
					tmp.Verse(0);
					sprintf(ref, "<chapterEnd ref=\"%s\" />", tmp.getOSISRef());
					pushString(&to, ref);
					tmp = MAXCHAPTER;
					tmp = MAXVERSE;
					if (*vkey == tmp) {
						tmp.Chapter(0);
						tmp.Verse(0);
						sprintf(ref, "<bookEnd ref=\"%s\" />", tmp.getOSISRef());
						pushString(&to, ref);
					}
				}
			}

			else if (vkey->Chapter())
				sprintf(ref, "<chapterStart ref=\"%s\" />", vkey->getOSISRef());
			else sprintf(ref, "<bookStart ref=\"%s\" />", vkey->getOSISRef());
		}
	}
	*to++ = 0;
	*to = 0;
	return 0;
}


void GBFOSIS::pushString(char **buf, const char *format, ...) {
  va_list argptr;

  va_start(argptr, format);
  *buf += vsprintf(*buf, format, argptr);
  va_end(argptr);

//  *buf += strlen(*buf);
}


const char *GBFOSIS::convertToOSIS(const char *inRef, const SWKey *key) {
	static string outRef;

	outRef = "";

	VerseKey defLanguage;
	ListKey verses = defLanguage.ParseVerseList(inRef, (*key), true);
	const char *startFrag = inRef;
	for (int i = 0; i < verses.Count(); i++) {
		VerseKey *element = SWDYNAMIC_CAST(VerseKey, verses.GetElement(i));
		char buf[5120];
		char frag[800];
		if (element) {
			memmove(frag, startFrag, ((const char *)element->userData - startFrag) + 1);
			frag[((const char *)element->userData - startFrag) + 1] = 0;
			startFrag = (const char *)element->userData + 1;
			sprintf(buf, "<reference refStart=\"KJV:%s\" refEnd=\"%s\">%s</reference>", element->LowerBound().getOSISRef(), element->UpperBound().getOSISRef(), frag);
		}
		else {
			memmove(frag, startFrag, ((const char *)verses.GetElement(i)->userData - startFrag) + 1);
			frag[((const char *)verses.GetElement(i)->userData - startFrag) + 1] = 0;
			startFrag = (const char *)verses.GetElement(i)->userData + 1;
			sprintf(buf, "<reference refStart=\"KJV:%s\">%s</reference>", VerseKey(*verses.GetElement(i)).getOSISRef(), frag);
		}
		outRef+=buf;
	}
	return outRef.c_str();
}