1 /******************************************************************************
2  *
3  *  zcom.cpp -	code for class 'zCom'- a module that reads raw commentary
4  *		files
5  *
6  * $Id: zcom.cpp 3073 2014-03-05 00:27:52Z 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 
28 #include <swbuf.h>
29 #include <zverse.h>
30 #include <versekey.h>
31 #include <zcom.h>
32 #include <filemgr.h>
33 
34 SWORD_NAMESPACE_START
35 
36 /******************************************************************************
37  * zCom Constructor - Initializes data for instance of zCom
38  *
39  * ENT:	ipath - path to data files
40  *		iname - Internal name for module
41  *		idesc - Name to display to user for module
42  *		iblockType - verse, chapter, book, etc. of index chunks
43  *		icomp - Compressor object
44  *		idisp - Display object to use for displaying
45  */
46 
zCom(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 zCom::zCom(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) : zVerse(ipath, -1, iblockType, icomp), SWCom(iname, idesc, idisp, enc, dir, mark, ilang, versification)/*, SWCompress()*/
48 {
49 	blockType = iblockType;
50 	lastWriteKey = 0;
51 }
52 
53 /******************************************************************************
54  * zCom Destructor - Cleans up instance of zCom
55  */
56 
~zCom()57 zCom::~zCom() {
58 	flushCache();
59 
60 	if (lastWriteKey)
61 		delete lastWriteKey;
62 }
63 
64 
isWritable() const65 bool zCom::isWritable() const {
66 	return ((idxfp[0]->getFd() > 0) && ((idxfp[0]->mode & FileMgr::RDWR) == FileMgr::RDWR));
67 }
68 
69 
70 /******************************************************************************
71  * zCom::getRawEntry	- Returns the current verse buffer
72  *
73  * RET: buffer with verse
74  */
75 
getRawEntryBuf() const76 SWBuf &zCom::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 zCom::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 
setEntry(const char * inbuf,long len)115 void zCom::setEntry(const char *inbuf, long len) {
116 	VerseKey *key = &getVerseKey();
117 
118 	// see if we've jumped across blocks since last write
119 	if (lastWriteKey) {
120 		if (!sameBlock(lastWriteKey, key)) {
121 			flushCache();
122 		}
123 		delete lastWriteKey;
124 	}
125 
126 	doSetText(key->getTestament(), key->getTestamentIndex(), inbuf, len);
127 
128 	lastWriteKey = (VerseKey *)key->clone();	// must delete
129 }
130 
131 
linkEntry(const SWKey * inkey)132 void zCom::linkEntry(const SWKey *inkey) {
133 	VerseKey *destkey = &getVerseKey();
134 	const VerseKey *srckey = &getVerseKey(inkey);
135 
136 	doLinkEntry(destkey->getTestament(), destkey->getTestamentIndex(), srckey->getTestamentIndex());
137 
138 	if (inkey != srckey) // free our key if we created a VerseKey
139 		delete srckey;
140 }
141 
142 /******************************************************************************
143  * zCom::deleteEntry	- deletes this entry
144  *
145  * RET: *this
146  */
147 
deleteEntry()148 void zCom::deleteEntry() {
149 
150 	VerseKey *key = &getVerseKey();
151 	doSetText(key->getTestament(), key->getTestamentIndex(), "");
152 }
153 
154 
155 /******************************************************************************
156  * zCom::increment	- Increments module key a number of entries
157  *
158  * ENT:	increment	- Number of entries to jump forward
159  *
160  * RET: *this
161  */
162 
increment(int steps)163 void zCom::increment(int steps) {
164 	long  start;
165 	unsigned short size;
166 	unsigned long buffnum;
167 	VerseKey *tmpkey = &getVerseKey();
168 
169 	findOffset(tmpkey->getTestament(), tmpkey->getTestamentIndex(), &start, &size, &buffnum);
170 
171 	SWKey lastgood = *tmpkey;
172 	while (steps) {
173 		long laststart = start;
174 		unsigned short lastsize = size;
175 		SWKey lasttry = *tmpkey;
176 		(steps > 0) ? ++(*key) : --(*key);
177 		tmpkey = &getVerseKey();
178 
179 		if ((error = key->popError())) {
180 			*key = lastgood;
181 			break;
182 		}
183 		long index = tmpkey->getTestamentIndex();
184 		findOffset(tmpkey->getTestament(), index, &start, &size, &buffnum);
185 		if (
186 			(((laststart != start) || (lastsize != size))	// we're a different entry
187 //				&& (start > 0)
188 				&& (size))	// and we actually have a size
189 				||(!skipConsecutiveLinks)) {	// or we don't want to skip consecutive links
190 			steps += (steps < 0) ? 1 : -1;
191 			lastgood = *tmpkey;
192 		}
193 	}
194 	error = (error) ? KEYERR_OUTOFBOUNDS : 0;
195 }
196 
isLinked(const SWKey * k1,const SWKey * k2) const197 bool zCom::isLinked(const SWKey *k1, const SWKey *k2) const {
198 	long start1, start2;
199 	unsigned short size1, size2;
200 	unsigned long buffnum1, buffnum2;
201 	VerseKey *vk1 = &getVerseKey(k1);
202 	VerseKey *vk2 = &getVerseKey(k2);
203 	if (vk1->getTestament() != vk2->getTestament()) return false;
204 
205 	findOffset(vk1->getTestament(), vk1->getTestamentIndex(), &start1, &size1, &buffnum1);
206 	findOffset(vk2->getTestament(), vk2->getTestamentIndex(), &start2, &size2, &buffnum2);
207 	return start1 == start2 && buffnum1 == buffnum2;
208 }
209 
hasEntry(const SWKey * k) const210 bool zCom::hasEntry(const SWKey *k) const {
211 	long start;
212 	unsigned short size;
213 	unsigned long buffnum;
214 	VerseKey *vk = &getVerseKey(k);
215 
216 	findOffset(vk->getTestament(), vk->getTestamentIndex(), &start, &size, &buffnum);
217 	return size;
218 }
219 
220 SWORD_NAMESPACE_END
221