3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
8 * See LICENSING which should be included
9 * along with this file for more details
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
);
38 felistentry () : ImageKey(NO_IMAGE
) {}
39 felistentry (cfestring
&String
, col16 Color
, uInt Marginal
, uInt ImageKey
, truth Selectable
) :
44 Selectable(Selectable
) {}
54 outputfile
&operator << (outputfile
&SaveFile
, const felistentry
*Entry
) {
55 SaveFile
<< Entry
->String
<< Entry
->Color
<< Entry
->Marginal
<< Entry
->Selectable
;
60 inputfile
&operator >> (inputfile
&SaveFile
, felistentry
*&Entry
) {
61 Entry
= new felistentry
;
62 SaveFile
>> Entry
->String
>> Entry
->Color
>> Entry
->Marginal
>> Entry
->Selectable
;
67 struct felistdescription
{
68 felistdescription () {}
69 felistdescription (cfestring
&String
, col16 Color
)
70 : String(String
), Color(Color
) {}
76 felist::felist (cfestring
&Topic
, col16 TopicColor
, uInt Maximum
) :
85 Flags(SELECTABLE
|FADE
),
90 AddDescription(Topic
, TopicColor
);
96 for (uInt c
= 0; c
< Description
.size(); ++c
) delete Description
[c
];
100 void felist::Pop () {
101 delete Entry
[GetLastEntryIndex()];
106 uInt
felist::Draw () {
107 while (Entry
.size() && Entry
[GetLastEntryIndex()]->String
.IsEmpty()) Pop();
108 if (Entry
.empty()) return LIST_WAS_EMPTY
;
110 FelistCurrentlyDrawn
= this;
111 if (globalwindowhandler::ControlLoopsInstalled()) globalwindowhandler::InstallControlLoop(FelistDrawController
);
113 bitmap
BackGround(RES
);
116 BackGround
.ActivateFastFlag();
118 Buffer
= new bitmap(RES
, 0);
119 Buffer
->ActivateFastFlag();
120 BackGround
.ClearToColor(0);
122 Buffer
= DOUBLE_BUFFER
;
123 Buffer
->FastBlit(&BackGround
);
127 uInt Return
, Selectables
= 0;
128 truth JustSelectMove
= false;
129 for (c
= 0; c
< Entry
.size(); ++c
) if (Entry
[c
]->Selectable
) ++Selectables
;
130 if (Selected
>= Selectables
) Selected
= Selectables
-1;
132 if (Flags
&SELECTABLE
) PageBegin
= Selected
-Selected
%PageLength
;
133 else if (Flags
&INVERSE_MODE
) PageBegin
= GetLastEntryIndex()-GetLastEntryIndex()%PageLength
;
137 truth AtTheEnd
= DrawPage(Buffer
);
139 if (JustSelectMove
) {
140 Buffer
->FastBlit(DOUBLE_BUFFER
);
141 graphics::BlitDBToScreen();
143 Buffer
->FadeToScreen();
145 JustSelectMove
= false;
147 graphics::BlitDBToScreen();
150 uInt Pressed
= GET_KEY(false);
152 if (Flags
&SELECTABLE
) {
153 // list movement and selections
156 if (Pressed
>= 'a' && Pressed
<= 'z') prs
= Pressed
-'a';
157 else if (Pressed
>= 'A' && Pressed
<= 'Z') prs
= Pressed
-'A';
158 else if (Pressed
>= '0' && Pressed
<= '9') prs
= Pressed
-'0'+26;
161 if ((uInt
)prs
< PageLength
&& (uInt
)prs
+PageBegin
< Selectables
) {
162 Return
= Selected
= (uInt
)prs
+PageBegin
;
164 JustSelectMove
= true;
173 if (Pressed
== UpKey
) {
176 if (Selected
< PageBegin
) {
177 BackGround
.FastBlit(Buffer
);
178 PageBegin
-= PageLength
;
180 JustSelectMove
= true;
183 for (c
= 0, Selected
= 0; c
< Entry
.size(); ++c
) if (Entry
[c
]->Selectable
) ++Selected
;
185 if (PageBegin
== Selected
-Selected
%PageLength
) JustSelectMove
= true;
187 BackGround
.FastBlit(Buffer
);
188 PageBegin
= Selected
-Selected
%PageLength
;
194 if (Pressed
== DownKey
) {
195 if (!AtTheEnd
|| Selected
!= Selectables
-1) {
197 if (Selected
> PageBegin
+PageLength
-1) {
198 PageBegin
+= PageLength
;
199 BackGround
.FastBlit(Buffer
);
201 JustSelectMove
= true;
204 if (!PageBegin
) JustSelectMove
= true; else BackGround
.FastBlit(Buffer
);
205 Selected
= PageBegin
= 0;
210 if (Pressed
== KEY_HOME
) {
211 Selected
= PageBegin
;
212 JustSelectMove
= true;
216 if (Pressed
== KEY_END
) {
217 //fprintf(stderr, "sel: %u; pb: %u; pl: %u; ss: %u; ae: %s\n", Selected, PageBegin, PageLength, Selectables, AtTheEnd ? "end" : "not end");
219 Selected
= PageBegin
+PageLength
-1;
220 if (Selected
>= Selectables
) Selected
= Selectables
-1;
222 JustSelectMove
= true;
226 if (Pressed
== KEY_LEFT
) {
228 if (Selectables
&& PageBegin
> 0) {
229 PageBegin
= (PageBegin
< PageLength
? 0 : PageBegin
-PageLength
);
230 Selected
= PageBegin
;
231 BackGround
.FastBlit(Buffer
);
236 if (Pressed
== KEY_RIGHT
) {
239 uInt pgend
= PageBegin
+PageLength
;
240 if (pgend
< Selectables
) {
241 PageBegin
+= PageLength
;
242 Selected
= PageBegin
;
243 BackGround
.FastBlit(Buffer
);
249 if (Pressed
== KEY_ENTER
) {
254 // not selectable: allow navigation with left/right
255 if (Pressed
== KEY_LEFT
) {
257 PageBegin
-= (PageBegin
< PageLength
? PageBegin
: PageLength
);
258 BackGround
.FastBlit(Buffer
);
263 if (Pressed
== KEY_RIGHT
) {
265 PageBegin
+= PageLength
;
266 BackGround
.FastBlit(Buffer
);
272 if (Pressed
== KEY_ESC
) {
277 if ((AtTheEnd
&& !(Flags
&INVERSE_MODE
)) || (!PageBegin
&& (Flags
&INVERSE_MODE
))) {
278 if (Flags
&FELIST_NO_BADKEY_EXIT
) continue;
279 Return
= NOTHING_SELECTED
;
282 BackGround
.FastBlit(Buffer
);
283 if (Flags
&INVERSE_MODE
) PageBegin
-= PageLength
; else PageBegin
+= PageLength
;
284 if (Flags
&SELECTABLE
) Selected
= PageBegin
;
289 if (Flags
&DRAW_BACKGROUND_AFTERWARDS
) BackGround
.FastBlit(DOUBLE_BUFFER
);
290 if (Flags
&BLIT_AFTERWARDS
) graphics::BlitDBToScreen();
295 globalwindowhandler::DeInstallControlLoop(FelistDrawController
);
300 //static festring Str;
302 truth
felist::DrawPage (bitmap
*Buffer
) const {
303 uInt LastFillBottom
= Pos
.Y
+23+Description
.size()*10;
306 DrawDescription(Buffer
);
307 uInt c
, i
; // c == entry index, i == selectable index
309 for (c
= 0, i
= 0; i
!= PageBegin
; ++c
) if (Entry
[c
]->Selectable
) ++i
;
310 while (!Entry
[c
]->Selectable
&& Entry
[c
]->String
.IsEmpty()) ++c
;
311 std::vector
<festring
> Chapter
;
313 //col16 selBack = BackColor^0xFFFF, selText = BackColor;
314 //col16 selBack = LIGHT_GRAY, selText = BLACK;
315 col16 selBack
= SEL_BLUE
, selText
= WHITE
;
319 uInt Marginal
= Entry
[c
]->Marginal
;
320 if ((Flags
&SELECTABLE
) && Entry
[c
]->Selectable
) {
321 if (i
-PageBegin
<= 25) Str
<< char('A'+(i
-PageBegin
)); else Str
<< char('0'+(i
-PageBegin
-26));
325 Str
<< Entry
[c
]->String
;
326 bool selected
= (Flags
&SELECTABLE
&& Entry
[c
]->Selectable
&& Selected
== i
);
327 if (selected
) selIdx
= (int)c
;
328 col16 ecolor
= Entry
[c
]->Color
;
330 if (ecolor
!= RED
&& ecolor
!= GREEN
&& ecolor
!= PINK
) ecolor
= selText
;
332 if (Entry
[c
]->ImageKey
!= NO_IMAGE
) {
333 if (Str
.rawLength() <= (Width
-50)>>3) {
334 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 20, (!selected
? BackColor
: selBack
));
335 if (EntryDrawer
) EntryDrawer(Buffer
, v2(Pos
.X
+13, LastFillBottom
), Entry
[c
]->ImageKey
);
337 FONT
->PrintfUnshadedColored(Buffer
, v2(Pos
.X
+37, LastFillBottom
+4), ecolor
, "%s", Str
.CStr());
339 FONT
->PrintfColored(Buffer
, v2(Pos
.X
+37, LastFillBottom
+4), ecolor
, "%s", Str
.CStr());
341 LastFillBottom
+= 20;
343 uInt ChapterSize
= festring::SplitStringColored(Str
, Chapter
, (Width
-50)>>3, Marginal
);
344 uInt PictureTop
= LastFillBottom
+ChapterSize
*5-9;
345 for (uInt l
= 0; l
< ChapterSize
; ++l
) {
346 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 10, !selected
? BackColor
: selBack
);
348 FONT
->PrintfUnshadedColored(Buffer
, v2(Pos
.X
+37, LastFillBottom
), ecolor
, "%s", Chapter
[l
].CStr());
350 FONT
->PrintfColored(Buffer
, v2(Pos
.X
+37, LastFillBottom
), ecolor
, "%s", Chapter
[l
].CStr());
352 LastFillBottom
+= 10;
354 if (EntryDrawer
) EntryDrawer(Buffer
, v2(Pos
.X
+13, PictureTop
), Entry
[c
]->ImageKey
);
357 uInt ChapterSize
= festring::SplitStringColored(Str
, Chapter
, (Width
-26)>>3, Marginal
);
358 for (uInt l
= 0; l
< ChapterSize
; ++l
) {
359 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 10, !selected
? BackColor
: selBack
);
361 FONT
->PrintfUnshadedColored(Buffer
, v2(Pos
.X
+13, LastFillBottom
), ecolor
, "%s", Chapter
[l
].CStr());
363 FONT
->PrintfColored(Buffer
, v2(Pos
.X
+13, LastFillBottom
), ecolor
, "%s", Chapter
[l
].CStr());
365 LastFillBottom
+= 10;
368 if ((i
-PageBegin
== PageLength
-1 && Entry
[c
]->Selectable
) || c
== Entry
.size()-1) {
369 if ((!(Flags
&INVERSE_MODE
) && c
!= Entry
.size()-1) || (Flags
&INVERSE_MODE
&& PageBegin
)) {
370 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 30, BackColor
);
371 FONT
->PrintfColored(Buffer
, v2(Pos
.X
+13, LastFillBottom
+10), WHITE
, "- Press SPACE to continue, ESC to exit -");
372 LastFillBottom
+= 30;
374 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 10, BackColor
);
375 LastFillBottom
+= 10;
377 Buffer
->DrawRectangle(Pos
.X
+1, Pos
.Y
+1, Pos
.X
+Width
-2, LastFillBottom
+1, DARK_GRAY
, true);
380 if (Entry
[c
++]->Selectable
) ++i
;
382 if (selIdx
!= -1 && mSaveSelector
) {
384 festring imgName
= Entry
[selIdx
]->String
;
385 festring::sizetype pos
= imgName
.FindLast(".sav");
386 if (pos
!= festring::NPos
) {
387 imgName
.Erase(pos
, 4); // remove '.sav'
388 #if defined(SGAME_SHOTS_IPU) || !defined(HAVE_IMLIB2)
389 imgName
= mSaveDir
+imgName
+".ipu";
391 imgName
= mSaveDir
+imgName
+".png";
393 //fprintf(stderr, "sel=%d; img=%s\n", selIdx, imgName.CStr());
394 #if defined(SGAME_SHOTS_IPU) || !defined(HAVE_IMLIB2)
395 if (bmp
.LoadIPU(imgName
))
397 if (bmp
.LoadPNG(imgName
))
400 //fprintf(stderr, " LOADED! %dx%d\n", bmp.GetSize().X, bmp.GetSize().Y);
401 int x
= Buffer
->GetSize().X
-bmp
.GetSize().X
-2;
402 int y
= Buffer
->GetSize().Y
-bmp
.GetSize().Y
-2;
403 int w
= bmp
.GetSize().X
;
404 int h
= bmp
.GetSize().Y
;
410 {0}, // luminance/flags
411 0xDEAD, // mask color
415 Buffer
->DrawRectangle(x
-2, y
-2, x
+w
, y
+h
, DARK_GRAY
, true);
419 return c
== Entry
.size()-1;
423 void felist::DrawDescription (bitmap
*Buffer
) const {
424 Buffer
->Fill(Pos
.X
+3, Pos
.Y
+3, Width
-6, 20, BackColor
);
425 for (uInt c
= 0; c
< Description
.size(); ++c
) {
426 Buffer
->Fill(Pos
.X
+3, Pos
.Y
+13+c
*10, Width
-6, 10, BackColor
);
427 FONT
->PrintfColored(Buffer
, v2(Pos
.X
+13, Pos
.Y
+13+c
*10), Description
[c
]->Color
, "%s", Description
[c
]->String
.CStr());
429 Buffer
->Fill(Pos
.X
+3, Pos
.Y
+13+Description
.size()*10, Width
-6, 10, BackColor
);
433 /* We suppose InverseMode != false here */
434 void felist::QuickDraw (bitmap
*Bitmap
, uInt PageLength
) const {
435 static std::vector
<festring
> Chapter
;
436 uInt Width
= Bitmap
->GetSize().X
;
437 Bitmap
->Fill(3, 3, Width
-6, 20+PageLength
*10, 0);
438 Bitmap
->DrawRectangle(1, 1, Width
-2, 24+PageLength
*10, DARK_GRAY
, true);
439 uInt LineSize
= (Width
-26)>>3;
441 uInt Bottom
= PageLength
*10+3;
442 for (uInt c1
= 0; c1
<= Selected
; ++c1
) {
443 const felistentry
* CurrentEntry
= Entry
[Selected
-c1
];
444 uInt ChapterSize
= festring::SplitStringColored(CurrentEntry
->String
, Chapter
, LineSize
, CurrentEntry
->Marginal
);
445 for (uInt c2
= 0; c2
< ChapterSize
; ++c2
) {
446 col16 Color
= CurrentEntry
->Color
;
448 GetRed16(Color
)-((GetRed16(Color
)*3*Index
/PageLength
)>>2),
449 GetGreen16(Color
)-((GetGreen16(Color
)*3*Index
/PageLength
)>>2),
450 GetBlue16(Color
)-((GetBlue16(Color
)*3*Index
/PageLength
)>>2));
451 FONT
->PrintfColored(Bitmap
, v2(13, Bottom
), Color
, "%s", Chapter
[ChapterSize
-c2
-1].CStr());
453 if (++Index
== PageLength
) return;
459 void felist::CreateQuickDrawFontCaches (rawbitmap
*Font
, col16 Color
, uInt PageLength
) {
460 if (PageLength
< 2) return;
461 for (uInt c
= 0; c
< PageLength
; ++c
)
462 Font
->CreateFontCache(
464 GetRed16(Color
)-((GetRed16(Color
)*3*c
/PageLength
)>>2),
465 GetGreen16(Color
)-((GetGreen16(Color
)*3*c
/PageLength
)>>2),
466 GetBlue16(Color
)-((GetBlue16(Color
)*3*c
/PageLength
)>>2)));
470 void felist::Empty () {
471 for (uInt c
= 0; c
< Entry
.size(); ++c
) delete Entry
[c
];
476 void felist::AddEntry (cfestring
&Str
, col16 Color
, uInt Marginal
, uInt Key
, truth Selectable
) {
477 Entry
.push_back(new felistentry(Str
, Color
, Marginal
, Key
, Selectable
));
478 if (Maximum
&& Entry
.size() > feuLong(Maximum
)) {
480 Entry
.erase(Entry
.begin());
485 void felist::Save (outputfile
&SaveFile
) const {
486 SaveFile
<< Entry
<< Maximum
<< Selected
;
490 void felist::Load (inputfile
& SaveFile
) {
491 SaveFile
>> Entry
>> Maximum
>> Selected
;
495 void felist::PrintToFile (cfestring
& FileName
) {
496 std::ofstream
SaveFile(FileName
.CStr(), std::ios::out
);
497 if (!SaveFile
.is_open()) return;
499 for (c
= 0; c
< Description
.size(); ++c
) SaveFile
<< Description
[c
]->String
.CStr() << std::endl
;
500 SaveFile
<< std::endl
;
501 for (c
= 0; c
< Entry
.size(); ++c
) {
502 if (Entry
[c
]->ImageKey
!= NO_IMAGE
) SaveFile
<< " ";
503 SaveFile
<< Entry
[c
]->String
.CStr() << std::endl
;
508 void felist::AddDescription (cfestring
&Str
, col16 Color
) {
509 Description
.push_back(new felistdescription(Str
, Color
));
513 festring
felist::GetEntry (uInt I
) const {
514 return Entry
[I
]->String
;
518 col16
felist::GetColor (uInt I
) const {
519 return Entry
[I
]->Color
;
523 void felist::SetColor (uInt I
, col16 What
) {
524 Entry
[I
]->Color
= What
;