1 //=============================================================================
2 //
3 // Adventure Game Studio (AGS)
4 //
5 // Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
6 // The full list of copyright holders can be found in the Copyright.txt
7 // file, which is part of this source code distribution.
8 //
9 // The AGS source code is provided under the Artistic License 2.0.
10 // A copy of this license can be found in the file License.txt and at
11 // http://www.opensource.org/licenses/artistic-license-2.0.php
12 //
13 //=============================================================================
14
15 #include <stdio.h>
16 #include "gui/guidialog.h"
17 #include "ac/common.h"
18 #include "ac/draw.h"
19 #include "ac/game.h"
20 #include "ac/gamesetup.h"
21 #include "ac/gamesetupstruct.h"
22 #include "gui/cscidialog.h"
23 #include <cctype> //isdigit()
24 #include "gfx/bitmap.h"
25 #include "gfx/graphicsdriver.h"
26
27 using namespace AGS::Common;
28 using namespace AGS::Engine;
29
30 extern IGraphicsDriver *gfxDriver;
31 extern GameSetup usetup;
32
33 // from ac_game
34 extern char saveGameDirectory[260];
35
36 int windowPosX, windowPosY, windowPosWidth, windowPosHeight;
37 Bitmap *windowBuffer;
38 IDriverDependantBitmap *dialogBmp;
39
40 #undef MAXSAVEGAMES
41 #define MAXSAVEGAMES 20
42 DisplayProperties dispp;
43 char *lpTemp, *lpTemp2;
44 char bufTemp[260], buffer2[260];
45 int numsaves = 0, toomanygames;
46 int filenumbers[MAXSAVEGAMES];
47 unsigned long filedates[MAXSAVEGAMES];
48
49 CSCIMessage smes;
50
51 char buff[200];
52 int myscrnwid = 320, myscrnhit = 200;
53
54
prepare_gui_screen(int x,int y,int width,int height,bool opaque)55 void prepare_gui_screen(int x, int y, int width, int height, bool opaque)
56 {
57 clear_gui_screen();
58 windowPosX = x;
59 windowPosY = y;
60 windowPosWidth = width;
61 windowPosHeight = height;
62 if (windowBuffer)
63 {
64 windowBuffer = recycle_bitmap(windowBuffer, windowBuffer->GetColorDepth(), windowPosWidth, windowPosHeight, !opaque);
65 }
66 else
67 {
68 windowBuffer = BitmapHelper::CreateBitmap(windowPosWidth, windowPosHeight, GetVirtualScreen()->GetColorDepth());
69 windowBuffer = ReplaceBitmapWithSupportedFormat(windowBuffer);
70 }
71 dialogBmp = recycle_ddb_bitmap(dialogBmp, windowBuffer, false, opaque);
72 }
73
clear_gui_screen()74 void clear_gui_screen()
75 {
76 if (dialogBmp)
77 gfxDriver->DestroyDDB(dialogBmp);
78 dialogBmp = NULL;
79 delete windowBuffer;
80 windowBuffer = NULL;
81 }
82
refresh_gui_screen()83 void refresh_gui_screen()
84 {
85 Bitmap *ds = GetVirtualScreen();
86 windowBuffer->Blit(ds, windowPosX, windowPosY, 0, 0, windowPosWidth, windowPosHeight);
87 gfxDriver->UpdateDDBFromBitmap(dialogBmp, windowBuffer, false);
88
89 render_graphics(dialogBmp, windowPosX, windowPosY);
90
91 // Copy it back, because the mouse will have been drawn on top
92 ds->Blit(windowBuffer, 0, 0, windowPosX, windowPosY, windowPosWidth, windowPosHeight);
93 }
94
loadgamedialog()95 int loadgamedialog()
96 {
97 int boxleft = myscrnwid / 2 - 100;
98 int boxtop = myscrnhit / 2 - 60;
99 int buttonhit = usetup.textheight + 5;
100 Bitmap *ds = GetVirtualScreen();
101 int handl = CSCIDrawWindow(ds, boxleft, boxtop, 200, 120);
102 int ctrlok =
103 CSCICreateControl(CNT_PUSHBUTTON | CNF_DEFAULT, boxleft + 135, boxtop + 5, 60, 10, get_global_message(MSG_RESTORE));
104 int ctrlcancel =
105 CSCICreateControl(CNT_PUSHBUTTON | CNF_CANCEL, boxleft + 135, boxtop + 5 + buttonhit, 60, 10,
106 get_global_message(MSG_CANCEL));
107 int ctrllist = CSCICreateControl(CNT_LISTBOX, boxleft + 10, boxtop + 30, 120, 80, NULL);
108 int ctrltex1 = CSCICreateControl(CNT_LABEL, boxleft + 10, boxtop + 5, 120, 0, get_global_message(MSG_SELECTLOAD));
109 CSCISendControlMessage(ctrllist, CLB_CLEAR, 0, 0);
110
111 preparesavegamelist(ctrllist);
112 CSCIMessage mes;
113 lpTemp = NULL;
114 int toret = -1;
115 while (1) {
116 CSCIWaitMessage(ds, &mes); //printf("mess: %d, id %d ",mes.code,mes.id);
117 if (mes.code == CM_COMMAND) {
118 if (mes.id == ctrlok) {
119 int cursel = CSCISendControlMessage(ctrllist, CLB_GETCURSEL, 0, 0);
120 if ((cursel >= numsaves) | (cursel < 0))
121 lpTemp = NULL;
122 else {
123 toret = filenumbers[cursel];
124 String path = get_save_game_path(toret);
125 strcpy(bufTemp, path);
126 lpTemp = &bufTemp[0];
127 }
128 } else if (mes.id == ctrlcancel) {
129 lpTemp = NULL;
130 }
131
132 break;
133 }
134 }
135
136 CSCIDeleteControl(ctrltex1);
137 CSCIDeleteControl(ctrllist);
138 CSCIDeleteControl(ctrlok);
139 CSCIDeleteControl(ctrlcancel);
140 CSCIEraseWindow(ds, handl);
141 return toret;
142 }
143
savegamedialog()144 int savegamedialog()
145 {
146 char okbuttontext[50];
147 strcpy(okbuttontext, get_global_message(MSG_SAVEBUTTON));
148 char labeltext[200];
149 strcpy(labeltext, get_global_message(MSG_SAVEDIALOG));
150 int boxleft = myscrnwid / 2 - 100;
151 int boxtop = myscrnhit / 2 - 60;
152 int buttonhit = usetup.textheight + 5;
153 int labeltop = boxtop + 5;
154 Bitmap *ds = GetVirtualScreen();
155 int handl = CSCIDrawWindow(ds, boxleft, boxtop, 200, 120);
156 int ctrlcancel =
157 CSCICreateControl(CNT_PUSHBUTTON | CNF_CANCEL, boxleft + 135, boxtop + 5 + buttonhit, 60, 10,
158 get_global_message(MSG_CANCEL));
159 int ctrllist = CSCICreateControl(CNT_LISTBOX, boxleft + 10, boxtop + 40, 120, 80, NULL);
160 int ctrltbox = 0;
161
162 CSCISendControlMessage(ctrllist, CLB_CLEAR, 0, 0); // clear the list box
163 preparesavegamelist(ctrllist);
164 if (toomanygames) {
165 strcpy(okbuttontext, get_global_message(MSG_REPLACE));
166 strcpy(labeltext, get_global_message(MSG_MUSTREPLACE));
167 labeltop = boxtop + 2;
168 } else
169 ctrltbox = CSCICreateControl(CNT_TEXTBOX, boxleft + 10, boxtop + 29, 120, 0, NULL);
170
171 int ctrlok = CSCICreateControl(CNT_PUSHBUTTON | CNF_DEFAULT, boxleft + 135, boxtop + 5, 60, 10, okbuttontext);
172 int ctrltex1 = CSCICreateControl(CNT_LABEL, boxleft + 10, labeltop, 120, 0, labeltext);
173 CSCIMessage mes;
174
175 lpTemp = NULL;
176 if (numsaves > 0)
177 CSCISendControlMessage(ctrllist, CLB_GETTEXT, 0, (long)&buffer2[0]);
178 else
179 buffer2[0] = 0;
180
181 CSCISendControlMessage(ctrltbox, CTB_SETTEXT, 0, (long)&buffer2[0]);
182
183 int toret = -1;
184 while (1) {
185 CSCIWaitMessage(ds, &mes); //printf("mess: %d, id %d ",mes.code,mes.id);
186 if (mes.code == CM_COMMAND) {
187 if (mes.id == ctrlok) {
188 int cursell = CSCISendControlMessage(ctrllist, CLB_GETCURSEL, 0, 0);
189 CSCISendControlMessage(ctrltbox, CTB_GETTEXT, 0, (long)&buffer2[0]);
190
191 if (numsaves > 0)
192 CSCISendControlMessage(ctrllist, CLB_GETTEXT, cursell, (long)&bufTemp[0]);
193 else
194 strcpy(bufTemp, "_NOSAVEGAMENAME");
195
196 if (toomanygames) {
197 int nwhand = CSCIDrawWindow(ds, boxleft + 5, boxtop + 20, 190, 65);
198 int lbl1 =
199 CSCICreateControl(CNT_LABEL, boxleft + 20, boxtop + 25, 160, 0, get_global_message(MSG_REPLACEWITH1));
200 int lbl2 = CSCICreateControl(CNT_LABEL, boxleft + 30, boxtop + 34, 160, 0, bufTemp);
201 int lbl3 =
202 CSCICreateControl(CNT_LABEL, boxleft + 20, boxtop + 45, 160, 0, get_global_message(MSG_REPLACEWITH2));
203 int txt1 = CSCICreateControl(CNT_TEXTBOX, boxleft + 20, boxtop + 55, 160, 0, bufTemp);
204 int btnOk =
205 CSCICreateControl(CNT_PUSHBUTTON | CNF_DEFAULT, boxleft + 30, boxtop + 70, 60, 10,
206 get_global_message(MSG_REPLACE));
207 int btnCancel =
208 CSCICreateControl(CNT_PUSHBUTTON | CNF_CANCEL, boxleft + 100, boxtop + 70, 60, 10,
209 get_global_message(MSG_CANCEL));
210
211 CSCIMessage cmes;
212 do {
213 CSCIWaitMessage(ds, &cmes);
214 } while (cmes.code != CM_COMMAND);
215
216 CSCISendControlMessage(txt1, CTB_GETTEXT, 0, (long)&buffer2[0]);
217 CSCIDeleteControl(btnCancel);
218 CSCIDeleteControl(btnOk);
219 CSCIDeleteControl(txt1);
220 CSCIDeleteControl(lbl3);
221 CSCIDeleteControl(lbl2);
222 CSCIDeleteControl(lbl1);
223 CSCIEraseWindow(ds, nwhand);
224 bufTemp[0] = 0;
225
226 if (cmes.id == btnCancel) {
227 lpTemp = NULL;
228 break;
229 } else
230 toret = filenumbers[cursell];
231
232 }
233 else if (strcmp(buffer2, bufTemp) != 0) { // create a new game (description different)
234 int highestnum = 0;
235 for (int pp = 0; pp < numsaves; pp++) {
236 if (filenumbers[pp] > highestnum)
237 highestnum = filenumbers[pp];
238 }
239
240 if (highestnum > 90)
241 quit("Save game directory overflow");
242
243 toret = highestnum + 1;
244 String path = get_save_game_path(toret);
245 strcpy(bufTemp, path);
246 }
247 else {
248 toret = filenumbers[cursell];
249 bufTemp[0] = 0;
250 }
251
252 if (bufTemp[0] == 0)
253 {
254 String path = get_save_game_path(toret);
255 strcpy(bufTemp, path);
256 }
257
258 lpTemp = &bufTemp[0];
259 lpTemp2 = &buffer2[0];
260 } else if (mes.id == ctrlcancel) {
261 lpTemp = NULL;
262 }
263 break;
264 } else if (mes.code == CM_SELCHANGE) {
265 int cursel = CSCISendControlMessage(ctrllist, CLB_GETCURSEL, 0, 0);
266 if (cursel >= 0) {
267 CSCISendControlMessage(ctrllist, CLB_GETTEXT, cursel, (long)&buffer2[0]);
268 CSCISendControlMessage(ctrltbox, CTB_SETTEXT, 0, (long)&buffer2[0]);
269 }
270 }
271 }
272
273 CSCIDeleteControl(ctrltbox);
274 CSCIDeleteControl(ctrltex1);
275 CSCIDeleteControl(ctrllist);
276 CSCIDeleteControl(ctrlok);
277 CSCIDeleteControl(ctrlcancel);
278 CSCIEraseWindow(ds, handl);
279 return toret;
280 }
281
preparesavegamelist(int ctrllist)282 void preparesavegamelist(int ctrllist)
283 {
284 numsaves = 0;
285 toomanygames = 0;
286 al_ffblk ffb;
287 int bufix = 0;
288 char curdir[255];
289 _getcwd(curdir, 255);
290
291 char searchPath[260];
292 sprintf(searchPath, "%s""agssave.*%s", saveGameDirectory, saveGameSuffix.GetCStr());
293
294 int don = al_findfirst(searchPath, &ffb, -1);
295 while (!don) {
296 bufix = 0;
297 if (numsaves >= MAXSAVEGAMES) {
298 toomanygames = 1;
299 break;
300 }
301
302 // only list games .000 to .099 (to allow higher slots for other purposes)
303 if (strstr(ffb.name, ".0") == NULL) {
304 don = al_findnext(&ffb);
305 continue;
306 }
307
308 const char *numberExtension = strstr(ffb.name, ".0") + 1;
309 int sgNumber = atoi(numberExtension);
310
311 String thisGamePath = get_save_game_path(sgNumber);
312
313 // get description
314 String description;
315 read_savedgame_description(thisGamePath, description);
316
317 CSCISendControlMessage(ctrllist, CLB_ADDITEM, 0, (long)description.GetCStr());
318 // Select the first item
319 CSCISendControlMessage(ctrllist, CLB_SETCURSEL, 0, 0);
320 filenumbers[numsaves] = sgNumber;
321 filedates[numsaves] = (long int)ffb.time;
322 numsaves++;
323 don = al_findnext(&ffb);
324 }
325
326 al_findclose(&ffb);
327 if (numsaves >= MAXSAVEGAMES)
328 toomanygames = 1;
329
330 for (int nn = 0; nn < numsaves - 1; nn++) {
331 for (int kk = 0; kk < numsaves - 1; kk++) { // Date order the games
332 if (filedates[kk] < filedates[kk + 1]) { // swap them round
333 CSCISendControlMessage(ctrllist, CLB_GETTEXT, kk, (long)&buff[0]);
334 CSCISendControlMessage(ctrllist, CLB_GETTEXT, kk + 1, (long)&buffer2[0]);
335 CSCISendControlMessage(ctrllist, CLB_SETTEXT, kk + 1, (long)&buff[0]);
336 CSCISendControlMessage(ctrllist, CLB_SETTEXT, kk, (long)&buffer2[0]);
337 int numtem = filenumbers[kk];
338 filenumbers[kk] = filenumbers[kk + 1];
339 filenumbers[kk + 1] = numtem;
340 long numted = filedates[kk];
341 filedates[kk] = filedates[kk + 1];
342 filedates[kk + 1] = numted;
343 }
344 }
345 }
346 }
347
enterstringwindow(const char * prompttext,char * stouse)348 void enterstringwindow(const char *prompttext, char *stouse)
349 {
350 int boxleft = 60, boxtop = 80;
351 int wantCancel = 0;
352 if (prompttext[0] == '!') {
353 wantCancel = 1;
354 prompttext++;
355 }
356 Bitmap *ds = GetVirtualScreen();
357 int handl = CSCIDrawWindow(ds, boxleft, boxtop, 200, 40);
358 int ctrlok = CSCICreateControl(CNT_PUSHBUTTON | CNF_DEFAULT, boxleft + 135, boxtop + 5, 60, 10, "OK");
359 int ctrlcancel = -1;
360 if (wantCancel)
361 ctrlcancel = CSCICreateControl(CNT_PUSHBUTTON | CNF_CANCEL, boxleft + 135, boxtop + 20, 60, 10, get_global_message(MSG_CANCEL));
362 int ctrltbox = CSCICreateControl(CNT_TEXTBOX, boxleft + 10, boxtop + 29, 120, 0, NULL);
363 int ctrltex1 = CSCICreateControl(CNT_LABEL, boxleft + 10, boxtop + 5, 120, 0, prompttext);
364 CSCIMessage mes;
365
366 while (1) {
367 CSCIWaitMessage(ds, &mes);
368 if (mes.code == CM_COMMAND) {
369 if (mes.id == ctrlcancel)
370 buffer2[0] = 0;
371 else
372 CSCISendControlMessage(ctrltbox, CTB_GETTEXT, 0, (long)&buffer2[0]);
373 break;
374 }
375 }
376
377 CSCIDeleteControl(ctrltex1);
378 CSCIDeleteControl(ctrltbox);
379 CSCIDeleteControl(ctrlok);
380 if (wantCancel)
381 CSCIDeleteControl(ctrlcancel);
382 CSCIEraseWindow(ds, handl);
383 strcpy(stouse, buffer2);
384 }
385
enternumberwindow(char * prompttext)386 int enternumberwindow(char *prompttext)
387 {
388 char ourbuf[200];
389 enterstringwindow(prompttext, ourbuf);
390 if (ourbuf[0] == 0)
391 return -9999;
392 return atoi(ourbuf);
393 }
394
roomSelectorWindow(int currentRoom,int numRooms,int * roomNumbers,char ** roomNames)395 int roomSelectorWindow(int currentRoom, int numRooms, int*roomNumbers, char**roomNames)
396 {
397 char labeltext[200];
398 strcpy(labeltext, get_global_message(MSG_SAVEDIALOG));
399 int boxleft = myscrnwid / 2 - 120;
400 int boxtop = myscrnhit / 2 - 80;
401 int labeltop = boxtop + 5;
402 Bitmap *ds = GetVirtualScreen();
403 int handl = CSCIDrawWindow(ds, boxleft, boxtop, 240, 160);
404 int ctrllist = CSCICreateControl(CNT_LISTBOX, boxleft + 10, boxtop + 40, 220, 100, NULL);
405 int ctrlcancel =
406 CSCICreateControl(CNT_PUSHBUTTON | CNF_CANCEL, boxleft + 80, boxtop + 145, 60, 10, "Cancel");
407
408 CSCISendControlMessage(ctrllist, CLB_CLEAR, 0, 0); // clear the list box
409 for (int aa = 0; aa < numRooms; aa++)
410 {
411 sprintf(buff, "%3d %s", roomNumbers[aa], roomNames[aa]);
412 CSCISendControlMessage(ctrllist, CLB_ADDITEM, 0, (long)&buff[0]);
413 if (roomNumbers[aa] == currentRoom)
414 {
415 CSCISendControlMessage(ctrllist, CLB_SETCURSEL, aa, 0);
416 }
417 }
418
419 int ctrlok = CSCICreateControl(CNT_PUSHBUTTON | CNF_DEFAULT, boxleft + 10, boxtop + 145, 60, 10, "OK");
420 int ctrltex1 = CSCICreateControl(CNT_LABEL, boxleft + 10, labeltop, 180, 0, "Choose which room to go to:");
421 CSCIMessage mes;
422
423 lpTemp = NULL;
424 buffer2[0] = 0;
425
426 int ctrltbox = CSCICreateControl(CNT_TEXTBOX, boxleft + 10, boxtop + 29, 120, 0, NULL);
427 CSCISendControlMessage(ctrltbox, CTB_SETTEXT, 0, (long)&buffer2[0]);
428
429 int toret = -1;
430 while (1) {
431 CSCIWaitMessage(ds, &mes); //printf("mess: %d, id %d ",mes.code,mes.id);
432 if (mes.code == CM_COMMAND)
433 {
434 if (mes.id == ctrlok)
435 {
436 CSCISendControlMessage(ctrltbox, CTB_GETTEXT, 0, (long)&buffer2[0]);
437 if (isdigit(buffer2[0]))
438 {
439 toret = atoi(buffer2);
440 }
441 }
442 else if (mes.id == ctrlcancel)
443 {
444 }
445 break;
446 }
447 else if (mes.code == CM_SELCHANGE)
448 {
449 int cursel = CSCISendControlMessage(ctrllist, CLB_GETCURSEL, 0, 0);
450 if (cursel >= 0)
451 {
452 sprintf(buffer2, "%d", roomNumbers[cursel]);
453 CSCISendControlMessage(ctrltbox, CTB_SETTEXT, 0, (long)&buffer2[0]);
454 }
455 }
456 }
457
458 CSCIDeleteControl(ctrltbox);
459 CSCIDeleteControl(ctrltex1);
460 CSCIDeleteControl(ctrllist);
461 CSCIDeleteControl(ctrlok);
462 CSCIDeleteControl(ctrlcancel);
463 CSCIEraseWindow(ds, handl);
464 return toret;
465 }
466
myscimessagebox(const char * lpprompt,char * btn1,char * btn2)467 int myscimessagebox(const char *lpprompt, char *btn1, char *btn2)
468 {
469 Bitmap *ds = GetVirtualScreen();
470 int windl = CSCIDrawWindow(ds, 80, 80, 240 - 80, 120 - 80);
471 int lbl1 = CSCICreateControl(CNT_LABEL, 90, 85, 150, 0, lpprompt);
472 int btflag = CNT_PUSHBUTTON;
473
474 if (btn2 == NULL)
475 btflag |= CNF_DEFAULT | CNF_CANCEL;
476 else
477 btflag |= CNF_DEFAULT;
478
479 int btnQuit = CSCICreateControl(btflag, 90, 105, 60, 10, btn1);
480 int btnPlay = 0;
481
482 if (btn2 != NULL)
483 btnPlay = CSCICreateControl(CNT_PUSHBUTTON | CNF_CANCEL, 165, 105, 60, 10, btn2);
484
485 smes.code = 0;
486
487 do {
488 CSCIWaitMessage(ds, &smes);
489 } while (smes.code != CM_COMMAND);
490
491 if (btnPlay)
492 CSCIDeleteControl(btnPlay);
493
494 CSCIDeleteControl(btnQuit);
495 CSCIDeleteControl(lbl1);
496 CSCIEraseWindow(ds, windl);
497
498 if (smes.id == btnQuit)
499 return 1;
500
501 return 0;
502 }
503
quitdialog()504 int quitdialog()
505 {
506 char quitbut[50], playbut[50];
507 strcpy(quitbut, get_global_message(MSG_QUITBUTTON));
508 strcpy(playbut, get_global_message(MSG_PLAYBUTTON));
509 return myscimessagebox(get_global_message(MSG_QUITDIALOG), quitbut, playbut);
510 }
511