summaryrefslogtreecommitdiffstats
path: root/kstars/kstars/objectnamelist.cpp
blob: 948f036ce45b928c2f131f9aa0507922a8367f38 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/***************************************************************************
                          objectnamelist.cpp  -  description
                             -------------------
    begin                : Mon Feb 18 2002
    copyright          : (C) 2002 by Thomas Kabelmann
    email                : tk78@gmx.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "objectnamelist.h"
#include "skyobjectname.h"
#include "skyobject.h"
#include "starobject.h"

#include <tqstring.h>
#include <kdebug.h>

ObjectNameList::ObjectNameList() {
	amount = 0;
	language = latin;
	mode = allLists;

	// delete just objects of local list
	for (int i= 0; i< 27; i++) {
		list[local][i].setAutoDelete(true);
		unsorted[i] = false;
	}

	constellations.setAutoDelete(true);
}

ObjectNameList::~ObjectNameList(){
}

void ObjectNameList::setLanguage( Language lang ) {
	language = lang;
}

void ObjectNameList::setLanguage( bool lang ) {
	language = ( Language ) lang;
}

void ObjectNameList::setMode( Mode m ) {
	mode = m;
}

void ObjectNameList::append( SkyObject *object, bool useLongName ) {
	amount++;
	// create name string and init with longname if forced by parameter else default name
	TQString name = ( useLongName ) ? object->longname() : object->name();

	//if star's name is it's genetive name, make sure we don't use the Greek charcter here
	if ( object->type() == 0 && name == ((StarObject*)object)->gname() )
		name = ((StarObject*)object)->gname( false );
	
	// create string with translated name
	TQString iName;

	if ( object->type() == -1 ) {  // constellation
		iName = i18n( "Constellation name (optional)", name.local8Bit().data() );
	}
	else {  // all other types
		iName = i18n( name.local8Bit() );
	}

	// create SkyObjectName with translated name
	SkyObjectName *soName = new SkyObjectName( iName, object );
	// append in localized list
	currentIndex = getIndex( name );
	list[local] [currentIndex].append(soName);

	// type == -1 -> constellation
	if (object->type() == -1) {
		// get latin name (default name)
		iName = name;
		// create new SkyObject with localized name
		soName = new SkyObjectName(iName, object);
		// to delete these objects store them in separate list
		constellations.append(soName);
	}

	// append in latin list
	currentIndex = getIndex(name);
	list[latin][currentIndex].append(soName);
	// set list unsorted
	unsorted[currentIndex] = true;
}

SkyObjectName* ObjectNameList::first( const TQString &name ) {
	sort();
	SkyObjectName *soName = 0;
	// set mode: string is empty set mode to all lists
	name.isEmpty() ? setMode( allLists ) : setMode( oneList );

	// start with first list in array
	if ( mode == allLists ) {
		currentIndex = 0;
	} else {
		// start with list which tqcontains the first letter
		currentIndex = getIndex( name );
	}

	soName = list[language][currentIndex].first();

	//It's possible that there is no object that belongs to currentIndex
	//If not, and mode==allLists, try the next index
	while ( !soName && mode==allLists && currentIndex < 26 ) {
		currentIndex++;  // loop through the array
		soName = list[language][currentIndex].first();
  }

	return soName;
}

SkyObjectName* ObjectNameList::next() {
	SkyObjectName *soName = 0;
	// get next SkyObjectName object
	soName = list[ language ] [ currentIndex ].next();

	// if all lists must checked and SkyObjectName is NULL
	// check next available list in array and set to first element in list
	// if currentIndex == 26 -> last index is reached
	if ( mode==allLists && soName==0 && currentIndex<26 ) {
		do {
			currentIndex++;  // loop through the array
			soName = list[ language ] [ currentIndex ].first();
		} while ( currentIndex<26 && soName==0 );  // break if currentIndex == 27 or soName is found
	}

	return soName;
}

int ObjectNameList::getIndex( const TQString &name ) {
	//	default index is 0 if object name starts with a number
	int index = 0;

	// if object name starts with a letter, so get index number between 1 and 26
	if ( !name.isEmpty() ) {
		TQChar firstLetter = name[0];
		if ( firstLetter ) {
			if ( firstLetter.isLetter() ) {
				const unsigned char letter = (unsigned char) firstLetter.lower();
				index = letter % 96;  // a == 97 in ASCII code => 97 % 96 = 1
			}

			/**
				*Avoid invalid index due to non ASCII letters like "� etc. Add your own letters to put them in
				*the right list (due to %96 index can't never get smaller than 0).
				*/
			if (index > 26) {
				switch (index) {
					case 41 : index = 5; break;	// �= e
					case 54 : index = 15; break;	// �= o
					default : index = 0;						// all other letters
				}
				kdDebug() << k_funcinfo << "Object: " << name << " starts with non ASCII letter. Put it in list #" << index << endl;
			}
		}
	}

	return index;
}

void ObjectNameList::sort() {
	for (int i=0; i<27; ++i) {
		if (unsorted[i] == true) {
			unsorted[i] = false;
			list[latin][i].sort();
			list[local][i].sort();
		}
	}
}

void ObjectNameList::remove ( const TQString &name ) {
	setMode(oneList);
	int index = getIndex(name);
	SortedList <SkyObjectName> *l = &(list[language][index]);

	SkyObjectName *son = find( name );
	if ( son ) l->remove( son );
}

SkyObjectName* ObjectNameList::find(const TQString &name) {
	sort();
	if (name.isNull()) return 0;
	// find works only in one list and not in all lists
	setMode(oneList);

	// items are stored translated (JH: Why?  this whole class is confusing...)
	TQString translatedName = i18n(name.utf8());

	int index = getIndex(name);

	// first item
	int lower = 0;
	SortedList <SkyObjectName> *l = &(list[language][index]);
	// last item
	int upper = l->count() - 1;
	// break if list is empty
	if (upper == -1) return 0;

	int next;

	// it's the "binary search" algorithm
	SkyObjectName *o;
	while (upper >= lower) {
		next = (lower + upper) / 2;
		o = l->at(next);
		if (translatedName == o->text()) { return o; }
		if (translatedName < o->text())
			upper = next - 1;
		else
			lower = next + 1;
	}
	return 0;
}