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
) :
83 Flags(SELECTABLE
|FADE
),
88 AddDescription(Topic
, TopicColor
);
94 for (uint c
= 0; c
< Description
.size(); ++c
) delete Description
[c
];
99 delete Entry
[GetLastEntryIndex()];
104 uint
felist::Draw () {
105 while (Entry
.size() && Entry
[GetLastEntryIndex()]->String
.IsEmpty()) Pop();
106 if (Entry
.empty()) return LIST_WAS_EMPTY
;
107 FelistCurrentlyDrawn
= this;
108 if (globalwindowhandler::ControlLoopsInstalled()) globalwindowhandler::InstallControlLoop(FelistDrawController
);
109 bitmap
BackGround(RES
);
110 BackGround
.ActivateFastFlag();
113 Buffer
= new bitmap(RES
, 0);
114 Buffer
->ActivateFastFlag();
115 BackGround
.ClearToColor(0);
117 Buffer
= DOUBLE_BUFFER
;
118 Buffer
->FastBlit(&BackGround
);
121 uint Return
, Selectables
= 0;
122 truth JustSelectMove
= false;
123 for (c
= 0; c
< Entry
.size(); ++c
) if (Entry
[c
]->Selectable
) ++Selectables
;
124 if (Selected
>= Selectables
) Selected
= Selectables
-1;
125 if (Flags
& SELECTABLE
) PageBegin
= Selected
-Selected
%PageLength
;
126 else if (Flags
& INVERSE_MODE
) PageBegin
= GetLastEntryIndex()-GetLastEntryIndex()%PageLength
;
129 truth AtTheEnd
= DrawPage(Buffer
);
131 if (JustSelectMove
) {
132 Buffer
->FastBlit(DOUBLE_BUFFER
);
133 graphics::BlitDBToScreen();
135 Buffer
->FadeToScreen();
137 JustSelectMove
= false;
139 graphics::BlitDBToScreen();
141 uint Pressed
= GET_KEY(false);
142 if (Flags
& SELECTABLE
) {
143 // list movement and selections
144 if (Pressed
>= 'a' && Pressed
<= 'z') Pressed
-= 32;
145 if (Pressed
>= 'A' && Pressed
<= 'Z') {
147 if (Pressed
< PageLength
&& Pressed
+PageBegin
< Selectables
) {
148 Return
= Selected
= Pressed
+PageBegin
;
150 JustSelectMove
= true;
158 if (Pressed
== UpKey
) {
161 if (Selected
< PageBegin
) {
162 BackGround
.FastBlit(Buffer
);
163 PageBegin
-= PageLength
;
165 JustSelectMove
= true;
168 for (c
= 0, Selected
= 0; c
< Entry
.size(); ++c
) if (Entry
[c
]->Selectable
) ++Selected
;
170 if (PageBegin
== Selected
-Selected
%PageLength
) JustSelectMove
= true;
172 BackGround
.FastBlit(Buffer
);
173 PageBegin
= Selected
-Selected
%PageLength
;
178 if (Pressed
== DownKey
) {
179 if (!AtTheEnd
|| Selected
!= Selectables
-1) {
181 if (Selected
> PageBegin
+PageLength
-1) {
182 BackGround
.FastBlit(Buffer
);
183 PageBegin
+= PageLength
;
185 JustSelectMove
= true;
188 if (!PageBegin
) JustSelectMove
= true; else BackGround
.FastBlit(Buffer
);
189 Selected
= PageBegin
= 0;
193 if (Pressed
== KEY_HOME
) {
194 Selected
= PageBegin
;
195 JustSelectMove
= true;
198 if (Pressed
== KEY_END
) {
199 //fprintf(stderr, "sel: %u; pb: %u; pl: %u; ss: %u; ae: %s\n", Selected, PageBegin, PageLength, Selectables, AtTheEnd ? "end" : "not end");
201 Selected
= PageBegin
+PageLength
-1;
202 if (Selected
>= Selectables
) Selected
= Selectables
-1;
204 JustSelectMove
= true;
207 if (Pressed
== KEY_ENTER
) {
212 if (Pressed
== KEY_ESC
) {
216 if ((AtTheEnd
&& !(Flags
& INVERSE_MODE
)) || (!PageBegin
&& (Flags
& INVERSE_MODE
))) {
217 if (Flags
& FELIST_NO_BADKEY_EXIT
) continue;
218 Return
= NOTHING_SELECTED
;
221 BackGround
.FastBlit(Buffer
);
222 if (Flags
& INVERSE_MODE
) PageBegin
-= PageLength
; else PageBegin
+= PageLength
;
223 if (Flags
& SELECTABLE
) Selected
= PageBegin
;
226 if (!(Flags
& FADE
)) {
227 if (Flags
& DRAW_BACKGROUND_AFTERWARDS
) BackGround
.FastBlit(DOUBLE_BUFFER
);
228 if (Flags
& BLIT_AFTERWARDS
) graphics::BlitDBToScreen();
232 globalwindowhandler::DeInstallControlLoop(FelistDrawController
);
239 truth
felist::DrawPage (bitmap
*Buffer
) const {
240 uint LastFillBottom
= Pos
.Y
+23+Description
.size()*10;
241 DrawDescription(Buffer
);
242 uint c
, i
; // c == entry index, i == selectable index
243 for (c
= 0, i
= 0; i
!= PageBegin
; ++c
) if (Entry
[c
]->Selectable
) ++i
;
244 while (!Entry
[c
]->Selectable
&& Entry
[c
]->String
.IsEmpty()) ++c
;
245 std::vector
<festring
> Chapter
;
246 //col16 selBack = BackColor^0xFFFF, selText = BackColor;
247 //col16 selBack = LIGHT_GRAY, selText = BLACK;
248 col16 selBack
= BLUE
, selText
= WHITE
;
251 uint Marginal
= Entry
[c
]->Marginal
;
252 if (Flags
& SELECTABLE
&& Entry
[c
]->Selectable
) {
253 Str
<< char('A'+(i
-PageBegin
)) << ": ";
256 Str
<< Entry
[c
]->String
;
257 bool selected
= (Flags
& SELECTABLE
&& Entry
[c
]->Selectable
&& Selected
== i
);
258 if (Entry
[c
]->ImageKey
!= NO_IMAGE
) {
259 if (Str
.GetSize() <= (Width
-50)>>3) {
260 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 20, !selected
? BackColor
: selBack
);
261 if (EntryDrawer
) EntryDrawer(Buffer
, v2(Pos
.X
+13, LastFillBottom
), Entry
[c
]->ImageKey
);
263 //FONT->PrintfUnshaded(Buffer, v2(Pos.X+38, LastFillBottom+5), WHITE, "%s", Str.CStr());
264 FONT
->PrintfUnshaded(Buffer
, v2(Pos
.X
+37, LastFillBottom
+4), selText
, "%s", Str
.CStr());
266 FONT
->Printf(Buffer
, v2(Pos
.X
+37, LastFillBottom
+4), Entry
[c
]->Color
, "%s", Str
.CStr());
268 LastFillBottom
+= 20;
270 uint ChapterSize
= festring::SplitString(Str
, Chapter
, (Width
-50)>>3, Marginal
);
271 uint PictureTop
= LastFillBottom
+ChapterSize
*5-9;
272 for (uint l
= 0; l
< ChapterSize
; ++l
) {
273 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 10, !selected
? BackColor
: selBack
);
275 //FONT->PrintfUnshaded(Buffer, v2(Pos.X+38, LastFillBottom+1), WHITE, "%s", Chapter[l].CStr());
276 FONT
->PrintfUnshaded(Buffer
, v2(Pos
.X
+37, LastFillBottom
), selText
, "%s", Chapter
[l
].CStr());
278 FONT
->Printf(Buffer
, v2(Pos
.X
+37, LastFillBottom
), Entry
[c
]->Color
, "%s", Chapter
[l
].CStr());
280 LastFillBottom
+= 10;
282 if (EntryDrawer
) EntryDrawer(Buffer
, v2(Pos
.X
+13, PictureTop
), Entry
[c
]->ImageKey
);
285 uint ChapterSize
= festring::SplitString(Str
, Chapter
, (Width
-26)>>3, Marginal
);
286 for (uint l
= 0; l
< ChapterSize
; ++l
) {
287 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 10, !selected
? BackColor
: selBack
);
289 //FONT->PrintfUnshaded(Buffer, v2(Pos.X+14, LastFillBottom+1), WHITE, "%s", Chapter[l].CStr());
290 FONT
->PrintfUnshaded(Buffer
, v2(Pos
.X
+13, LastFillBottom
), selText
, "%s", Chapter
[l
].CStr());
292 FONT
->Printf(Buffer
, v2(Pos
.X
+13, LastFillBottom
), Entry
[c
]->Color
, "%s", Chapter
[l
].CStr());
294 LastFillBottom
+= 10;
297 if ((i
-PageBegin
== PageLength
-1 && Entry
[c
]->Selectable
) || c
== Entry
.size()-1) {
298 if ((!(Flags
& INVERSE_MODE
) && c
!= Entry
.size()-1) || (Flags
& INVERSE_MODE
&& PageBegin
)) {
299 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 30, BackColor
);
300 FONT
->Printf(Buffer
, v2(Pos
.X
+13, LastFillBottom
+10), WHITE
, "- Press SPACE to continue, ESC to exit -");
301 LastFillBottom
+= 30;
303 Buffer
->Fill(Pos
.X
+3, LastFillBottom
, Width
-6, 10, BackColor
);
304 LastFillBottom
+= 10;
306 Buffer
->DrawRectangle(Pos
.X
+1, Pos
.Y
+1, Pos
.X
+Width
-2, LastFillBottom
+1, DARK_GRAY
, true);
309 if (Entry
[c
++]->Selectable
) ++i
;
311 return c
== Entry
.size()-1;
315 void felist::DrawDescription (bitmap
*Buffer
) const {
316 Buffer
->Fill(Pos
.X
+3, Pos
.Y
+3, Width
-6, 20, BackColor
);
317 for (uint c
= 0; c
< Description
.size(); ++c
) {
318 Buffer
->Fill(Pos
.X
+3, Pos
.Y
+13+c
*10, Width
-6, 10, BackColor
);
319 FONT
->Printf(Buffer
, v2(Pos
.X
+13, Pos
.Y
+13+c
*10), Description
[c
]->Color
, Description
[c
]->String
.CStr());
321 Buffer
->Fill(Pos
.X
+3, Pos
.Y
+13+Description
.size()*10, Width
-6, 10, BackColor
);
325 /* We suppose InverseMode != false here */
326 void felist::QuickDraw (bitmap
*Bitmap
, uint PageLength
) const {
327 static std::vector
<festring
> Chapter
;
328 uint Width
= Bitmap
->GetSize().X
;
329 Bitmap
->Fill(3, 3, Width
-6, 20+PageLength
*10, 0);
330 Bitmap
->DrawRectangle(1, 1, Width
-2, 24+PageLength
*10, DARK_GRAY
, true);
331 uint LineSize
= (Width
-26)>>3;
333 uint Bottom
= PageLength
*10+3;
334 for (uint c1
= 0; c1
<= Selected
; ++c1
) {
335 const felistentry
* CurrentEntry
= Entry
[Selected
-c1
];
336 uint ChapterSize
= festring::SplitString(CurrentEntry
->String
, Chapter
, LineSize
, CurrentEntry
->Marginal
);
337 for (uint c2
= 0; c2
< ChapterSize
; ++c2
) {
338 col16 Color
= CurrentEntry
->Color
;
340 GetRed16(Color
)-((GetRed16(Color
)*3*Index
/PageLength
)>>2),
341 GetGreen16(Color
)-((GetGreen16(Color
)*3*Index
/PageLength
)>>2),
342 GetBlue16(Color
)-((GetBlue16(Color
)*3*Index
/PageLength
)>>2));
343 FONT
->Printf(Bitmap
, v2(13, Bottom
), Color
, "%s", Chapter
[ChapterSize
-c2
-1].CStr());
345 if (++Index
== PageLength
) return;
351 void felist::CreateQuickDrawFontCaches (rawbitmap
*Font
, col16 Color
, uint PageLength
) {
352 if (PageLength
< 2) return;
353 for (uint c
= 0; c
< PageLength
; ++c
)
354 Font
->CreateFontCache(
356 GetRed16(Color
)-((GetRed16(Color
)*3*c
/PageLength
)>>2),
357 GetGreen16(Color
)-((GetGreen16(Color
)*3*c
/PageLength
)>>2),
358 GetBlue16(Color
)-((GetBlue16(Color
)*3*c
/PageLength
)>>2)));
362 void felist::Empty () {
363 for (uint c
= 0; c
< Entry
.size(); ++c
) delete Entry
[c
];
368 void felist::AddEntry (cfestring
&Str
, col16 Color
, uint Marginal
, uint Key
, truth Selectable
) {
369 Entry
.push_back(new felistentry(Str
, Color
, Marginal
, Key
, Selectable
));
370 if (Maximum
&& Entry
.size() > ulong(Maximum
)) {
372 Entry
.erase(Entry
.begin());
377 void felist::Save (outputfile
&SaveFile
) const {
378 SaveFile
<< Entry
<< Maximum
<< Selected
;
382 void felist::Load (inputfile
& SaveFile
) {
383 SaveFile
>> Entry
>> Maximum
>> Selected
;
387 void felist::PrintToFile (cfestring
& FileName
) {
388 std::ofstream
SaveFile(FileName
.CStr(), std::ios::out
);
389 if (!SaveFile
.is_open()) return;
391 for (c
= 0; c
< Description
.size(); ++c
) SaveFile
<< Description
[c
]->String
.CStr() << std::endl
;
392 SaveFile
<< std::endl
;
393 for (c
= 0; c
< Entry
.size(); ++c
) {
394 if (Entry
[c
]->ImageKey
!= NO_IMAGE
) SaveFile
<< " ";
395 SaveFile
<< Entry
[c
]->String
.CStr() << std::endl
;
400 void felist::AddDescription (cfestring
&Str
, col16 Color
) {
401 Description
.push_back(new felistdescription(Str
, Color
));
405 festring
felist::GetEntry (uint I
) const {
406 return Entry
[I
]->String
;
410 col16
felist::GetColor (uint I
) const {
411 return Entry
[I
]->Color
;
415 void felist::SetColor (uint I
, col16 What
) {
416 Entry
[I
]->Color
= What
;