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 #endif
00026
00027 #include "SDL_events.h"
00028
00029 #include "Audio.h"
00030 #include "Configuration.h"
00031 #include "File_gump.h"
00032 #include "exult.h"
00033 #include "game.h"
00034 #include "gamewin.h"
00035 #include "Gump_button.h"
00036 #include "mouse.h"
00037 #include "Yesno_gump.h"
00038
00039 #ifndef UNDER_CE
00040 using std::cout;
00041 using std::endl;
00042 using std::memmove;
00043 using std::string;
00044 using std::strlen;
00045 using std::strncpy;
00046 #endif
00047
00048
00049
00050
00051 short File_gump::btn_rows[2] = {143, 156};
00052 short File_gump::btn_cols[3] = {94, 163, 232};
00053 short File_gump::textx = 237, File_gump::texty = 14,
00054 File_gump::texth = 13;
00055
00056
00057
00058
00059
00060 class Load_save_button : public Gump_button
00061 {
00062 public:
00063 Load_save_button(Gump *par, int px, int py, int shapenum)
00064 : Gump_button(par, shapenum, px, py)
00065 { }
00066
00067 virtual void activate();
00068 };
00069
00070
00071
00072
00073 class Quit_button : public Gump_button
00074 {
00075 public:
00076 Quit_button(Gump *par, int px, int py)
00077 : Gump_button(par,
00078 game->get_shape("gumps/quitbtn"), px, py)
00079 { }
00080
00081 virtual void activate();
00082 };
00083
00084
00085
00086
00087 class Sound_button : public Gump_button
00088 {
00089 public:
00090 Sound_button(Gump *par, int px, int py, int shapenum,
00091 bool enabled)
00092 : Gump_button(par, shapenum, px, py)
00093 { pushed = enabled; }
00094
00095 virtual void activate();
00096 };
00097
00098
00099
00100
00101
00102 void Load_save_button::activate
00103 (
00104 )
00105 {
00106 if (get_shapenum() == game->get_shape("gumps/loadbtn"))
00107 ((File_gump *) parent)->load();
00108 else
00109 ((File_gump *) parent)->save();
00110 }
00111
00112
00113
00114
00115
00116 void Quit_button::activate
00117 (
00118 )
00119 {
00120 ((File_gump *) parent)->quit();
00121 }
00122
00123
00124
00125
00126
00127 void Sound_button::activate
00128 (
00129 )
00130 {
00131 pushed = ((File_gump *) parent)->toggle_option(this);
00132 parent->paint();
00133 }
00134
00135
00136
00137
00138
00139 class Gump_text : public Gump_widget
00140 {
00141 char *text;
00142 int max_size;
00143 int length;
00144 int textx, texty;
00145 int cursor;
00146 public:
00147 Gump_text(Gump *par, int shnum, int px, int py, int maxsz,
00148 int tx, int ty)
00149 : Gump_widget(par, shnum, px, py), text(new char[maxsz + 1]),
00150 max_size(maxsz), length(0), textx(x + tx), texty(y + ty),
00151 cursor(0)
00152 {
00153 text[0] = text[maxsz] = 0;
00154 Shape_frame *shape =
00155 ShapeID(shnum, 0, SF_GUMPS_VGA).get_shape();
00156
00157 textx -= shape->get_xleft();
00158 texty -= shape->get_yabove();
00159 }
00160 ~Gump_text()
00161 { delete [] text; }
00162 int get_length()
00163 { return length; }
00164 char *get_text()
00165 { return text; }
00166 void set_text(char *newtxt)
00167 {
00168 strncpy(text, newtxt ? newtxt : "", max_size);
00169 length = strlen(text);
00170 }
00171 int get_cursor()
00172 { return cursor; }
00173 void set_cursor(int pos)
00174 {
00175 if (pos >= 0 && pos <= length)
00176 {
00177 cursor = pos;
00178 refresh();
00179 }
00180 }
00181 void paint();
00182
00183 int mouse_clicked(int mx, int my);
00184 void insert(int chr);
00185 int delete_left();
00186 int delete_right();
00187 void lose_focus();
00188
00189 protected:
00190 void refresh()
00191 {
00192 paint();
00193 }
00194 };
00195
00196
00197
00198
00199
00200 void Gump_text::paint
00201 (
00202 )
00203 {
00204 paint_shape(parent->get_x() + x, parent->get_y() + y);
00205
00206 sman->paint_text(2, text, parent->get_x() + textx,
00207 parent->get_y() + texty);
00208 if (get_framenum())
00209 gwin->get_win()->fill8(0, 1, sman->get_text_height(2),
00210 parent->get_x() + textx +
00211 sman->get_text_width(2, text, cursor),
00212 parent->get_y() + texty + 1);
00213 gwin->set_painted();
00214 }
00215
00216
00217
00218
00219
00220
00221
00222 int Gump_text::mouse_clicked
00223 (
00224 int mx, int my
00225 )
00226 {
00227 if (!on_widget(mx, my))
00228 return (0);
00229 mx -= textx + parent->get_x();
00230 if (!get_framenum())
00231 {
00232 set_frame(1);
00233 cursor = 0;
00234 }
00235 else
00236 {
00237 for (cursor = 0; cursor <= length; cursor++)
00238 if (sman->get_text_width(2, text, cursor) > mx)
00239 {
00240 if (cursor > 0)
00241 cursor--;
00242 break;
00243 }
00244 if (cursor > length)
00245 cursor--;
00246 }
00247 return (1);
00248 }
00249
00250
00251
00252
00253
00254 void Gump_text::insert
00255 (
00256 int chr
00257 )
00258 {
00259 if (!get_framenum() || length == max_size)
00260 return;
00261 if (cursor < length)
00262 memmove(text + cursor + 1, text + cursor, length - cursor);
00263 text[cursor++] = chr;
00264 length++;
00265 text[length] = 0;
00266 refresh();
00267 }
00268
00269
00270
00271
00272
00273
00274
00275 int Gump_text::delete_left
00276 (
00277 )
00278 {
00279 if (!get_framenum() || !cursor)
00280 return (0);
00281 if (cursor < length)
00282 memmove(text + cursor - 1, text + cursor, length - cursor);
00283 text[--length] = 0;
00284 cursor--;
00285 refresh();
00286 return (1);
00287 }
00288
00289
00290
00291
00292
00293
00294
00295 int Gump_text::delete_right
00296 (
00297 )
00298 {
00299 if (!get_framenum() || cursor == length)
00300 return (0);
00301 cursor++;
00302 return (delete_left());
00303 }
00304
00305
00306
00307
00308
00309 void Gump_text::lose_focus
00310 (
00311 )
00312 {
00313 set_frame(0);
00314 refresh();
00315 }
00316
00317
00318
00319
00320
00321 File_gump::File_gump
00322 (
00323 ) : Modal_gump(0, game->get_shape("gumps/fileio")),
00324 pushed_text(0), focus(0), restored(0)
00325 {
00326 set_object_area(Rectangle(0,0,0,0), 8, 150);
00327
00328 size_t i;
00329 int ty = texty;
00330 for (i = 0; i < sizeof(names)/sizeof(names[0]); i++, ty += texth)
00331 {
00332 names[i] = new Gump_text(this,
00333 game->get_shape("gumps/fntext"),
00334 textx, ty, 30, 12, 2);
00335 names[i]->set_text(gwin->get_save_name(i));
00336 }
00337
00338 buttons[0] = buttons[1] = 0;
00339 buttons[2] = new Quit_button(this, btn_cols[2], btn_rows[0]);
00340
00341 buttons[3] = new Sound_button(this, btn_cols[0], btn_rows[1],
00342 game->get_shape("gumps/musicbtn"),
00343 Audio::get_ptr()->is_music_enabled());
00344 buttons[4] = new Sound_button(this, btn_cols[1], btn_rows[1],
00345 game->get_shape("gumps/speechbtn"),
00346 Audio::get_ptr()->is_speech_enabled());
00347 buttons[5] = new Sound_button(this, btn_cols[2], btn_rows[1],
00348 game->get_shape("gumps/soundbtn"),
00349 Audio::get_ptr()->are_effects_enabled());
00350 }
00351
00352
00353
00354
00355
00356 File_gump::~File_gump
00357 (
00358 )
00359 {
00360 size_t i;
00361 for (i = 0; i < sizeof(names)/sizeof(names[0]); i++)
00362 delete names[i];
00363 for (i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++)
00364 delete buttons[i];
00365 }
00366
00367
00368
00369
00370
00371
00372
00373 int File_gump::get_save_index
00374 (
00375 Gump_text *txt
00376 )
00377 {
00378 for (size_t i = 0; i < sizeof(names)/sizeof(names[0]); i++)
00379 if (names[i] == txt)
00380 return (i);
00381 return (-1);
00382 }
00383
00384
00385
00386
00387
00388 void File_gump::remove_focus
00389 (
00390 )
00391 {
00392 if (!focus)
00393 return;
00394 focus->lose_focus();
00395 focus = 0;
00396 delete buttons[0];
00397 buttons[0] = 0;
00398 delete buttons[1];
00399 buttons[1] = 0;
00400 paint();
00401 }
00402
00403
00404
00405
00406
00407 void File_gump::load
00408 (
00409 )
00410 {
00411 if (!focus ||
00412 !focus->get_length())
00413 return;
00414 int num = get_save_index(focus);
00415 if (num == -1)
00416 return;
00417 if (!Yesno_gump::ask(
00418 "Okay to load over your current game?"))
00419 return;
00420 gwin->restore_gamedat(num);
00421 gwin->read();
00422 done = 1;
00423 restored = 1;
00424 }
00425
00426
00427
00428
00429
00430 void File_gump::save
00431 (
00432 )
00433 {
00434 if (!focus ||
00435 !focus->get_length())
00436 return;
00437 int num = get_save_index(focus);
00438 if (num == -1)
00439 return;
00440 if (*gwin->get_save_name(num))
00441 if (!Yesno_gump::ask(
00442 "Okay to write over existing saved game?"))
00443 return;
00444 gwin->write();
00445 gwin->save_gamedat(num, focus->get_text());
00446 cout << "Saved game #" << num << " successfully." << endl;
00447 remove_focus();
00448 }
00449
00450
00451
00452
00453
00454 void File_gump::quit
00455 (
00456 )
00457 {
00458 if (!Yesno_gump::ask("Do you really want to quit?"))
00459 return;
00460 quitting_time = QUIT_TIME_YES;
00461 done = 1;
00462 }
00463
00464
00465
00466
00467
00468
00469
00470 int File_gump::toggle_option
00471 (
00472 Gump_button *btn
00473 )
00474 {
00475 if (btn == buttons[3])
00476 {
00477 bool music = !Audio::get_ptr()->is_music_enabled();
00478 Audio::get_ptr()->set_music_enabled(music);
00479 if (!music)
00480 Audio::get_ptr()->stop_music();
00481 string s = music ? "yes" : "no";
00482
00483 config->set("config/audio/midi/enabled", s, true);
00484 return music ? 1 : 0;
00485 }
00486 if (btn == buttons[4])
00487 {
00488 bool speech = !Audio::get_ptr()->is_speech_enabled();
00489 Audio::get_ptr()->set_speech_enabled(speech);
00490 string s = speech ? "yes" : "no";
00491
00492 config->set("config/audio/speech/enabled", s, true);
00493 return speech ? 1 : 0;
00494 }
00495 if (btn == buttons[5])
00496 {
00497 bool effects = !Audio::get_ptr()->are_effects_enabled();
00498 Audio::get_ptr()->set_effects_enabled(effects);
00499 if (!effects)
00500 Audio::get_ptr()->stop_sound_effects();
00501 string s = effects ? "yes" : "no";
00502
00503 config->set("config/audio/effects/enabled", s, true);
00504 return effects ? 1 : 0;
00505 }
00506 return false;
00507 }
00508
00509
00510
00511
00512
00513 void File_gump::paint
00514 (
00515 )
00516 {
00517 Gump::paint();
00518
00519 size_t i;
00520 for (i = 0; i < sizeof(names)/sizeof(names[0]); i++)
00521 if (names[i])
00522 names[i]->paint();
00523 for (i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++)
00524 if (buttons[i])
00525 buttons[i]->paint();
00526 }
00527
00528
00529
00530
00531
00532 void File_gump::mouse_down
00533 (
00534 int mx, int my
00535 )
00536 {
00537 pushed = 0;
00538 pushed_text = 0;
00539
00540 Gump_button *btn = Gump::on_button(mx, my);
00541 if (btn)
00542 pushed = btn;
00543 else
00544 for (size_t i = 0; i < sizeof(buttons)/sizeof(buttons[0]); i++)
00545 if (buttons[i] && buttons[i]->on_button(mx, my))
00546 {
00547 pushed = buttons[i];
00548 break;
00549 }
00550 if (pushed)
00551 {
00552 pushed->push();
00553 return;
00554 }
00555
00556 for (size_t i = 0; i < sizeof(names)/sizeof(names[0]); i++)
00557 if (names[i]->on_widget(mx, my))
00558 {
00559 pushed_text = names[i];
00560 break;
00561 }
00562 }
00563
00564
00565
00566
00567
00568 void File_gump::mouse_up
00569 (
00570 int mx, int my
00571 )
00572 {
00573 if (pushed)
00574 {
00575 pushed->unpush();
00576 if (pushed->on_button(mx, my))
00577 pushed->activate();
00578 pushed = 0;
00579 }
00580 if (!pushed_text)
00581 return;
00582
00583 if (!pushed_text->mouse_clicked(mx, my) ||
00584 pushed_text == focus)
00585 {
00586 pushed_text->paint();
00587 pushed_text = 0;
00588 return;
00589 }
00590 if (focus)
00591 {
00592 focus->set_text(gwin->get_save_name(get_save_index(focus)));
00593 focus->lose_focus();
00594 }
00595 focus = pushed_text;
00596 pushed_text = 0;
00597 if (focus->get_length())
00598 {
00599 if (!buttons[0])
00600 buttons[0] = new Load_save_button(this,
00601 btn_cols[0], btn_rows[0], game->get_shape("gumps/loadbtn"));
00602 if (!buttons[1])
00603 buttons[1] = new Load_save_button(this,
00604 btn_cols[1], btn_rows[0], game->get_shape("gumps/savebtn"));
00605 }
00606 else if (!focus->get_length())
00607 {
00608 delete buttons[0];
00609 delete buttons[1];
00610 buttons[0] = buttons[1] = 0;
00611 }
00612 paint();
00613 gwin->set_painted();
00614 }
00615
00616
00617
00618
00619
00620 void File_gump::text_input(int chr, int unicode)
00621 {
00622 if (!focus)
00623 return;
00624 switch (chr)
00625 {
00626 case SDLK_RETURN:
00627 if (!buttons[0] && buttons[1])
00628 {
00629 buttons[1]->push();
00630 gwin->show(1);
00631 buttons[1]->unpush();
00632 gwin->show(1);
00633 buttons[1]->activate();
00634 }
00635 break;
00636 case SDLK_BACKSPACE:
00637 if (focus->delete_left())
00638 {
00639 delete buttons[0];
00640 buttons[0] = 0;
00641 }
00642 if (!focus->get_length())
00643 {
00644 delete buttons[0];
00645 delete buttons[1];
00646 buttons[0] = buttons[1] = 0;
00647 paint();
00648 }
00649 return;
00650 case SDLK_DELETE:
00651 if (focus->delete_right())
00652 {
00653 delete buttons[0];
00654 buttons[0] = 0;
00655 }
00656 if (!focus->get_length())
00657 {
00658 delete buttons[0];
00659 delete buttons[1];
00660 buttons[0] = buttons[1] = 0;
00661 paint();
00662 }
00663 return;
00664 case SDLK_LEFT:
00665 focus->set_cursor(focus->get_cursor() - 1);
00666 return;
00667 case SDLK_RIGHT:
00668 focus->set_cursor(focus->get_cursor() + 1);
00669 return;
00670 case SDLK_HOME:
00671 focus->set_cursor(0);
00672 return;
00673 case SDLK_END:
00674 focus->set_cursor(focus->get_length());
00675 return;
00676 }
00677
00678 if ((unicode & 0xFF80) == 0 )
00679 chr = unicode & 0x7F;
00680 else
00681 chr = 0;
00682
00683 if (chr < ' ')
00684 return;
00685 if (chr < 256 && isascii(chr))
00686 {
00687 int old_length = focus->get_length();
00688 focus->insert(chr);
00689
00690
00691 if (!old_length && focus->get_length() && !buttons[1])
00692 {
00693 buttons[1] = new Load_save_button(this,
00694 btn_cols[1], btn_rows[0], game->get_shape("gumps/savebtn"));
00695 buttons[1]->paint();
00696 }
00697 if (buttons[0])
00698 {
00699 delete buttons[0];
00700 buttons[0] = 0;
00701 paint();
00702 }
00703 gwin->set_painted();
00704 }
00705 }