1
/******************************************************************************
2
* listkey.cpp - code for base class 'ListKey'. ListKey is the basis for all
3
* types of keys that have lists of specified indexes
4
* (e.g. a list of verses, place, etc.)
7
* Copyright 2009 CrossWire Bible Society (http://www.crosswire.org)
8
* CrossWire Bible Society
10
* Tempe, AZ 85280-2528
12
* This program is free software; you can redistribute it and/or modify it
13
* under the terms of the GNU General Public License as published by the
14
* Free Software Foundation version 2.
16
* This program is distributed in the hope that it will be useful, but
17
* WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
* General Public License for more details.
32
static const char *classes[] = {"ListKey", "SWKey", "SWObject", 0};
33
SWClass ListKey::classdef(classes);
35
/******************************************************************************
36
* ListKey Constructor - initializes instance of ListKey
38
* ENT: ikey - text key
41
ListKey::ListKey(const char *ikey): SWKey(ikey) {
48
ListKey::ListKey(ListKey const &k) : SWKey(k.keytext) {
49
arraymax = k.arraymax;
50
arraypos = k.arraypos;
51
arraycnt = k.arraycnt;
52
array = (arraymax)?(SWKey **)malloc(k.arraymax * sizeof(SWKey *)):0;
53
for (int i = 0; i < arraycnt; i++)
54
array[i] = k.array[i]->clone();
59
void ListKey::init() {
61
// this is a listkey, bound is always set
66
SWKey *ListKey::clone() const
68
return new ListKey(*this);
71
/******************************************************************************
72
* ListKey Destructor - cleans up instance of ListKey
81
/******************************************************************************
82
* ListKey::ClearList - Clears out elements of list
90
for (loop = 0; loop < arraycnt; loop++)
102
/******************************************************************************
103
* ListKey::copyFrom Equates this ListKey to another ListKey object
105
* ENT: ikey - other ListKey object
108
void ListKey::copyFrom(const ListKey &ikey) {
111
arraymax = ikey.arraymax;
112
arraypos = ikey.arraypos;
113
arraycnt = ikey.arraycnt;
114
array = (arraymax)?(SWKey **)malloc(ikey.arraymax * sizeof(SWKey *)):0;
115
for (int i = 0; i < arraycnt; i++)
116
array[i] = ikey.array[i]->clone();
122
/******************************************************************************
123
* ListKey::add - Adds an element to the list
126
void ListKey::add(const SWKey &ikey) {
127
if (++arraycnt > arraymax) {
128
array = (SWKey **) ((array) ? realloc(array, (arraycnt + 32) * sizeof(SWKey *)) : calloc(arraycnt + 32, sizeof(SWKey *)));
129
arraymax = arraycnt + 32;
131
array[arraycnt-1] = ikey.clone();
132
SetToElement(arraycnt-1);
137
/******************************************************************************
138
* ListKey::setPosition(SW_POSITION) - Positions this key
145
void ListKey::setPosition(SW_POSITION p) {
147
case 1: // GCC won't compile P_TOP
150
case 2: // GCC won't compile P_BOTTOM
151
SetToElement(arraycnt-1, p);
157
/******************************************************************************
158
* ListKey::increment - Increments a number of elements
161
void ListKey::increment(int step) {
166
Error(); // clear error
167
for(; step && !Error(); step--) {
168
if (arraypos < arraycnt) {
169
if (array[arraypos]->isBoundSet())
170
(*(array[arraypos]))++;
171
if ((array[arraypos]->Error()) || (!array[arraypos]->isBoundSet())) {
172
SetToElement(arraypos+1);
174
else SWKey::setText((const char *)(*array[arraypos]));
176
else error = KEYERR_OUTOFBOUNDS;
181
/******************************************************************************
182
* ListKey::decrement - Decrements a number of elements
185
void ListKey::decrement(int step) {
190
Error(); // clear error
191
for(; step && !Error(); step--) {
193
if (array[arraypos]->isBoundSet())
194
(*(array[arraypos]))--;
195
if ((array[arraypos]->Error()) || (!array[arraypos]->isBoundSet())) {
196
SetToElement(arraypos-1, BOTTOM);
198
else SWKey::setText((const char *)(*array[arraypos]));
200
else error = KEYERR_OUTOFBOUNDS;
205
/******************************************************************************
206
* ListKey::Count - Returns number of elements in list
209
int ListKey::Count() {
214
/******************************************************************************
215
* ListKey::SetToElement - Sets key to element number
217
* ENT: ielement - element number to set to
222
char ListKey::SetToElement(int ielement, SW_POSITION pos) {
224
if (arraypos >= arraycnt) {
225
arraypos = (arraycnt>0)?arraycnt - 1:0;
226
error = KEYERR_OUTOFBOUNDS;
231
error = KEYERR_OUTOFBOUNDS;
239
if (array[arraypos]->isBoundSet())
240
(*array[arraypos]) = pos;
241
SWKey::setText((const char *)(*array[arraypos]));
243
else SWKey::setText("");
249
/******************************************************************************
250
* ListKey::GetElement - Gets a key element number
252
* ENT: pos - element number to get (or default current)
254
* RET: Key or null on error
257
SWKey *ListKey::getElement(int pos) {
262
error = KEYERR_OUTOFBOUNDS;
264
return (error) ? 0:array[pos];
268
/******************************************************************************
269
* ListKey::Remove - Removes current element from list
272
void ListKey::Remove() {
273
if ((arraypos > -1) && (arraypos < arraycnt)) {
274
delete array[arraypos];
275
if (arraypos < arraycnt - 1)
276
memmove(&array[arraypos], &array[arraypos+1], (arraycnt - arraypos - 1) * sizeof(SWKey *));
279
SetToElement((arraypos)?arraypos-1:0);
284
/******************************************************************************
285
* ListKey::getRangeText - returns parsable range text for this key
288
const char *ListKey::getRangeText() const {
289
char *buf = new char[(arraycnt + 1) * 255];
291
for (int i = 0; i < arraycnt; i++) {
292
strcat(buf, array[i]->getRangeText());
296
stdstr(&rangeText, buf);
302
/******************************************************************************
303
* ListKey::getOSISRefRangeText - returns parsable range text for this key
306
const char *ListKey::getOSISRefRangeText() const {
307
char *buf = new char[(arraycnt + 1) * 255];
309
for (int i = 0; i < arraycnt; i++) {
310
strcat(buf, array[i]->getOSISRefRangeText());
314
stdstr(&rangeText, buf);
320
/******************************************************************************
321
* ListKey::getText - returns text key if (const char *) cast is requested
324
const char *ListKey::getText() const {
326
SWKey *key = (pos >= arraycnt) ? 0:array[pos];
327
return (key) ? key->getText() : keytext;
331
void ListKey::setText(const char *ikey) {
332
// at least try to set the current element to this text
333
for (arraypos = 0; arraypos < arraycnt; arraypos++) {
334
SWKey *key = array[arraypos];
336
if (key->isTraversable() && key->isBoundSet()) {
342
if (!strcmp(key->getText(), ikey))
347
if (arraypos >= arraycnt) {
349
arraypos = arraycnt-1;
352
SWKey::setText(ikey);
355
// This sort impl sucks. Let's change it to a quicksort or some other efficient algol
356
void ListKey::sort() {
357
for (int i = 0; i < arraycnt; i++) {
358
for (int j = i; j < arraycnt; j++) {
359
if (*array[j] < *array[i]) {
360
SWKey *tmp = array[i];