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
, feuLong udata
) :
44 Selectable(Selectable
),
56 outputfile
&operator << (outputfile
&SaveFile
, const felistentry
*Entry
) {
57 SaveFile
<< Entry
->String
<< Entry
->Color
<< Entry
->Marginal
<< Entry
->Selectable
;
62 inputfile
&operator >> (inputfile
&SaveFile
, felistentry
*&Entry
) {
63 Entry
= new felistentry
;
64 SaveFile
>> Entry
->String
>> Entry
->Color
>> Entry
->Marginal
>> Entry
->Selectable
;
69 struct felistdescription
{
70 felistdescription () {}
71 felistdescription (cfestring
&String
, col16 Color
)
72 : String(String
), Color(Color
) {}
78 felist::felist (cfestring
&Topic
, col16 TopicColor
, uInt Maximum
) :
87 Flags(SELECTABLE
|FADE
),
92 AddDescription(Topic
, TopicColor
);
98 for (uInt c
= 0; c
< Description
.size(); ++c
) delete Description
[c
];
102 truth
felist::IsEntrySelectable (uInt idx
) const {
103 return (idx
< Entry
.size() ? Entry
[idx
]->Selectable
: false);
107 feuLong
felist::GetEntryUData (uInt idx
) const {
108 return (idx
< Entry
.size() ? Entry
[idx
]->UData
: 0);
112 void felist::SetEntryUData (uInt idx
, feuLong udata
) {
113 if (idx
< Entry
.size()) Entry
[idx
]->UData
= udata
;
117 void felist::Pop () {
118 delete Entry
[GetLastEntryIndex()];
123 uInt
felist::Draw () {
124 while (Entry
.size() && Entry
[GetLastEntryIndex()]->String
.IsEmpty()) Pop();
125 if (Entry
.empty()) return LIST_WAS_EMPTY
;
127 FelistCurrentlyDrawn
= this;
128 if (globalwindowhandler::ControlLoopsInstalled()) globalwindowhandler::InstallControlLoop(FelistDrawController
);
130 bitmap
BackGround(RES
);
133 BackGround
.ActivateFastFlag();
135 Buffer
= new bitmap(RES
, 0);
136 Buffer
->ActivateFastFlag();
137 BackGround
.ClearToColor(0);
139 Buffer
= DOUBLE_BUFFER
;
140 Buffer
->FastBlit(&BackGround
);
144 uInt Return
, Selectables
= 0;
145 truth JustSelectMove
= false;
146 for (c
= 0; c
< Entry
.size(); ++c
) if (Entry
[c
]->Selectable
) ++Selectables
;
147 if (Selected
>= Selectables
) Selected
= Selectables
-1;
149 if (Flags
&SELECTABLE
) PageBegin
= Selected
-Selected
%PageLength
;
150 else if (Flags
&INVERSE_MODE
) PageBegin
= GetLastEntryIndex()-GetLastEntryIndex()%PageLength
;
154 truth AtTheEnd
= DrawPage(Buffer
);
156 if (JustSelectMove
) {
157 Buffer
->FastBlit(DOUBLE_BUFFER
);
158 graphics::BlitDBToScreen();
160 Buffer
->FadeToScreen();
162 JustSelectMove
= false;
164 graphics::BlitDBToScreen();
167 uInt Pressed
= GET_KEY(false);
169 if (Flags
&SELECTABLE
) {
170 // list movement and selections
173 if (Pressed
>= 'a' && Pressed
<= 'z') prs
= Pressed
-'a';
174 else if (Pressed
>= 'A' && Pressed
<= 'Z') prs
= Pressed
-'A';
175 else if (Pressed
>= '0' && Pressed
<= '9') prs
= Pressed
-'0'+26;
178 if ((uInt
)prs
< PageLength
&& (uInt
)prs
+PageBegin
< Selectables
) {
179 Return
= Selected
= (uInt
)prs
+PageBegin
;
181 JustSelectMove
= true;
190 if (Pressed
== UpKey
) {
193 if (Selected
< PageBegin
) {
194 BackGround
.FastBlit(Buffer
);
195 PageBegin
-= PageLength
;
197 JustSelectMove
= true;
200 for (c
= 0, Selected
= 0; c
< Entry
.size(); ++c
) if (Entry
[c
]->Selectable
) ++Selected
;
202 if (PageBegin
== Selected
-Selected
%PageLength
) JustSelectMove
= true;
204 BackGround
.FastBlit(Buffer
);
205 PageBegin
= Selected
-Selected
%PageLength
;
211 if (Pressed
== DownKey
) {
212 if (!AtTheEnd
|| Selected
!= Selectables
-1) {
214 if (Selected
> PageBegin
+PageLength
-1) {
215 PageBegin
+= PageLength
;
216 BackGround
.FastBlit(Buffer
);
218 JustSelectMove
= true;
221 if (!PageBegin
) JustSelectMove
= true; else BackGround
.FastBlit(Buffer
);
222 Selected
= PageBegin
= 0;
227 if (Pressed
== KEY_HOME
) {
228 Selected
= PageBegin
;
229 JustSelectMove
= true;
233 if (Pressed
== KEY_END
) {
234 //fprintf(stderr, "sel: %u; pb: %u; pl: %u; ss: %u; ae: %s\n", Selected, PageBegin, PageLength, Selectables, AtTheEnd ? "end" : "not end");
236 Selected
= PageBegin
+PageLength
-1;
237 if (Selected
>= Selectables
) Selected
= Selectables
-1;
239 JustSelectMove
= true;
243 if (Pressed
== KEY_LEFT
) {
245 if (Selectables
&& PageBegin
> 0) {
246 PageBegin
= (PageBegin
< PageLength
? 0 : PageBegin
-PageLength
);
247 Selected
= PageBegin
;
248 BackGround
.FastBlit(Buffer
);
253 if (Pressed
== KEY_RIGHT
) {
256 uInt pgend
= PageBegin
+PageLength
;
257 if (pgend
< Selectables
) {
258 PageBegin
+= PageLength
;
259 Selected
= PageBegin
;
260 BackGround
.FastBlit(Buffer
);
266 if (Pressed
== KEY_ENTER
) {
271 // not selectable: allow navigation with left/right
272 if (Pressed
== KEY_LEFT
) {
274 PageBegin
-= (PageBegin
< PageLength
? PageBegin
: PageLength
);
275 BackGround
.FastBlit(Buffer
);
280 if (Pressed
== KEY_RIGHT
) {
282 PageBegin
+= PageLength
;
283 BackGround
.FastBlit(Buffer
);
289 if (Pressed
== KEY_ESC
) {
294 if ((AtTheEnd
&& !(Flags
&INVERSE_MODE
)) || (!PageBegin
&& (Flags
&INVERSE_MODE
))) {
295 if (Flags
&FELIST_NO_BADKEY_EXIT
) continue;
296 Return
= NOTHING_SELECTED
;
299 BackGround
.FastBlit(Buffer
);
300 if (Flags
&INVERSE_MODE
) PageBegin
-= PageLength
; else PageBegin
+= PageLength
;
301 if (Flags
&SELECTABLE
) Selected
= PageBegin
;
306 if (Flags
&DRAW_BACKGROUND_AFTERWARDS
) BackGround
.FastBlit(DOUBLE_BUFFER
);
307 if (Flags
&BLIT_AFTERWARDS
) graphics::BlitDBToScreen();
312 globalwindowhandler::DeInstallControlLoop(FelistDrawController
);
317 //static festring Str;
319 truth
felist::DrawPage (bitmap
*Buffer
) const {
320 uInt LastFillBottom
= Pos
.Y
+23+Description
.size()*10;
323 DrawDescription(Buffer
);
324 uInt c
, i
; // c == entry index, i == selectable index
326 for (c
= 0, i
= 0; i
!= PageBegin
; ++c
) if (Entry
[c
]->Selectable
) ++i
;
327 while (!Entry
[c
]->Selectable
&& Entry
[c
]->String
.IsEmpty()) ++c
;
328 std::vector
<festring
> Chapter
;
330 //col16 selBack = BackColor^0xFFFF, selText = BackColor;
331 //col16 selBack = LIGHT_GRAY, selText = BLACK;
332 col16 selBack
= SEL_BLUE
, selText
= WHITE
;
336 uInt Marginal
= Entry
[c
]->Marginal
;
337 if ((Flags
&SELECTABLE
) && Entry
[c
]->Selectable
) {
338 if (i
-PageBegin
<= 25) Str
<< char('A'+(i
-PageBegin
)); else Str
<< char('0'+(i
-PageBegin
-26));
342 Str
<< Entry
[c
]->String
;
343 bool selected
= (Flags
&SELECTABLE
&& Entry
[c
]->Selectable
&& Selected
== i
);
344 if (selected
) selIdx
= (int)c
;
345 col16 ecolor
= Entry
[c
]->Color
;
347 if (ecolor
!= RED
&& ecolor
!= GREEN
&& ecolor
!= PINK
&& ecolor
!= ORANGE
) ecolor
= selText
;
349 if (Entry
[c
]->ImageKey
!= NO_IMAGE
) {
350 if (Str
.rawLength() <= (Width
-50)>>3) {
351 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 20, (!selected
? BackColor
: selBack
));
352 if (EntryDrawer
) EntryDrawer(Buffer
, v2(Pos
.X
+13, LastFillBottom
), Entry
[c
]->ImageKey
);
354 FONT
->PrintfUnshadedColored(Buffer
, v2(Pos
.X
+37, LastFillBottom
+4), ecolor
, "%s", Str
.CStr());
356 FONT
->PrintfColored(Buffer
, v2(Pos
.X
+37, LastFillBottom
+4), ecolor
, "%s", Str
.CStr());
358 LastFillBottom
+= 20;
360 uInt ChapterSize
= festring::SplitStringColored(Str
, Chapter
, (Width
-50)>>3, Marginal
);
361 uInt PictureTop
= LastFillBottom
+ChapterSize
*5-9;
362 for (uInt l
= 0; l
< ChapterSize
; ++l
) {
363 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 10, !selected
? BackColor
: selBack
);
365 FONT
->PrintfUnshadedColored(Buffer
, v2(Pos
.X
+37, LastFillBottom
), ecolor
, "%s", Chapter
[l
].CStr());
367 FONT
->PrintfColored(Buffer
, v2(Pos
.X
+37, LastFillBottom
), ecolor
, "%s", Chapter
[l
].CStr());
369 LastFillBottom
+= 10;
371 if (EntryDrawer
) EntryDrawer(Buffer
, v2(Pos
.X
+13, PictureTop
), Entry
[c
]->ImageKey
);
374 uInt ChapterSize
= festring::SplitStringColored(Str
, Chapter
, (Width
-26)>>3, Marginal
);
375 for (uInt l
= 0; l
< ChapterSize
; ++l
) {
376 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 10, !selected
? BackColor
: selBack
);
378 FONT
->PrintfUnshadedColored(Buffer
, v2(Pos
.X
+13, LastFillBottom
), ecolor
, "%s", Chapter
[l
].CStr());
380 FONT
->PrintfColored(Buffer
, v2(Pos
.X
+13, LastFillBottom
), ecolor
, "%s", Chapter
[l
].CStr());
382 LastFillBottom
+= 10;
385 if ((i
-PageBegin
== PageLength
-1 && Entry
[c
]->Selectable
) || c
== Entry
.size()-1) {
386 if ((!(Flags
&INVERSE_MODE
) && c
!= Entry
.size()-1) || (Flags
&INVERSE_MODE
&& PageBegin
)) {
387 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 30, BackColor
);
388 FONT
->PrintfColored(Buffer
, v2(Pos
.X
+13, LastFillBottom
+10), WHITE
, "- Press SPACE to continue, ESC to exit -");
389 LastFillBottom
+= 30;
391 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 10, BackColor
);
392 LastFillBottom
+= 10;
394 Buffer
->DrawRectangle(Pos
.X
+1, Pos
.Y
+1, Pos
.X
+Width
-2, LastFillBottom
+1, DARK_GRAY
, true);
397 if (Entry
[c
++]->Selectable
) ++i
;
399 if (selIdx
!= -1 && mSaveSelector
) {
401 festring imgName
= Entry
[selIdx
]->String
;
402 festring::sizetype pos
= imgName
.FindLast(".sav");
403 if (pos
!= festring::NPos
) {
404 imgName
.Erase(pos
, 4); // remove '.sav'
405 #if defined(SGAME_SHOTS_IPU) || (!defined(HAVE_IMLIB2) && !defined(HAVE_LIBPNG))
406 imgName
= mSaveDir
+imgName
+".ipu";
408 imgName
= mSaveDir
+imgName
+".png";
410 //fprintf(stderr, "sel=%d; img=%s\n", selIdx, imgName.CStr());
411 #if defined(SGAME_SHOTS_IPU) || (!defined(HAVE_IMLIB2) && !defined(HAVE_LIBPNG))
412 if (bmp
.LoadIPU(imgName
))
414 if (bmp
.LoadPNG(imgName
))
417 //fprintf(stderr, " LOADED! %dx%d\n", bmp.GetSize().X, bmp.GetSize().Y);
418 int x
= Buffer
->GetSize().X
-bmp
.GetSize().X
-2;
419 int y
= Buffer
->GetSize().Y
-bmp
.GetSize().Y
-2;
420 int w
= bmp
.GetSize().X
;
421 int h
= bmp
.GetSize().Y
;
427 {0}, // luminance/flags
428 0xDEAD, // mask color
432 Buffer
->DrawRectangle(x
-2, y
-2, x
+w
, y
+h
, DARK_GRAY
, true);
436 return c
== Entry
.size()-1;
440 void felist::DrawDescription (bitmap
*Buffer
) const {
441 Buffer
->Fill(Pos
.X
+3, Pos
.Y
+3, Width
-6, 20, BackColor
);
442 for (uInt c
= 0; c
< Description
.size(); ++c
) {
443 Buffer
->Fill(Pos
.X
+3, Pos
.Y
+13+c
*10, Width
-6, 10, BackColor
);
444 FONT
->PrintfColored(Buffer
, v2(Pos
.X
+13, Pos
.Y
+13+c
*10), Description
[c
]->Color
, "%s", Description
[c
]->String
.CStr());
446 Buffer
->Fill(Pos
.X
+3, Pos
.Y
+13+Description
.size()*10, Width
-6, 10, BackColor
);
450 /* We suppose InverseMode != false here */
451 void felist::QuickDraw (bitmap
*Bitmap
, uInt PageLength
) const {
452 static std::vector
<festring
> Chapter
;
453 uInt Width
= Bitmap
->GetSize().X
;
454 Bitmap
->Fill(3, 3, Width
-6, 20+PageLength
*10, 0);
455 Bitmap
->DrawRectangle(1, 1, Width
-2, 24+PageLength
*10, DARK_GRAY
, true);
456 uInt LineSize
= (Width
-26)>>3;
458 uInt Bottom
= PageLength
*10+3;
459 for (uInt c1
= 0; c1
<= Selected
; ++c1
) {
460 const felistentry
* CurrentEntry
= Entry
[Selected
-c1
];
461 uInt ChapterSize
= festring::SplitStringColored(CurrentEntry
->String
, Chapter
, LineSize
, CurrentEntry
->Marginal
);
462 for (uInt c2
= 0; c2
< ChapterSize
; ++c2
) {
463 col16 Color
= CurrentEntry
->Color
;
465 GetRed16(Color
)-((GetRed16(Color
)*3*Index
/PageLength
)>>2),
466 GetGreen16(Color
)-((GetGreen16(Color
)*3*Index
/PageLength
)>>2),
467 GetBlue16(Color
)-((GetBlue16(Color
)*3*Index
/PageLength
)>>2));
468 FONT
->PrintfColored(Bitmap
, v2(13, Bottom
), Color
, "%s", Chapter
[ChapterSize
-c2
-1].CStr());
470 if (++Index
== PageLength
) return;
476 void felist::CreateQuickDrawFontCaches (rawbitmap
*Font
, col16 Color
, uInt PageLength
) {
477 if (PageLength
< 2) return;
478 for (uInt c
= 0; c
< PageLength
; ++c
)
479 Font
->CreateFontCache(
481 GetRed16(Color
)-((GetRed16(Color
)*3*c
/PageLength
)>>2),
482 GetGreen16(Color
)-((GetGreen16(Color
)*3*c
/PageLength
)>>2),
483 GetBlue16(Color
)-((GetBlue16(Color
)*3*c
/PageLength
)>>2)));
487 void felist::Empty () {
488 for (uInt c
= 0; c
< Entry
.size(); ++c
) delete Entry
[c
];
493 void felist::AddEntry (cfestring
&Str
, col16 Color
, uInt Marginal
, uInt Key
, truth Selectable
, feuLong udata
) {
494 Entry
.push_back(new felistentry(Str
, Color
, Marginal
, Key
, Selectable
, udata
));
495 if (Maximum
&& Entry
.size() > feuLong(Maximum
)) {
497 Entry
.erase(Entry
.begin());
502 void felist::Save (outputfile
&SaveFile
) const {
503 SaveFile
<< Entry
<< Maximum
<< Selected
;
507 void felist::Load (inputfile
& SaveFile
) {
508 SaveFile
>> Entry
>> Maximum
>> Selected
;
512 void felist::PrintToFile (cfestring
& FileName
) {
513 std::ofstream
SaveFile(FileName
.CStr(), std::ios::out
);
514 if (!SaveFile
.is_open()) return;
516 for (c
= 0; c
< Description
.size(); ++c
) SaveFile
<< Description
[c
]->String
.CStr() << std::endl
;
517 SaveFile
<< std::endl
;
518 for (c
= 0; c
< Entry
.size(); ++c
) {
519 if (Entry
[c
]->ImageKey
!= NO_IMAGE
) SaveFile
<< " ";
520 SaveFile
<< Entry
[c
]->String
.CStr() << std::endl
;
525 void felist::AddDescription (cfestring
&Str
, col16 Color
) {
526 Description
.push_back(new felistdescription(Str
, Color
));
530 festring
felist::GetEntry (uInt I
) const {
531 return Entry
[I
]->String
;
535 col16
felist::GetColor (uInt I
) const {
536 return Entry
[I
]->Color
;
540 void felist::SetColor (uInt I
, col16 What
) {
541 Entry
[I
]->Color
= What
;