fixed some bugs in new 'g'o system
[k8-i-v-a-n.git] / src / felib / felist.cpp
blob522c0c096ad86ea28c54242bd34978f4d0e93dde
1 /*
3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
6 * Public License
8 * See LICENSING which should be included
9 * along with this file for more details
12 #include <fstream>
14 #include "felist.h"
15 #include "graphics.h"
16 #include "bitmap.h"
17 #include "whandler.h"
18 #include "rawbit.h"
19 #include "fesave.h"
20 #include "festring.h"
23 const felist *FelistCurrentlyDrawn = 0;
24 truth fastListMode = 0;
27 truth felist::GetFastListMode () { return fastListMode; }
28 void felist::SetFastListMode (truth modeon) { fastListMode = modeon; }
31 truth FelistDrawController () {
32 FelistCurrentlyDrawn->DrawPage(DOUBLE_BUFFER);
33 return true;
37 struct felistentry {
38 felistentry () : ImageKey(NO_IMAGE) {}
39 felistentry (cfestring &String, col16 Color, uInt Marginal, uInt ImageKey, truth Selectable) :
40 String(String),
41 Color(Color),
42 Marginal(Marginal),
43 ImageKey(ImageKey),
44 Selectable(Selectable) {}
46 festring String;
47 col16 Color;
48 uInt Marginal;
49 uInt ImageKey;
50 truth Selectable;
54 outputfile &operator << (outputfile &SaveFile, const felistentry *Entry) {
55 SaveFile << Entry->String << Entry->Color << Entry->Marginal << Entry->Selectable;
56 return SaveFile;
60 inputfile &operator >> (inputfile &SaveFile, felistentry *&Entry) {
61 Entry = new felistentry;
62 SaveFile >> Entry->String >> Entry->Color >> Entry->Marginal >> Entry->Selectable;
63 return SaveFile;
67 struct felistdescription {
68 felistdescription () {}
69 felistdescription (cfestring &String, col16 Color)
70 : String(String), Color(Color) {}
71 festring String;
72 col16 Color;
76 felist::felist (cfestring &Topic, col16 TopicColor, uInt Maximum) :
77 mSaveSelector(false),
78 mSaveDir(""),
79 Maximum(Maximum),
80 Selected(0),
81 Pos(10, 10),
82 Width(780),
83 PageLength(26),
84 BackColor(0),
85 Flags(SELECTABLE|FADE),
86 UpKey(KEY_UP),
87 DownKey(KEY_DOWN),
88 EntryDrawer(0)
90 AddDescription(Topic, TopicColor);
94 felist::~felist () {
95 Empty();
96 for (uInt c = 0; c < Description.size(); ++c) delete Description[c];
100 void felist::Pop () {
101 delete Entry[GetLastEntryIndex()];
102 Entry.pop_back();
106 uInt felist::Draw () {
107 while (Entry.size() && Entry[GetLastEntryIndex()]->String.IsEmpty()) Pop();
108 if (Entry.empty()) return LIST_WAS_EMPTY;
109 FelistCurrentlyDrawn = this;
110 if (globalwindowhandler::ControlLoopsInstalled()) globalwindowhandler::InstallControlLoop(FelistDrawController);
111 bitmap BackGround(RES);
112 BackGround.ActivateFastFlag();
113 bitmap *Buffer;
114 if (Flags & FADE) {
115 Buffer = new bitmap(RES, 0);
116 Buffer->ActivateFastFlag();
117 BackGround.ClearToColor(0);
118 } else {
119 Buffer = DOUBLE_BUFFER;
120 Buffer->FastBlit(&BackGround);
122 uInt c;
123 uInt Return, Selectables = 0;
124 truth JustSelectMove = false;
125 for (c = 0; c < Entry.size(); ++c) if (Entry[c]->Selectable) ++Selectables;
126 if (Selected >= Selectables) Selected = Selectables-1;
127 if (Flags & SELECTABLE) PageBegin = Selected-Selected%PageLength;
128 else if (Flags & INVERSE_MODE) PageBegin = GetLastEntryIndex()-GetLastEntryIndex()%PageLength;
129 else PageBegin = 0;
130 for (;;) {
131 truth AtTheEnd = DrawPage(Buffer);
132 if (Flags & FADE) {
133 if (JustSelectMove) {
134 Buffer->FastBlit(DOUBLE_BUFFER);
135 graphics::BlitDBToScreen();
136 } else {
137 Buffer->FadeToScreen();
139 JustSelectMove = false;
140 } else {
141 graphics::BlitDBToScreen();
143 uInt Pressed = GET_KEY(false);
144 if (Flags & SELECTABLE) {
145 // list movement and selections
146 if (Pressed >= 'a' && Pressed <= 'z') Pressed -= 32;
147 if (Pressed >= 'A' && Pressed <= 'Z') {
148 Pressed -= 65;
149 if (Pressed < PageLength && Pressed+PageBegin < Selectables) {
150 Return = Selected = Pressed+PageBegin;
151 if (fastListMode) {
152 JustSelectMove = true;
153 continue;
154 } else {
155 break;
158 continue;
160 if (Pressed == UpKey) {
161 if (Selected) {
162 --Selected;
163 if (Selected < PageBegin) {
164 BackGround.FastBlit(Buffer);
165 PageBegin -= PageLength;
166 } else {
167 JustSelectMove = true;
169 } else {
170 for (c = 0, Selected = 0; c < Entry.size(); ++c) if (Entry[c]->Selectable) ++Selected;
171 --Selected;
172 if (PageBegin == Selected-Selected%PageLength) JustSelectMove = true;
173 else {
174 BackGround.FastBlit(Buffer);
175 PageBegin = Selected-Selected%PageLength;
178 continue;
180 if (Pressed == DownKey) {
181 if (!AtTheEnd || Selected != Selectables-1) {
182 ++Selected;
183 if (Selected > PageBegin+PageLength-1) {
184 BackGround.FastBlit(Buffer);
185 PageBegin += PageLength;
186 } else {
187 JustSelectMove = true;
189 } else {
190 if (!PageBegin) JustSelectMove = true; else BackGround.FastBlit(Buffer);
191 Selected = PageBegin = 0;
193 continue;
195 if (Pressed == KEY_HOME) {
196 Selected = PageBegin;
197 JustSelectMove = true;
198 continue;
200 if (Pressed == KEY_END) {
201 //fprintf(stderr, "sel: %u; pb: %u; pl: %u; ss: %u; ae: %s\n", Selected, PageBegin, PageLength, Selectables, AtTheEnd ? "end" : "not end");
202 if (Selectables) {
203 Selected = PageBegin+PageLength-1;
204 if (Selected >= Selectables) Selected = Selectables-1;
206 JustSelectMove = true;
207 continue;
209 if (Pressed == KEY_ENTER) {
210 Return = Selected;
211 break;
214 if (Pressed == KEY_ESC) {
215 Return = ESCAPED;
216 break;
218 if ((AtTheEnd && !(Flags & INVERSE_MODE)) || (!PageBegin && (Flags & INVERSE_MODE))) {
219 if (Flags & FELIST_NO_BADKEY_EXIT) continue;
220 Return = NOTHING_SELECTED;
221 break;
222 } else {
223 BackGround.FastBlit(Buffer);
224 if (Flags & INVERSE_MODE) PageBegin -= PageLength; else PageBegin += PageLength;
225 if (Flags & SELECTABLE) Selected = PageBegin;
228 if (!(Flags & FADE)) {
229 if (Flags & DRAW_BACKGROUND_AFTERWARDS) BackGround.FastBlit(DOUBLE_BUFFER);
230 if (Flags & BLIT_AFTERWARDS) graphics::BlitDBToScreen();
231 } else {
232 delete Buffer;
234 globalwindowhandler::DeInstallControlLoop(FelistDrawController);
235 return Return;
239 //static festring Str;
241 truth felist::DrawPage (bitmap *Buffer) const {
242 uInt LastFillBottom = Pos.Y+23+Description.size()*10;
243 festring Str;
245 DrawDescription(Buffer);
246 uInt c, i; // c == entry index, i == selectable index
247 int selIdx = -1;
248 for (c = 0, i = 0; i != PageBegin; ++c) if (Entry[c]->Selectable) ++i;
249 while (!Entry[c]->Selectable && Entry[c]->String.IsEmpty()) ++c;
250 std::vector<festring> Chapter;
251 //col16 selBack = BackColor^0xFFFF, selText = BackColor;
252 //col16 selBack = LIGHT_GRAY, selText = BLACK;
253 col16 selBack = BLUE, selText = WHITE;
254 for (;;) {
255 Str.Empty();
256 uInt Marginal = Entry[c]->Marginal;
257 if (Flags & SELECTABLE && Entry[c]->Selectable) {
258 Str << char('A'+(i-PageBegin)) << ": ";
259 Marginal += 3;
261 Str << Entry[c]->String;
262 bool selected = (Flags & SELECTABLE && Entry[c]->Selectable && Selected == i);
263 if (selected) selIdx = (int)c;
264 if (Entry[c]->ImageKey != NO_IMAGE) {
265 if (Str.GetSize() <= (Width-50)>>3) {
266 Buffer->Fill(Pos.X+3, LastFillBottom, Width-6, 20, !selected ? BackColor : selBack);
267 if (EntryDrawer) EntryDrawer(Buffer, v2(Pos.X+13, LastFillBottom), Entry[c]->ImageKey);
268 if (selected) {
269 //FONT->PrintfUnshaded(Buffer, v2(Pos.X+38, LastFillBottom+5), WHITE, "%s", Str.CStr());
270 FONT->PrintfUnshaded(Buffer, v2(Pos.X+37, LastFillBottom+4), selText, "%s", Str.CStr());
271 } else {
272 FONT->Printf(Buffer, v2(Pos.X+37, LastFillBottom+4), Entry[c]->Color, "%s", Str.CStr());
274 LastFillBottom += 20;
275 } else {
276 uInt ChapterSize = festring::SplitString(Str, Chapter, (Width-50)>>3, Marginal);
277 uInt PictureTop = LastFillBottom+ChapterSize*5-9;
278 for (uInt l = 0; l < ChapterSize; ++l) {
279 Buffer->Fill(Pos.X+3, LastFillBottom, Width-6, 10, !selected ? BackColor : selBack);
280 if (selected) {
281 //FONT->PrintfUnshaded(Buffer, v2(Pos.X+38, LastFillBottom+1), WHITE, "%s", Chapter[l].CStr());
282 FONT->PrintfUnshaded(Buffer, v2(Pos.X+37, LastFillBottom), selText, "%s", Chapter[l].CStr());
283 } else {
284 FONT->Printf(Buffer, v2(Pos.X+37, LastFillBottom), Entry[c]->Color, "%s", Chapter[l].CStr());
286 LastFillBottom += 10;
288 if (EntryDrawer) EntryDrawer(Buffer, v2(Pos.X+13, PictureTop), Entry[c]->ImageKey);
290 } else {
291 uInt ChapterSize = festring::SplitString(Str, Chapter, (Width-26)>>3, Marginal);
292 for (uInt l = 0; l < ChapterSize; ++l) {
293 Buffer->Fill(Pos.X+3, LastFillBottom, Width-6, 10, !selected ? BackColor : selBack);
294 if (selected) {
295 //FONT->PrintfUnshaded(Buffer, v2(Pos.X+14, LastFillBottom+1), WHITE, "%s", Chapter[l].CStr());
296 FONT->PrintfUnshaded(Buffer, v2(Pos.X+13, LastFillBottom), selText, "%s", Chapter[l].CStr());
297 } else {
298 FONT->Printf(Buffer, v2(Pos.X+13, LastFillBottom), Entry[c]->Color, "%s", Chapter[l].CStr());
300 LastFillBottom += 10;
303 if ((i-PageBegin == PageLength-1 && Entry[c]->Selectable) || c == Entry.size()-1) {
304 if ((!(Flags & INVERSE_MODE) && c != Entry.size()-1) || (Flags & INVERSE_MODE && PageBegin)) {
305 Buffer->Fill(Pos.X+3, LastFillBottom, Width-6, 30, BackColor);
306 FONT->Printf(Buffer, v2(Pos.X+13, LastFillBottom+10), WHITE, "- Press SPACE to continue, ESC to exit -");
307 LastFillBottom += 30;
308 } else {
309 Buffer->Fill(Pos.X+3, LastFillBottom, Width-6, 10, BackColor);
310 LastFillBottom += 10;
312 Buffer->DrawRectangle(Pos.X+1, Pos.Y+1, Pos.X+Width-2, LastFillBottom+1, DARK_GRAY, true);
313 break;
315 if (Entry[c++]->Selectable) ++i;
317 if (selIdx != -1 && mSaveSelector) {
318 bitmap bmp(ZERO_V2);
319 festring imgName = Entry[selIdx]->String;
320 festring::sizetype pos = imgName.FindLast(".sav");
321 if (pos != festring::NPos) {
322 imgName.Erase(pos, 4); // remove '.sav'
323 #if defined(SGAME_SHOTS_IPU) || !defined(HAVE_IMLIB2)
324 imgName = mSaveDir+imgName+".ipu";
325 #else
326 imgName = mSaveDir+imgName+".png";
327 #endif
328 //fprintf(stderr, "sel=%d; img=%s\n", selIdx, imgName.CStr());
329 #if defined(SGAME_SHOTS_IPU) || !defined(HAVE_IMLIB2)
330 if (bmp.LoadIPU(imgName))
331 #else
332 if (bmp.LoadPNG(imgName))
333 #endif
335 //fprintf(stderr, " LOADED! %dx%d\n", bmp.GetSize().X, bmp.GetSize().Y);
336 int x = Buffer->GetSize().X-bmp.GetSize().X-2;
337 int y = Buffer->GetSize().Y-bmp.GetSize().Y-2;
338 int w = bmp.GetSize().X;
339 int h = bmp.GetSize().Y;
340 blitdata bd = {
341 Buffer,
342 {0, 0}, //src
343 {x, y}, //dest
344 {w, h}, //border
345 {0}, // luminance/flags
346 0xDEAD, // mask color
347 0 // custom data
349 bmp.NormalBlit(bd);
350 Buffer->DrawRectangle(x-2, y-2, x+w, y+h, DARK_GRAY, true);
354 return c == Entry.size()-1;
358 void felist::DrawDescription (bitmap *Buffer) const {
359 Buffer->Fill(Pos.X+3, Pos.Y+3, Width-6, 20, BackColor);
360 for (uInt c = 0; c < Description.size(); ++c) {
361 Buffer->Fill(Pos.X+3, Pos.Y+13+c*10, Width-6, 10, BackColor);
362 FONT->Printf(Buffer, v2(Pos.X+13, Pos.Y+13+c*10), Description[c]->Color, "%s", Description[c]->String.CStr());
364 Buffer->Fill(Pos.X+3, Pos.Y+13+Description.size()*10, Width-6, 10, BackColor);
368 /* We suppose InverseMode != false here */
369 void felist::QuickDraw (bitmap *Bitmap, uInt PageLength) const {
370 static std::vector<festring> Chapter;
371 uInt Width = Bitmap->GetSize().X;
372 Bitmap->Fill(3, 3, Width-6, 20+PageLength*10, 0);
373 Bitmap->DrawRectangle(1, 1, Width-2, 24+PageLength*10, DARK_GRAY, true);
374 uInt LineSize = (Width-26)>>3;
375 uInt Index = 0;
376 uInt Bottom = PageLength*10+3;
377 for (uInt c1 = 0; c1 <= Selected; ++c1) {
378 const felistentry* CurrentEntry = Entry[Selected-c1];
379 uInt ChapterSize = festring::SplitString(CurrentEntry->String, Chapter, LineSize, CurrentEntry->Marginal);
380 for (uInt c2 = 0; c2 < ChapterSize; ++c2) {
381 col16 Color = CurrentEntry->Color;
382 Color = MakeRGB16(
383 GetRed16(Color)-((GetRed16(Color)*3*Index/PageLength)>>2),
384 GetGreen16(Color)-((GetGreen16(Color)*3*Index/PageLength)>>2),
385 GetBlue16(Color)-((GetBlue16(Color)*3*Index/PageLength)>>2));
386 FONT->Printf(Bitmap, v2(13, Bottom), Color, "%s", Chapter[ChapterSize-c2-1].CStr());
387 Bottom -= 10;
388 if (++Index == PageLength) return;
394 void felist::CreateQuickDrawFontCaches (rawbitmap *Font, col16 Color, uInt PageLength) {
395 if (PageLength < 2) return;
396 for (uInt c = 0; c < PageLength; ++c)
397 Font->CreateFontCache(
398 MakeRGB16(
399 GetRed16(Color)-((GetRed16(Color)*3*c/PageLength)>>2),
400 GetGreen16(Color)-((GetGreen16(Color)*3*c/PageLength)>>2),
401 GetBlue16(Color)-((GetBlue16(Color)*3*c/PageLength)>>2)));
405 void felist::Empty () {
406 for (uInt c = 0; c < Entry.size(); ++c) delete Entry[c];
407 Entry.clear();
411 void felist::AddEntry (cfestring &Str, col16 Color, uInt Marginal, uInt Key, truth Selectable) {
412 Entry.push_back(new felistentry(Str, Color, Marginal, Key, Selectable));
413 if (Maximum && Entry.size() > feuLong(Maximum)) {
414 delete Entry[0];
415 Entry.erase(Entry.begin());
420 void felist::Save (outputfile &SaveFile) const {
421 SaveFile << Entry << Maximum << Selected;
425 void felist::Load (inputfile& SaveFile) {
426 SaveFile >> Entry >> Maximum >> Selected;
430 void felist::PrintToFile (cfestring& FileName) {
431 std::ofstream SaveFile(FileName.CStr(), std::ios::out);
432 if (!SaveFile.is_open()) return;
433 uInt c;
434 for (c = 0; c < Description.size(); ++c) SaveFile << Description[c]->String.CStr() << std::endl;
435 SaveFile << std::endl;
436 for (c = 0; c < Entry.size(); ++c) {
437 if (Entry[c]->ImageKey != NO_IMAGE) SaveFile << " ";
438 SaveFile << Entry[c]->String.CStr() << std::endl;
443 void felist::AddDescription (cfestring &Str, col16 Color) {
444 Description.push_back(new felistdescription(Str, Color));
448 festring felist::GetEntry (uInt I) const {
449 return Entry[I]->String;
453 col16 felist::GetColor (uInt I) const {
454 return Entry[I]->Color;
458 void felist::SetColor (uInt I, col16 What) {
459 Entry[I]->Color = What;