1 /******************************************************************************
2  *
3  *  ztext.cpp -	code for class 'zText'- a module that reads compressed text
4  *		files
5  *
6  * $Id: ztext.cpp 2980 2013-09-14 21:51:47Z scribe $
7  *
8  * Copyright 1996-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 <ctype.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <sysdata.h>
28 #include <versekey.h>
29 #include <filemgr.h>
30 
31 #include <ztext.h>
32 
33 SWORD_NAMESPACE_START
34 
35 /******************************************************************************
36  * zText Constructor - Initializes data for instance of zText
37  *
38  * ENT:	ipath - path to data files
39  *		iname - Internal name for module
40  *		idesc - Name to display to user for module
41  *		iblockType - verse, chapter, book, etc. of index chunks
42  *		icomp - Compressor object
43  *		idisp - Display object to use for displaying
44  */
45 
zText(const char * ipath,const char * iname,const char * idesc,int iblockType,SWCompress * icomp,SWDisplay * idisp,SWTextEncoding enc,SWTextDirection dir,SWTextMarkup mark,const char * ilang,const char * versification)46 zText::zText(const char *ipath, const char *iname, const char *idesc, int iblockType, SWCompress *icomp, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char *ilang, const char *versification)
47 		: zVerse(ipath, FileMgr::RDWR, iblockType, icomp), SWText(iname, idesc, idisp, enc, dir, mark, ilang, versification) {
48 	blockType = iblockType;
49 	lastWriteKey = 0;
50 }
51 
52 
53 /******************************************************************************
54  * zText Destructor - Cleans up instance of zText
55  */
56 
~zText()57 zText::~zText()
58 {
59 	flushCache();
60 
61 	if (lastWriteKey)
62 		delete lastWriteKey;
63 
64 }
65 
66 
isWritable() const67 bool zText::isWritable() const { return ((idxfp[0]->getFd() > 0) && ((idxfp[0]->mode & FileMgr::RDWR) == FileMgr::RDWR)); }
68 
69 
70 /******************************************************************************
71  * zText::getRawEntry	- Returns the current verse buffer
72  *
73  * RET: buffer with verse
74  */
75 
getRawEntryBuf() const76 SWBuf &zText::getRawEntryBuf() const {
77 	long  start = 0;
78 	unsigned short size = 0;
79 	unsigned long buffnum = 0;
80 	VerseKey &key = getVerseKey();
81 
82 	findOffset(key.getTestament(), key.getTestamentIndex(), &start, &size, &buffnum);
83 	entrySize = size;        // support getEntrySize call
84 
85 	entryBuf = "";
86 
87 	zReadText(key.getTestament(), start, size, buffnum, entryBuf);
88 	rawFilter(entryBuf, &key);
89 
90 //	if (!isUnicode())
91 		prepText(entryBuf);
92 
93 	return entryBuf;
94 }
95 
96 
sameBlock(VerseKey * k1,VerseKey * k2)97 bool zText::sameBlock(VerseKey *k1, VerseKey *k2) {
98 	if (k1->getTestament() != k2->getTestament())
99 		return false;
100 
101 	switch (blockType) {
102 	case VERSEBLOCKS:
103 		if (k1->getVerse() != k2->getVerse())
104 			return false;
105 	case CHAPTERBLOCKS:
106 		if (k1->getChapter() != k2->getChapter())
107 			return false;
108 	case BOOKBLOCKS:
109 		if (k1->getBook() != k2->getBook())
110 			return false;
111 	}
112 	return true;
113 }
114 
115 
setEntry(const char * inbuf,long len)116 void zText::setEntry(const char *inbuf, long len) {
117 	VerseKey &key = getVerseKey();
118 
119 	// see if we've jumped across blocks since last write
120 	if (lastWriteKey) {
121 		if (!sameBlock(lastWriteKey, &key)) {
122 			flushCache();
123 		}
124 		delete lastWriteKey;
125 	}
126 
127 	doSetText(key.getTestament(), key.getTestamentIndex(), inbuf, len);
128 
129 	lastWriteKey = (VerseKey *)key.clone();	// must delete
130 }
131 
132 
linkEntry(const SWKey * inkey)133 void zText::linkEntry(const SWKey *inkey) {
134 	VerseKey &destkey = getVerseKey();
135 	const VerseKey *srckey = &getVerseKey(inkey);
136 	doLinkEntry(destkey.getTestament(), destkey.getTestamentIndex(), srckey->getTestamentIndex());
137 }
138 
139 
140 /******************************************************************************
141  * zFiles::deleteEntry	- deletes this entry
142  *
143  */
144 
deleteEntry()145 void zText::deleteEntry() {
146 
147 	VerseKey &key = getVerseKey();
148 
149 	doSetText(key.getTestament(), key.getTestamentIndex(), "");
150 }
151 
152 
153 /******************************************************************************
154  * zText::increment	- Increments module key a number of entries
155  *
156  * ENT:	increment	- Number of entries to jump forward
157  *
158  */
159 
increment(int steps)160 void zText::increment(int steps) {
161 	long start;
162 	unsigned short size;
163 	unsigned long buffnum;
164 	VerseKey *tmpkey = &getVerseKey();
165 
166 	findOffset(tmpkey->getTestament(), tmpkey->getTestamentIndex(), &start, &size, &buffnum);
167 
168 	SWKey lastgood = *tmpkey;
169 	while (steps) {
170 		long laststart = start;
171 		unsigned short lastsize = size;
172 		SWKey lasttry = *tmpkey;
173 		(steps > 0) ? ++(*key) : --(*key);
174 		tmpkey = &getVerseKey();
175 
176 		if ((error = key->popError())) {
177 			*key = lastgood;
178 			break;
179 		}
180 		long index = tmpkey->getTestamentIndex();
181 		findOffset(tmpkey->getTestament(), index, &start, &size, &buffnum);
182 
183 		if (
184 			(
185 				((laststart != start) || (lastsize != size))	// we're a different entry
186 //				&& (start > 0)
187 				&& (size)	// and we actually have a size
188 			)
189 			|| !skipConsecutiveLinks
190 		) {	// or we don't want to skip consecutive links
191 			steps += (steps < 0) ? 1 : -1;
192 			lastgood = *tmpkey;
193 		}
194 	}
195 	error = (error) ? KEYERR_OUTOFBOUNDS : 0;
196 }
197 
198 
isLinked(const SWKey * k1,const SWKey * k2) const199 bool zText::isLinked(const SWKey *k1, const SWKey *k2) const {
200 	long start1, start2;
201 	unsigned short size1, size2;
202 	unsigned long buffnum1, buffnum2;
203 	VerseKey *vk1 = &getVerseKey(k1);
204 	VerseKey *vk2 = &getVerseKey(k2);
205 	if (vk1->getTestament() != vk2->getTestament()) return false;
206 
207 	findOffset(vk1->getTestament(), vk1->getTestamentIndex(), &start1, &size1, &buffnum1);
208 	findOffset(vk2->getTestament(), vk2->getTestamentIndex(), &start2, &size2, &buffnum2);
209 	return start1 == start2 && buffnum1 == buffnum2;
210 }
211 
hasEntry(const SWKey * k) const212 bool zText::hasEntry(const SWKey *k) const {
213 	long start;
214 	unsigned short size;
215 	unsigned long buffnum;
216 	VerseKey *vk = &getVerseKey(k);
217 
218 	findOffset(vk->getTestament(), vk->getTestamentIndex(), &start, &size, &buffnum);
219 	return size;
220 }
221 
222 
223 SWORD_NAMESPACE_END
224