00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 # include <config.h>
00021 #endif
00022
00023 #ifndef ALPHA_LINUX_CXX
00024 # include <cstring>
00025 # include <ctime>
00026 #endif
00027
00028 #include "exult_flx.h"
00029
00030 #include "Audio.h"
00031 #include "Configuration.h"
00032 #include "Gump_button.h"
00033 #include "Newfile_gump.h"
00034 #include "Yesno_gump.h"
00035 #include "actors.h"
00036 #include "exult.h"
00037 #include "game.h"
00038 #include "gameclk.h"
00039 #include "gamewin.h"
00040 #include "listfiles.h"
00041 #include "mouse.h"
00042 #include "party.h"
00043 #include "Text_button.h"
00044
00045 #ifndef UNDER_CE
00046 using std::atoi;
00047 using std::cout;
00048 using std::endl;
00049 using std::isdigit;
00050 using std::memcpy;
00051 using std::memset;
00052 using std::memmove;
00053 using std::qsort;
00054 using std::string;
00055 using std::strlen;
00056 using std::strncpy;
00057 using std::strcpy;
00058 using std::strcat;
00059 using std::time_t;
00060 using std::tm;
00061 #endif
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 const short Newfile_gump::btn_rows[5] = {186, 2, 15, 158, 171};
00072 const short Newfile_gump::btn_cols[5] = {2, 46, 88, 150, 210};
00073
00074
00075 const short Newfile_gump::fieldx = 2;
00076 const short Newfile_gump::fieldy = 2;
00077 const short Newfile_gump::fieldw = 207;
00078 const short Newfile_gump::fieldh = 12;
00079 const short Newfile_gump::fieldgap = 1;
00080 const short Newfile_gump::fieldcount = 14;
00081 const short Newfile_gump::textx = 12;
00082 const short Newfile_gump::texty = 2;
00083 const short Newfile_gump::textw = 190;
00084 const short Newfile_gump::iconx = 2;
00085 const short Newfile_gump::icony = 2;
00086
00087
00088 const short Newfile_gump::scrollx = 212;
00089 const short Newfile_gump::scrolly = 28;
00090 const short Newfile_gump::scrollh = 129;
00091 const short Newfile_gump::sliderw = 7;
00092 const short Newfile_gump::sliderh = 7;
00093
00094 const short Newfile_gump::infox = 224;
00095 const short Newfile_gump::infoy = 67;
00096 const short Newfile_gump::infow = 92;
00097 const short Newfile_gump::infoh = 79;
00098 const char Newfile_gump::infostring[] = "Avatar: %s\n"
00099 "Exp: %i Hp: %i\n"
00100 "Str: %i Dxt: %i\n"
00101 "Int: %i Trn: %i\n"
00102 "\n"
00103 "Game Day: %i\n"
00104 "Game Time: %02i:%02i\n"
00105 "\n"
00106 "Save Count: %i\n"
00107 "Date: %i%s %s %04i\n"
00108 "Time: %02i:%02i";
00109
00110 const char *Newfile_gump::months[12] = {"Jan",
00111 "Feb",
00112 "March",
00113 "April",
00114 "May",
00115 "June",
00116 "July",
00117 "Aug",
00118 "Sept",
00119 "Oct",
00120 "Nov",
00121 "Dec" };
00122
00123 static const char *loadtext = "LOAD";
00124 static const char *savetext = "SAVE";
00125 static const char *deletetext = "DELETE";
00126 static const char *canceltext = "CANCEL";
00127
00128 #ifdef UNDER_CE
00129 struct tm * __cdecl localtime(const time_t *it)
00130 {
00131 static tm t;
00132 memset(&t,0,sizeof(t));
00133
00134 SYSTEMTIME systime;
00135 FILETIME filetime;
00136 FILETIME local_filetime;
00137 LONGLONG time;
00138
00139 SYSTEMTIME systime_1970;
00140 FILETIME filetime_1970;
00141 LONGLONG time_1970;
00142
00143 systime_1970.wYear = 1970;
00144 systime_1970.wMonth = 1;
00145 systime_1970.wDay = 1;
00146 systime_1970.wHour = 0;
00147 systime_1970.wMinute = 0;
00148 systime_1970.wSecond = 0;
00149 systime_1970.wMilliseconds = 0;
00150 SystemTimeToFileTime(&systime_1970, &filetime_1970);
00151 memcpy(&time_1970, &filetime_1970, 8);
00152
00153
00154 time = *it;
00155 time *= 10000000;
00156 time += time_1970;
00157
00158 memcpy(&filetime, &time, 8);
00159 FileTimeToLocalFileTime(&filetime, &local_filetime);
00160 FileTimeToSystemTime(&local_filetime, &systime);
00161
00162 t.tm_sec = systime.wSecond;
00163 t.tm_min = systime.wMinute;
00164 t.tm_hour = systime.wHour;
00165 t.tm_isdst = 0;
00166 t.tm_wday = systime.wDayOfWeek;
00167 t.tm_mday = systime.wDay;
00168 t.tm_mon = systime.wMonth - 1;
00169 t.tm_yday = 0;
00170 t.tm_year = systime.wYear - 1900;
00171
00172 return &t;
00173 }
00174
00175 time_t __cdecl time(time_t *t)
00176 {
00177 SYSTEMTIME systime;
00178 FILETIME filetime;
00179 LONGLONG time;
00180
00181 SYSTEMTIME systime_1970;
00182 FILETIME filetime_1970;
00183 LONGLONG time_1970;
00184
00185 GetSystemTime(&systime);
00186 SystemTimeToFileTime(&systime, &filetime);
00187 memcpy(&time, &filetime, 8);
00188
00189 systime_1970.wYear = 1970;
00190 systime_1970.wMonth = 1;
00191 systime_1970.wDay = 1;
00192 systime_1970.wHour = 0;
00193 systime_1970.wMinute = 0;
00194 systime_1970.wSecond = 0;
00195 systime_1970.wMilliseconds = 0;
00196 SystemTimeToFileTime(&systime_1970, &filetime_1970);
00197 memcpy(&time_1970, &filetime_1970, 8);
00198
00199
00200 time -= time_1970;
00201 if (time < 0) time = 0;
00202
00203
00204 time /= 10000000;
00205
00206 if (t) *t = time;
00207
00208 return time;
00209 }
00210 #endif
00211
00212
00213
00214
00215
00216 class Newfile_button : public Gump_button
00217 {
00218 public:
00219 Newfile_button(Gump *par, int px, int py, int shapenum)
00220 : Gump_button(par, shapenum, px, py, SF_EXULT_FLX)
00221 { }
00222
00223 virtual void activate();
00224 };
00225
00226 class Newfile_Textbutton : public Text_button
00227 {
00228 public:
00229 Newfile_Textbutton(Gump *par, string text, int px, int py, int width)
00230 : Text_button(par, text, px, py, width)
00231 { }
00232
00233 virtual void activate();
00234 };
00235
00236
00237
00238
00239
00240 void Newfile_button::activate
00241 (
00242 )
00243 {
00244 int shapenum = get_shapenum();
00245 if (shapenum == EXULT_FLX_SAV_DOWNDOWN_SHP)
00246 ((Newfile_gump *) parent)->scroll_page(1);
00247 else if (shapenum == EXULT_FLX_SAV_DOWN_SHP)
00248 ((Newfile_gump *) parent)->scroll_line(1);
00249 else if (shapenum == EXULT_FLX_SAV_UP_SHP)
00250 ((Newfile_gump *) parent)->scroll_line(-1);
00251 else if (shapenum == EXULT_FLX_SAV_UPUP_SHP)
00252 ((Newfile_gump *) parent)->scroll_page(-1);
00253 }
00254
00255 void Newfile_Textbutton::activate()
00256 {
00257 if (text == loadtext)
00258 ((Newfile_gump *) parent)->load();
00259 else if (text == savetext)
00260 ((Newfile_gump *) parent)->save();
00261 else if (text == deletetext)
00262 ((Newfile_gump *) parent)->delete_file();
00263 else if (text == canceltext)
00264 parent->close();
00265 }
00266
00267
00268
00269
00270
00271
00272 Newfile_gump::Newfile_gump
00273 (
00274 ) : Modal_gump(0, gwin->get_width()/2-160,
00275 gwin->get_height()/2-100,
00276 EXULT_FLX_SAVEGUMP_SHP, SF_EXULT_FLX),
00277 restored(0), games(0), num_games(0), first_free(0),
00278 cur_shot(0), cur_details(0), cur_party(0),
00279 gd_shot(0), gd_details(0), gd_party(0),
00280 screenshot(0), details(0), party(0), is_readable(false), filename(0),
00281 list_position(-2), selected(-3), cursor(0), slide_start(-1)
00282
00283 {
00284 set_object_area(Rectangle(0,0,320,200), -22, 190);
00285
00286 newname[0] = 0;
00287
00288 gwin->get_tqueue()->pause(SDL_GetTicks());
00289 back = gwin->get_win()->create_buffer(gwin->get_width(), gwin->get_height());
00290 gwin->get_win()->get(back, 0, 0);
00291
00292
00293 buttons[0] = buttons[1] = buttons[2] = 0;
00294
00295
00296 buttons[3] = new Newfile_Textbutton(this, canceltext,
00297 btn_cols[3], btn_rows[0], 59);
00298
00299
00300 buttons[4] = new Newfile_button(this, btn_cols[4], btn_rows[1], EXULT_FLX_SAV_UPUP_SHP);
00301 buttons[5] = new Newfile_button(this, btn_cols[4], btn_rows[2], EXULT_FLX_SAV_UP_SHP);
00302 buttons[6] = new Newfile_button(this, btn_cols[4], btn_rows[3], EXULT_FLX_SAV_DOWN_SHP);
00303 buttons[7] = new Newfile_button(this, btn_cols[4], btn_rows[4], EXULT_FLX_SAV_DOWNDOWN_SHP);
00304
00305 LoadSaveGameDetails();
00306 }
00307
00308
00309
00310
00311
00312 Newfile_gump::~Newfile_gump
00313 (
00314 )
00315 {
00316 gwin->get_tqueue()->resume(SDL_GetTicks());
00317 size_t i;
00318 for (i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++)
00319 delete buttons[i];
00320
00321 FreeSaveGameDetails();
00322
00323 delete back;
00324 }
00325
00326
00327
00328
00329
00330 void Newfile_gump::load()
00331 {
00332
00333 if (selected == -2 || selected == -3)
00334 return;
00335
00336
00337
00338 if (selected != -1) gwin->restore_gamedat(games[selected].num);
00339
00340
00341 gwin->read();
00342
00343
00344 done = true;
00345 restored = 1;
00346
00347
00348 selected = -3;
00349
00350 delete buttons[0];
00351 buttons[0] = 0;
00352 delete buttons[1];
00353 buttons[1] = 0;
00354 delete buttons[2];
00355 buttons[2] = 0;
00356
00357
00358
00359
00360
00361
00362 }
00363
00364
00365
00366
00367
00368 void Newfile_gump::save()
00369 {
00370
00371 if (!strlen(newname) || selected == -3)
00372 return;
00373
00374
00375
00376 if (selected != -2) if (!Yesno_gump::ask("Okay to write over existing saved game?"))
00377 return;
00378
00379
00380 gwin->write();
00381
00382
00383 if (selected >= 0) gwin->save_gamedat(games[selected].num, newname);
00384 else if (selected == -2) gwin->save_gamedat(first_free, newname);
00385
00386 cout << "Saved game #" << selected << " successfully." << endl;
00387
00388
00389 selected = -3;
00390
00391 delete buttons[0];
00392 buttons[0] = 0;
00393 delete buttons[1];
00394 buttons[1] = 0;
00395 delete buttons[2];
00396 buttons[2] = 0;
00397
00398 FreeSaveGameDetails();
00399 LoadSaveGameDetails();
00400 paint();
00401 gwin->set_painted();
00402 }
00403
00404
00405
00406
00407
00408 void Newfile_gump::delete_file()
00409 {
00410
00411 if (selected == -1 || selected == -2 || selected == -3)
00412 return;
00413
00414
00415
00416 if (!Yesno_gump::ask("Okay to delete saved game?"))
00417 return;
00418
00419 U7remove (games[selected].filename);
00420 filename = 0;
00421 is_readable = false;
00422
00423 cout << "Deleted Save game #" << selected << " (" << games[selected].filename << ") successfully." << endl;
00424
00425
00426 selected = -3;
00427
00428 delete buttons[0];
00429 buttons[0] = 0;
00430 delete buttons[1];
00431 buttons[1] = 0;
00432 delete buttons[2];
00433 buttons[2] = 0;
00434
00435 FreeSaveGameDetails();
00436 LoadSaveGameDetails();
00437 paint();
00438 gwin->set_painted();
00439 }
00440
00441
00442
00443
00444
00445 void Newfile_gump::scroll_line(int dir)
00446 {
00447 list_position += dir;
00448
00449 if (list_position > num_games-fieldcount)
00450 list_position = num_games-fieldcount;
00451
00452 if (list_position < -2)
00453 list_position = -2;
00454
00455 #ifdef DEBUG
00456 cout << "New list position " << list_position << endl;
00457 #endif
00458
00459 paint();
00460 gwin->set_painted();
00461 }
00462
00463
00464
00465
00466
00467 void Newfile_gump::scroll_page(int dir)
00468 {
00469 scroll_line (dir * fieldcount);
00470 }
00471
00472 void Newfile_gump::PaintSaveName (int line)
00473 {
00474
00475 int actual_game = line+list_position;
00476
00477 if (actual_game < -2 || actual_game >= num_games) return;
00478
00479 char *text;
00480
00481 if (actual_game == -1)
00482 text = "Quick Save";
00483 else if (actual_game == -2 && selected != -2)
00484 text = "Empty Slot";
00485 else if (actual_game != selected || buttons[0])
00486 text = games[actual_game].savename;
00487 else
00488 text = newname;
00489
00490 sman->paint_text (2, text,
00491 x + fieldx + textx,
00492 y + fieldy + texty + line*(fieldh + fieldgap));
00493
00494
00495 if (selected == actual_game && cursor != -1)
00496 gwin->get_win()->fill8(0, 1, sman->get_text_height(2),
00497 x + fieldx + textx + sman->get_text_width(2, text, cursor),
00498 y + fieldy + texty + line*(fieldh + fieldgap));
00499
00500
00501 if (selected == actual_game)
00502 {
00503 ShapeID icon (EXULT_FLX_SAV_SELECTED_SHP, 0, SF_EXULT_FLX);
00504 icon.paint_shape ( x+fieldx+iconx,
00505 y+fieldy+icony+line*(fieldh+fieldgap));
00506 }
00507
00508 }
00509
00510
00511
00512
00513
00514
00515 void Newfile_gump::paint
00516 (
00517 )
00518 {
00519 if (!games)
00520 return;
00521 Gump::paint();
00522
00523
00524 int i;
00525
00526 for (i = 0; i < fieldcount; i++)
00527 PaintSaveName (i);
00528
00529
00530 for (i = 0; i < 8; i++) if (buttons[i])
00531 buttons[i]->paint();
00532
00533
00534
00535
00536 int num_pos = (2+num_games)-fieldcount;
00537 if (num_pos < 1) num_pos = 1;
00538
00539
00540 int pos = ((scrollh-sliderh)*(list_position+2))/num_pos;
00541
00542 ShapeID slider_shape(EXULT_FLX_SAV_SLIDER_SHP, 0, SF_EXULT_FLX);
00543 slider_shape.paint_shape(x+scrollx , y+scrolly+pos);
00544
00545
00546 if (screenshot)
00547 sman->paint_shape(x + 222, y + 2, screenshot->get_frame(0));
00548
00549
00550 if (party && party[0].shape_file == SF_BG_SISHAPES_VGA &&
00551 !sman->can_use_multiracial())
00552 {
00553 party[0].shape_file = SF_SHAPES_VGA;
00554
00555
00556 if (party[0].shape %2) party[0].shape = 989;
00557 else party[0].shape = 721;
00558 }
00559
00560 if (details && party)
00561 {
00562 int i;
00563
00564 for (i=0; i<4 && i<details->party_size; i++)
00565 {
00566 ShapeID shape(party[i].shape, 16, (ShapeFile) party[i].shape_file);
00567 shape.paint_shape(x + 249 + i*23, y + 169);
00568 }
00569
00570 for (i=4; i<8 && i<details->party_size; i++)
00571 {
00572 ShapeID shape(party[i].shape, 16, (ShapeFile) party[i].shape_file);
00573 shape.paint_shape(x + 249 + (i-4)*23, y + 198);
00574 }
00575
00576 char info[320];
00577
00578 char *suffix = "th";
00579
00580 if ((details->real_day%10) == 1 && details->real_day != 11)
00581 suffix = "st";
00582 else if ((details->real_day%10) == 2 && details->real_day != 12)
00583 suffix = "nd";
00584 else if ((details->real_day%10) == 3 && details->real_day != 13)
00585 suffix = "rd";
00586
00587 snprintf (info, 320, infostring, party[0].name,
00588 party[0].exp, party[0].health,
00589 party[0].str, party[0].dext,
00590 party[0].intel, party[0].training,
00591 details->game_day, details->game_hour, details->game_minute,
00592 details->save_count,
00593 details->real_day, suffix, months[details->real_month-1], details->real_year,
00594 details->real_hour, details->real_minute);
00595
00596 if (filename)
00597 {
00598 std::strncat (info, "\nFile: ", 320);
00599
00600 int offset = strlen(filename);
00601
00602 while (offset--)
00603 {
00604 if (filename[offset] == '/' || filename[offset] == '\\')
00605 {
00606 offset++;
00607 break;
00608 }
00609 }
00610 std::strncat (info, filename+offset, 320);
00611
00612 }
00613
00614 sman->paint_text_box (4, info, x+infox, y+infoy, infow, infoh);
00615
00616 }
00617 else
00618 {
00619 if (filename)
00620 {
00621 char info[64] = {0};
00622
00623 std::strncat (info, "File: ", 64);
00624
00625 int offset = strlen(filename);
00626
00627 while (offset--)
00628 {
00629 if (filename[offset] == '/' || filename[offset] == '\\')
00630 {
00631 offset++;
00632 break;
00633 }
00634 }
00635 std::strncat (info, filename+offset, 64);
00636 sman->paint_text_box (4, info, x+infox, y+infoy, infow, infoh);
00637
00638 }
00639
00640 if (!is_readable)
00641 {
00642 sman->paint_text (2, "Unreadable", x+infox+(infow-sman->get_text_width(2, "Unreadable"))/2, y+infoy+(infoh-18)/2);
00643 sman->paint_text (2, "Savegame", x+infox+(infow-sman->get_text_width(2, "Savegame"))/2, y+infoy+(infoh)/2);
00644 }
00645 else
00646 {
00647 sman->paint_text (4, "No Info", x+infox+(infow-sman->get_text_width(4, "No Info"))/2, y+infoy+(infoh-sman->get_text_height(4))/2);
00648 }
00649 }
00650 gwin->set_painted();
00651 }
00652
00653
00654
00655
00656
00657 void Newfile_gump::mouse_down
00658 (
00659 int mx, int my
00660 )
00661 {
00662 slide_start = -1;
00663
00664 pushed = Gump::on_button(mx, my);
00665
00666 if (!pushed) for (size_t i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++)
00667 if (buttons[i] && buttons[i]->on_button(mx, my))
00668 {
00669 pushed = buttons[i];
00670 break;
00671 }
00672
00673 if (pushed)
00674 {
00675 pushed->push();
00676 return;
00677 }
00678
00679 int gx = mx - x;
00680 int gy = my - y;
00681
00682
00683 if (gx >= scrollx && gx < scrollx+sliderw && gy >= scrolly && gy < scrolly+scrollh)
00684 {
00685 int num_pos = (2+num_games)-fieldcount;
00686 if (num_pos < 1) num_pos = 1;
00687
00688
00689 int pos = ((scrollh-sliderh)*(list_position+2))/num_pos;
00690
00691
00692 if (gy < pos+scrolly)
00693 {
00694 scroll_page(-1);
00695 paint();
00696 return;
00697 }
00698
00699 else if (gy >= pos+scrolly+sliderh)
00700 {
00701 scroll_page(1);
00702 paint();
00703 return;
00704 }
00705
00706 else
00707 {
00708 slide_start = gy;
00709 return;
00710 }
00711 }
00712
00713
00714
00715 if (gx < fieldx || gx >= fieldx+fieldw)
00716 return;
00717
00718 int hit = -1;
00719 int i;
00720 for (i = 0; i < fieldcount; i++)
00721 {
00722 int fy = fieldy + i*(fieldh + fieldgap);
00723 if (gy >= fy && gy < fy+fieldh)
00724 {
00725 hit = i;
00726 break;
00727 }
00728 }
00729
00730 if (hit == -1) return;
00731
00732 if (hit+list_position >= num_games || hit+list_position < -2 || selected == hit+list_position) return;
00733
00734 #ifdef DEBUG
00735 cout << "Hit a save game field" << endl;
00736 #endif
00737 selected = hit+list_position;
00738
00739 int want_load = true;
00740 int want_delete = true;
00741 int want_save = true;
00742
00743 if (selected == -2)
00744 {
00745 want_load = false;
00746 want_delete = false;
00747 want_save = false;
00748 screenshot = cur_shot;
00749 details = cur_details;
00750 party = cur_party;
00751 newname[0] = 0;
00752 cursor = 0;
00753 is_readable = true;
00754 filename = 0;
00755 }
00756 else if (selected == -1)
00757 {
00758 want_delete = false;
00759 screenshot = gd_shot;
00760 details = gd_details;
00761 party = gd_party;
00762 strcpy (newname, "Quick Save");
00763 cursor = -1;
00764 is_readable = true;
00765 filename = 0;
00766 }
00767 else
00768 {
00769 screenshot = games[selected].screenshot;
00770 details = games[selected].details;
00771 party = games[selected].party;
00772 strcpy (newname, games[selected].savename);
00773 cursor = strlen (newname);
00774 is_readable = want_load = games[selected].readable;
00775 filename = games[selected].filename;
00776 }
00777
00778 if (!buttons[0] && want_load)
00779 buttons[0] = new Newfile_Textbutton(this, loadtext,
00780 btn_cols[1], btn_rows[0], 39);
00781 else if (buttons[0] && !want_load)
00782 {
00783 delete buttons[0];
00784 buttons[0] = 0;
00785 }
00786
00787 if (!buttons[1] && want_save)
00788 buttons[1] = new Newfile_Textbutton(this, savetext,
00789 btn_cols[0], btn_rows[0], 40);
00790 else if (buttons[1] && !want_save)
00791 {
00792 delete buttons[1];
00793 buttons[1] = 0;
00794 }
00795
00796 if (!buttons[2] && want_delete)
00797 buttons[2] = new Newfile_Textbutton(this, deletetext,
00798 btn_cols[2], btn_rows[0], 59);
00799 else if (buttons[2] && !want_delete)
00800 {
00801 delete buttons[2];
00802 buttons[2] = 0;
00803 }
00804
00805 paint();
00806 gwin->set_painted();
00807
00808 }
00809
00810
00811
00812
00813
00814 void Newfile_gump::mouse_up
00815 (
00816 int mx, int my
00817 )
00818 {
00819 slide_start = -1;
00820
00821 if (pushed)
00822 {
00823 pushed->unpush();
00824 if (pushed->on_button(mx, my))
00825 pushed->activate();
00826 pushed = 0;
00827 }
00828 }
00829
00830 void Newfile_gump::mousewheel_up()
00831 {
00832 SDLMod mod = SDL_GetModState();
00833 if (mod & KMOD_ALT)
00834 scroll_page(-1);
00835 else
00836 scroll_line(-1);
00837 }
00838
00839 void Newfile_gump::mousewheel_down()
00840 {
00841 SDLMod mod = SDL_GetModState();
00842 if (mod & KMOD_ALT)
00843 scroll_page(1);
00844 else
00845 scroll_line(1);
00846 }
00847
00848
00849
00850
00851
00852 void Newfile_gump::mouse_drag
00853 (
00854 int mx, int my
00855 )
00856 {
00857
00858 if (slide_start == -1) return;
00859
00860 int gx = mx - x;
00861 int gy = my - y;
00862
00863
00864
00865 int sy = gy - scrolly;
00866 if (gx < scrollx-20 || gx > scrollx+sliderw+20)
00867 sy = slide_start - scrolly;
00868
00869 if (sy < sliderh/2) sy = sliderh/2;
00870 if (sy > scrollh-sliderh/2) sy = scrollh-sliderh/2;
00871 sy -= sliderh/2;
00872
00873
00874 int num_pos = (2+num_games)-fieldcount;
00875
00876
00877 if (num_pos < 1) return;
00878
00879
00880 int new_pos = ((sy*num_pos*2)/(scrollh-sliderh)+1)/2-2;
00881
00882 if (new_pos != list_position)
00883 {
00884 list_position = new_pos;
00885 paint();
00886 }
00887 }
00888
00889
00890
00891
00892
00893 void Newfile_gump::text_input(int chr, int unicode)
00894 {
00895 bool update_details = false;
00896 int repaint = false;
00897
00898
00899 if (selected == -3)
00900 return;
00901
00902
00903 switch (chr) {
00904
00905 case SDLK_RETURN:
00906 if (!buttons[0] && buttons[1])
00907 {
00908 buttons[1]->push();
00909 gwin->show(1);
00910 buttons[1]->unpush();
00911 gwin->show(1);
00912 buttons[1]->activate();
00913 }
00914 update_details = true;
00915 break;
00916
00917 case SDLK_BACKSPACE:
00918 if (BackspacePressed())
00919 {
00920
00921 delete buttons[0];
00922 delete buttons[2];
00923 buttons[0] = buttons[2] = 0;
00924
00925
00926 if (!newname[0])
00927 {
00928 delete buttons[1];
00929 buttons[1] = 0;
00930 }
00931 update_details = true;
00932 }
00933 break;
00934
00935 case SDLK_DELETE:
00936 if (DeletePressed())
00937 {
00938
00939 delete buttons[0];
00940 delete buttons[2];
00941 buttons[0] = buttons[2] = 0;
00942
00943
00944 if (!newname[0])
00945 {
00946 delete buttons[1];
00947 buttons[1] = 0;
00948 }
00949 update_details = true;
00950 }
00951 break;
00952
00953 case SDLK_LEFT:
00954 repaint = MoveCursor(-1);
00955 break;
00956
00957 case SDLK_RIGHT:
00958 repaint = MoveCursor(1);
00959 break;
00960
00961 case SDLK_HOME:
00962 repaint = MoveCursor(-MAX_SAVEGAME_NAME_LEN);
00963 break;
00964
00965 case SDLK_END:
00966 repaint = MoveCursor(MAX_SAVEGAME_NAME_LEN);
00967 break;
00968
00969 default:
00970
00971 if ((unicode & 0xFF80) == 0 )
00972 chr = unicode & 0x7F;
00973 else
00974 chr = 0;
00975
00976 if (chr < ' ')
00977 return;
00978
00979 if (chr < 256 && isascii(chr))
00980 {
00981 if (AddCharacter (chr))
00982 {
00983
00984 if (newname[0] && !buttons[1])
00985 {
00986 buttons[1] = new Newfile_Textbutton(this, savetext,
00987 btn_cols[0],
00988 btn_rows[0], 40);
00989 buttons[1]->paint();
00990 }
00991
00992
00993 if (buttons[0] || buttons[2])
00994 {
00995 delete buttons[0];
00996 delete buttons[2];
00997 buttons[0] = buttons[2] = 0;
00998 }
00999 update_details = true;
01000 }
01001 }
01002 break;
01003 }
01004
01005
01006 if (update_details)
01007 {
01008 screenshot = cur_shot;
01009 details = cur_details;
01010 party = cur_party;
01011 repaint = true;
01012 }
01013 if (repaint)
01014 {
01015 paint();
01016 gwin->set_painted();
01017 }
01018 }
01019
01020 int Newfile_gump::BackspacePressed()
01021 {
01022 if (cursor == -1 || cursor == 0) return 0;
01023 cursor--;
01024 return DeletePressed();
01025 }
01026 int Newfile_gump::DeletePressed()
01027 {
01028 if (cursor == -1 || cursor == strlen (newname)) return 0;
01029 for (int i = cursor; i < strlen (newname); i++)
01030 newname[i] = newname[i+1];
01031
01032 return 1;
01033 }
01034 int Newfile_gump::MoveCursor(int count)
01035 {
01036 if (cursor == -1) return 0;
01037
01038 cursor += count;
01039 if (cursor < 0) cursor = 0;
01040 if (cursor > strlen (newname)) cursor = strlen (newname);
01041
01042 return 1;
01043 }
01044 int Newfile_gump::AddCharacter(char c)
01045 {
01046 if (cursor == -1 || cursor == MAX_SAVEGAME_NAME_LEN-1) return 0;
01047
01048 char text[MAX_SAVEGAME_NAME_LEN];
01049
01050 strcpy (text, newname);
01051 text[cursor+1] = 0;
01052 text[cursor] = c;
01053 strcat (text, newname+cursor);
01054
01055
01056 if (sman->get_text_width(2, text) >= textw)
01057 return 0;
01058
01059 cursor++;
01060 strcpy (newname, text);
01061 return 1;
01062 }
01063
01064 void Newfile_gump::LoadSaveGameDetails()
01065 {
01066 int i;
01067
01068
01069
01070 gwin->get_saveinfo(gd_shot, gd_details, gd_party);
01071
01072
01073 cur_shot = gwin->create_mini_screenshot();
01074
01075
01076 cur_details = new SaveGame_Details;
01077 memset (cur_details, 0, sizeof(SaveGame_Details));
01078
01079 gwin->get_win()->put(back, 0, 0);
01080
01081 if (gd_details) cur_details->save_count = gd_details->save_count;
01082 else cur_details->save_count = 0;
01083
01084 cur_details->party_size = partyman->get_count()+1;
01085 cur_details->game_day = gclock->get_total_hours() / 24;;
01086 cur_details->game_hour = gclock->get_hour();
01087 cur_details->game_minute = gclock->get_minute();
01088
01089 time_t t = std::time(0);
01090 struct tm *timeinfo = std::localtime (&t);
01091
01092 cur_details->real_day = timeinfo->tm_mday;
01093 cur_details->real_hour = timeinfo->tm_hour;
01094 cur_details->real_minute = timeinfo->tm_min;
01095 cur_details->real_month = timeinfo->tm_mon+1;
01096 cur_details->real_year = timeinfo->tm_year + 1900;
01097 cur_details->real_second = timeinfo->tm_sec;
01098
01099
01100 cur_party = new SaveGame_Party[cur_details->party_size];
01101 for (i=0; i<cur_details->party_size ; i++)
01102 {
01103 Actor *npc;
01104 if (i == 0)
01105 npc = gwin->get_main_actor();
01106 else
01107 npc = (Npc_actor *) gwin->get_npc(partyman->get_member(i-1));
01108
01109 std::string namestr = npc->get_npc_name();
01110 strncpy (cur_party[i].name, namestr.c_str(), 18);
01111 cur_party[i].shape = npc->get_shapenum();
01112 cur_party[i].shape_file = npc->get_shapefile();
01113
01114 cur_party[i].dext = npc->get_property(Actor::dexterity);
01115 cur_party[i].str = npc->get_property(Actor::strength);
01116 cur_party[i].intel = npc->get_property(Actor::intelligence);
01117 cur_party[i].health = npc->get_property(Actor::health);
01118 cur_party[i].combat = npc->get_property(Actor::combat);
01119 cur_party[i].mana = npc->get_property(Actor::mana);
01120 cur_party[i].magic = npc->get_property(Actor::magic);
01121 cur_party[i].training = npc->get_property(Actor::training);
01122 cur_party[i].exp = npc->get_property(Actor::exp);
01123 cur_party[i].food = npc->get_property(Actor::food_level);
01124 cur_party[i].flags = npc->get_flags();
01125 cur_party[i].flags2 = npc->get_flags2();
01126 }
01127
01128 party = cur_party;
01129 screenshot = cur_shot;
01130 details = cur_details;
01131
01132
01133 char mask[256];
01134
01135 snprintf(mask, 256, SAVENAME2, Game::get_game_type() == BLACK_GATE ? "bg" : "si");
01136
01137 FileList filenames;
01138 U7ListFiles (mask, filenames);
01139 num_games = filenames.size();
01140
01141 games = new SaveInfo[num_games];
01142
01143
01144 for (i = 0; i<num_games; i++)
01145 {
01146 games[i].filename = new char[filenames[i].length()+1];
01147 strcpy (games[i].filename, filenames[i].c_str());
01148 games[i].SetSeqNumber();
01149 }
01150
01151
01152
01153 if (num_games)
01154 qsort(games, num_games, sizeof(SaveInfo), SaveInfo::CompareGames);
01155
01156
01157 first_free = -1;
01158 for (i = 0; i<num_games; i++)
01159 {
01160 games[i].readable = gwin->get_saveinfo(games[i].num, games[i].savename, games[i].screenshot,
01161 games[i].details, games[i].party);
01162
01163 if (first_free == -1 && i != games[i].num) first_free = i;
01164 }
01165
01166 if (first_free == -1) first_free = num_games;
01167
01168
01169 if (num_games) qsort(games, num_games, sizeof(SaveInfo), SaveInfo::CompareGames);
01170
01171
01172
01173
01174 #ifdef DEBUG
01175 cout << "Listing " << num_games << " Save games" << endl;
01176 for (i = 0; i<num_games; i++)
01177 cout << i << " = " << games[i].num << " : " << games[i].filename << " : " << games[i].savename << endl;
01178
01179 cout << "First Free Game " << first_free << endl;
01180 #endif
01181 }
01182
01183 void Newfile_gump::FreeSaveGameDetails()
01184 {
01185 delete cur_shot;
01186 cur_shot = 0;
01187 delete cur_details;
01188 cur_details = 0;
01189 delete [] cur_party;
01190 cur_party = 0;
01191
01192 delete gd_shot;
01193 gd_shot = 0;
01194 delete gd_details;
01195 gd_details = 0;
01196 delete [] gd_party;
01197 gd_party = 0;
01198
01199 filename = 0;
01200
01201
01202
01203 delete [] games;
01204 games = 0;
01205 }
01206
01207
01208
01209
01210 Newfile_gump::SaveInfo::SaveInfo() : num(0), filename(0), savename(0), readable(true),
01211 details(0), party(0), screenshot(0)
01212 {
01213
01214 }
01215
01216
01217 Newfile_gump::SaveInfo::~SaveInfo()
01218 {
01219 delete [] filename;
01220 delete [] savename;
01221 delete details;
01222 delete [] party;
01223 delete screenshot;
01224 }
01225
01226
01227 void Newfile_gump::SaveInfo::SetSeqNumber()
01228 {
01229 int i;
01230
01231 for (i = strlen(filename) - 1; !isdigit(filename[i]); i--)
01232 ;
01233 for (; isdigit(filename[i]); i--)
01234 ;
01235
01236 num = atoi(filename+i+1);
01237 }
01238
01239
01240 int Newfile_gump::SaveInfo::CompareThis(const SaveInfo *other) const
01241 {
01242
01243 if (details && other->details)
01244 {
01245 if (details->real_year < other->details->real_year)
01246 return 1;
01247 if (details->real_year > other->details->real_year)
01248 return -1;
01249
01250 if (details->real_month < other->details->real_month)
01251 return 1;
01252 if (details->real_month > other->details->real_month)
01253 return -1;
01254
01255 if (details->real_day < other->details->real_day)
01256 return 1;
01257 if (details->real_day > other->details->real_day)
01258 return -1;
01259
01260 if (details->real_hour < other->details->real_hour)
01261 return 1;
01262 if (details->real_hour > other->details->real_hour)
01263 return -1;
01264
01265 if (details->real_minute < other->details->real_minute)
01266 return 1;
01267 if (details->real_minute > other->details->real_minute)
01268 return -1;
01269
01270 if (details->real_second < other->details->real_second)
01271 return 1;
01272 if (details->real_second > other->details->real_second)
01273 return -1;
01274 }
01275 else if (details)
01276 {
01277 return -1;
01278 }
01279 else if (other->details)
01280 {
01281 return 1;
01282 }
01283
01284 return num - other->num;
01285 }
01286
01287 static int _U7SaveSeqNr(const char *a)
01288 {
01289 int i;
01290
01291
01292 for (i = strlen((char*)a) - 1; !isdigit(((char*)a)[i]); i--)
01293 ;
01294 for (; isdigit(((char*)a)[i]); i--)
01295 ;
01296
01297
01298 return atoi(&a[i+1]);
01299 }
01300
01301
01302 int Newfile_gump::SaveInfo::CompareGames(const void *a, const void *b)
01303 {
01304 return ((Newfile_gump::SaveInfo*)a)->CompareThis((Newfile_gump::SaveInfo*)b);
01305 }