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