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
;
109 FelistCurrentlyDrawn
= this;
110 if (globalwindowhandler::ControlLoopsInstalled()) globalwindowhandler::InstallControlLoop(FelistDrawController
);
111 bitmap
BackGround(RES
);
112 BackGround
.ActivateFastFlag();
115 Buffer
= new bitmap(RES
, 0);
116 Buffer
->ActivateFastFlag();
117 BackGround
.ClearToColor(0);
119 Buffer
= DOUBLE_BUFFER
;
120 Buffer
->FastBlit(&BackGround
);
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
;
131 truth AtTheEnd
= DrawPage(Buffer
);
133 if (JustSelectMove
) {
134 Buffer
->FastBlit(DOUBLE_BUFFER
);
135 graphics::BlitDBToScreen();
137 Buffer
->FadeToScreen();
139 JustSelectMove
= false;
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') {
149 if (Pressed
< PageLength
&& Pressed
+PageBegin
< Selectables
) {
150 Return
= Selected
= Pressed
+PageBegin
;
152 JustSelectMove
= true;
160 if (Pressed
== UpKey
) {
163 if (Selected
< PageBegin
) {
164 BackGround
.FastBlit(Buffer
);
165 PageBegin
-= PageLength
;
167 JustSelectMove
= true;
170 for (c
= 0, Selected
= 0; c
< Entry
.size(); ++c
) if (Entry
[c
]->Selectable
) ++Selected
;
172 if (PageBegin
== Selected
-Selected
%PageLength
) JustSelectMove
= true;
174 BackGround
.FastBlit(Buffer
);
175 PageBegin
= Selected
-Selected
%PageLength
;
180 if (Pressed
== DownKey
) {
181 if (!AtTheEnd
|| Selected
!= Selectables
-1) {
183 if (Selected
> PageBegin
+PageLength
-1) {
184 BackGround
.FastBlit(Buffer
);
185 PageBegin
+= PageLength
;
187 JustSelectMove
= true;
190 if (!PageBegin
) JustSelectMove
= true; else BackGround
.FastBlit(Buffer
);
191 Selected
= PageBegin
= 0;
195 if (Pressed
== KEY_HOME
) {
196 Selected
= PageBegin
;
197 JustSelectMove
= true;
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");
203 Selected
= PageBegin
+PageLength
-1;
204 if (Selected
>= Selectables
) Selected
= Selectables
-1;
206 JustSelectMove
= true;
209 if (Pressed
== KEY_ENTER
) {
214 if (Pressed
== KEY_ESC
) {
218 if ((AtTheEnd
&& !(Flags
& INVERSE_MODE
)) || (!PageBegin
&& (Flags
& INVERSE_MODE
))) {
219 if (Flags
& FELIST_NO_BADKEY_EXIT
) continue;
220 Return
= NOTHING_SELECTED
;
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();
234 globalwindowhandler::DeInstallControlLoop(FelistDrawController
);
239 //static festring Str;
241 truth
felist::DrawPage (bitmap
*Buffer
) const {
242 uInt LastFillBottom
= Pos
.Y
+23+Description
.size()*10;
245 DrawDescription(Buffer
);
246 uInt c
, i
; // c == entry index, i == selectable index
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
;
256 uInt Marginal
= Entry
[c
]->Marginal
;
257 if (Flags
& SELECTABLE
&& Entry
[c
]->Selectable
) {
258 Str
<< char('A'+(i
-PageBegin
)) << ": ";
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
);
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());
272 FONT
->Printf(Buffer
, v2(Pos
.X
+37, LastFillBottom
+4), Entry
[c
]->Color
, "%s", Str
.CStr());
274 LastFillBottom
+= 20;
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
);
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());
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
);
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
);
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());
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;
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);
315 if (Entry
[c
++]->Selectable
) ++i
;
317 if (selIdx
!= -1 && mSaveSelector
) {
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";
326 imgName
= mSaveDir
+imgName
+".png";
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
))
332 if (bmp
.LoadPNG(imgName
))
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
;
345 {0}, // luminance/flags
346 0xDEAD, // mask color
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;
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
;
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());
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(
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
];
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
)) {
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;
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
;