FFERAWJ5ZXJW3N63T4PENDNVV7HOJ6IUH7QD2RXX7723MKZSP4BQC 2H4FKWKSYEQ2BTYS7USCX7Y7IJMP6X7DD6ADAOJM2JYJY5Y6BPYQC NCYUW5C4IA6JQMFGJQUZNB2GBLKG6ROI7I3ZKO5O5DIQSQNXLNDAC TFUIWOKE42ZQ4ABAAJM4M3NT4QR3GMNQLJVJLH3JGH4MK7C5RYDAC 77KQMSMPKSU2HXCP5UDQJOM6ETXFCF2IYFM2EU566D5A7XE7AHKQC GE5BQQ52QQ2H2PRP336XDLDKHKUGTBBQH4P4IETXAWZJOZUXUQSQC UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC R4TQ3M6GL77RCITERZWQKMEMM3YAGJJE5J2MYOQPH26O5STVKSGAC 2U7VFZ3242P22EPRQKCIHFZRRWHHBZGOEEN2WJNMCXV5BEI67NNAC C55G5JGGSVWMU7XVEJL6YZZLDXQZGRN7JQOAALS6WIKFPX3L2U6QC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC JJULXW764V5C2HJKZNWQAEWB6QM5YZADD7ZCE35LYTBFEM6PMYCAC 6LT6USGJOTDMRJGXLAN2NSZXK2GKWEXDKKUV6SVV7ZC6WI6EKMDQC C2PRXJYHDRF2642VDAUY76HJKCPQFGWDI6AM3SMCMYCHGWYDQXQQC RGWUYJO74FDGTH22CYSHBKFDGJ4S76WTLIULKPXA4QT5ZCNOB4LQC STQDS62PD6PCLYBAB7LPYTG47WMBJP3FIJL55UHC3XFDPGERC3UQC O6ZMFKDI3XO2SWPNEYHIPYFDWJR4TVDP5BAATK6LVCVETQID6E7AC EZLGE274NEOKEADYMRFN62DFMLCKJT7ADPOA2WYLZODI34CK24NQC 4O3VTUJT5T7NBNF3Q45XO2WHS6TCJXVLH6CKX4K36WUBDRT5F6KAC VXSORUQOM2VZA4CAZDC6KPAY373NQIN3UT7CXQXTRCYXO2WM62DAC WQIEW3O4MANA2KKYRUWEZP44KHVJ4RRHEZTDXSF4EDELX66LO26QC IHOKNI4O7EEW4UBMKHP6XOZNEIQSW4AYOT4O3JXUIXNNR553IQAQC JDM5R3HYGXKQKZWY35QZ2KOB24TFZ3FW2PCNXCRCMWG72AZC5ZXQC AAAUQAV76BL63J4HPATVE67LJD4L6OES4A2XODS2OGISOFYQY3XQC KUB3QPOJTCHHU7TRZKMCAEVJU5BN4J556BHDRJWIL3EEVKNHEN7QC 5OVWAD2MGK2NT6Q546KW7HZHELVDBBRC2CQX6VZMZF2YVRC7CPVAC 2NCKGJDDPPGP2NXYYPEPVRJIIWEP6M7HE6WYMQN3UNNN3C2JIRFQC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC TW7QOMTSLYPGUUWHGHLY5G5LV6QQRQIKK4BSE64RY7RDGKVDHCEAC HVSBRVFZODK4R7P6EJ7Y7AHZDVRSNSFDHIH3M3DDGG5E26Z4KD5AC QFIV4YISNBTC5QXN7JYHEL3FBFWIQ2HKJ4YBDCZYTQ3PMPFE653AC JR2RAQ523LOWNDYJNK6AZVKI6WVMI622PIV72XWOVZYPXPUKSQWAC UKYGZDI6PYZPXDACCQGVPHANUP5ADCSNROOZIE7LYIZQWSNFHJZAC POACC5YR6QQGEX6GGMUJKGCDQNX6P6FUF4UQTYGOSHFOHJ26X4SQC DWQDVEHZSTDVFS2GU24ZLIGJDA3M4767TB734JAQEAUVOOCLZ75AC ZMDWMRPYXXYXWETOQANNKZ4RMP4LHZENRPVOYOE7ZU4HBZFUK64QC 25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC XCEZ7OA2INNPSYNAB5U6JB7XNDAD5BKU26YLFPPZ3SEESFZKADQAC KH5DN75GPQGMSUV5VTNFSXV4G3Q43O4R4M2BADFSYEEQYUQFCWMAC MQ62OAMLGJVRW2QIL4PAZRAU6PC52ZVGY2FCOBIY6IWGQIHMU5CAC 7AMQN7MITMXBNVDAK5VOXTQ4TZIAOD6ZLOFJG7GQMBTY23Y2BKSAC #ifndef NG_INPUT_H#define NG_INPUT_Hstruct newgame_def;void opening_screen();bool validate_player_name(const std::string &name, bool verbose);void enter_player_name(newgame_def &ng, bool blankOK);#endif
#include "AppHdr.h"#include "ng-input.h"#include "newgame.h"#include "cio.h"#include "files.h"#include "menu.h"#include "stuff.h"extern std::string init_file_error; // defined in acr.cc// Eventually, this should be something more grand. {dlb}void opening_screen(void){#ifdef USE_TILE// More grand... Like this? ;)if (Options.tile_title_screen)tiles.draw_title();#endifstd::string msg ="<yellow>Hello, welcome to " CRAWL " " + Version::Long() + "!</yellow>" EOL"<brown>(c) Copyright 1997-2002 Linley Henzell, ""2002-2009 Crawl DevTeam" EOL"Please consult crawl_manual.txt for instructions and legal details.""</brown>" EOL;const bool init_found = init_file_error.empty();if (!init_found)msg += "<lightred>No init file ";elsemsg += "<lightgrey>(Read options from ";if (init_found){#ifdef DGAMELAUNCH// For dgl installs, show only the last segment of the .crawlrc// file name so that we don't leak details of the directory// structure to (untrusted) users.msg += get_base_filename(Options.filename);#elsemsg += Options.filename;#endifmsg += ".)";}else{msg += init_file_error;msg += ", using defaults.";}msg += EOL;formatted_string::parse_string(msg).display();textcolor( LIGHTGREY );}static void _show_name_prompt(int where, bool blankOK,const std::vector<player_save_info> &existing_chars,slider_menu &menu){cgotoxy(1, where);textcolor( CYAN );if (blankOK){if (Options.prev_name.length() && Options.remember_name){cprintf(EOL"Press <Enter> for \"%s\", or . to be prompted later."EOL,Options.prev_name.c_str());}else{cprintf(EOL"Press <Enter> to answer this after species and ""job are chosen." EOL);}}cprintf(EOL "What is your name today? ");if (!existing_chars.empty()){const int name_x = wherex(), name_y = wherey();menu.set_limits(name_y + 3, get_number_of_lines());menu.display();cgotoxy(name_x, name_y);}textcolor( LIGHTGREY );}static void _preprocess_character_name(std::string &name, bool blankOK){if (name.empty() && blankOK && Options.prev_name.length()&& Options.remember_name){name = Options.prev_name;}// '.', '?' and '*' are blanked.if (name.length() == 1&& (name[0] == '.' || name[0] == '*' || name[0] == '?')){name = "";}}static bool _is_good_name(std::string &name, bool blankOK, bool verbose){_preprocess_character_name(name, blankOK);// verification begins here {dlb}:if (name.empty()){if (blankOK)return (true);if (verbose)cprintf(EOL "That's a silly name!" EOL);return (false);}// If MULTIUSER is defined, userid will be tacked onto the end// of each character's files, making bones a valid player name.#ifndef MULTIUSER// This would cause big probs with ghosts.// What would? {dlb}// ... having the name "bones" of course! The problem comes from// the fact that bones files would have the exact same filename// as level files for a character named "bones". -- bwrif (stricmp(name.c_str(), "bones") == 0){if (verbose)cprintf(EOL "That's a silly name!" EOL);return (false);}#endifreturn (validate_player_name(name, verbose));}static int newname_keyfilter(int &ch){if (ch == CK_DOWN || ch == CK_PGDN || ch == '\t')return -1;return 1;}static bool _read_player_name(std::string &name,const std::vector<player_save_info> &existing,slider_menu &menu){const int name_x = wherex(), name_y = wherey();int (*keyfilter)(int &) = newname_keyfilter;if (existing.empty())keyfilter = NULL;char buf[kNameLen];// XXX: Prompt displays garbage otherwise, but don't really know why.// Other places don't do this. --robbuf[0] = '\0';line_reader reader(buf, sizeof(buf));reader.set_keyproc(keyfilter);while (true){cgotoxy(name_x, name_y);if (name_x <= 80)cprintf("%-*s", 80 - name_x + 1, "");cgotoxy(name_x, name_y);int ret = reader.read_line(false);if (!ret){name = buf;return (true);}if (ret == CK_ESCAPE)return (false);if (ret != CK_ESCAPE && existing.size()){menu.set_search(name);menu.show();const MenuEntry *sel = menu.selected_entry();if (sel){const player_save_info &p =*static_cast<player_save_info*>( sel->data );name = p.name;return (true);}}// Go back and prompt the user.}}// Reads a valid name from the player, writing it to ng.name.void enter_player_name(newgame_def &ng, bool blankOK){int prompt_start = wherey();bool ask_name = true;std::vector<player_save_info> existing_chars;slider_menu char_menu(MF_SINGLESELECT | MF_NOWRAP, false);if (!ng.name.empty())ask_name = false;if (blankOK && (ask_name || !_is_good_name(ng.name, false, false))){existing_chars = find_saved_characters();if (existing_chars.empty()){cgotoxy(1,12);formatted_string::parse_string(" If you've never been here before, you might want to try out" EOL" the Dungeon Crawl tutorial. To do this, press ""<white>Ctrl-T</white> on the next" EOL" screen.").display();}else{MenuEntry *title = new MenuEntry("Or choose an existing character:");title->colour = LIGHTCYAN;char_menu.set_title( title );for (unsigned int i = 0; i < existing_chars.size(); ++i){std::string desc = " " + existing_chars[i].short_desc();if (static_cast<int>(desc.length()) >= get_number_of_cols())desc = desc.substr(0, get_number_of_cols() - 1);#ifdef USE_TILEMenuEntry *me = new PlayerMenuEntry(desc);#elseMenuEntry *me = new MenuEntry(desc);#endifme->data = &existing_chars[i];char_menu.add_entry(me);}}}do{// Prompt for a new name if current one unsatisfactory {dlb}:if (ask_name){_show_name_prompt(prompt_start, blankOK, existing_chars, char_menu);// If the player wants out, we bail out.if (!_read_player_name(ng.name, existing_chars, char_menu))end(0);trim_string(ng.name);}}while (ask_name = !_is_good_name(ng.name, blankOK, true));}bool validate_player_name(const std::string &name, bool verbose){#if defined(TARGET_OS_DOS) || defined(TARGET_OS_WINDOWS)// Quick check for CON -- blows up real good under DOS/Windows.if (stricmp(name.c_str(), "con") == 0|| stricmp(name.c_str(), "nul") == 0|| stricmp(name.c_str(), "prn") == 0|| strnicmp(name.c_str(), "LPT", 3) == 0){if (verbose)cprintf(EOL "Sorry, that name gives your OS a headache." EOL);return (false);}#endiffor (unsigned int i = 0; i < name.length(); i++){char c = name[i];// Note that this includes systems which may be using the// packaging system. The packaging system is very simple// and doesn't take the time to escape every character that// might be a problem for some random shell or OS... so we// play it very conservative here. -- bwrif (!isalnum(c) && c != '-' && c != '.' && c != '_' && c != ' '){if (verbose){cprintf( EOL"Alpha-numerics, spaces, dashes, periods ""and underscores only, please."EOL );}return (false);}}return (true);}
}// Eventually, this should be something more grand. {dlb}static void _opening_screen(void){#ifdef USE_TILE// More grand... Like this? ;)if (Options.tile_title_screen)tiles.draw_title();#endifstd::string msg ="<yellow>Hello, welcome to " CRAWL " " + Version::Long() + "!</yellow>" EOL"<brown>(c) Copyright 1997-2002 Linley Henzell, ""2002-2009 Crawl DevTeam" EOL"Please consult crawl_manual.txt for instructions and legal details.""</brown>" EOL;const bool init_found = init_file_error.empty();if (!init_found)msg += "<lightred>No init file ";elsemsg += "<lightgrey>(Read options from ";if (init_found){#ifdef DGAMELAUNCH// For dgl installs, show only the last segment of the .crawlrc// file name so that we don't leak details of the directory// structure to (untrusted) users.msg += get_base_filename(Options.filename);#elsemsg += Options.filename;#endifmsg += ".)";}else{msg += init_file_error;msg += ", using defaults.";}msg += EOL;formatted_string::parse_string(msg).display();textcolor( LIGHTGREY );}static void _show_name_prompt(int where, bool blankOK,const std::vector<player_save_info> &existing_chars,slider_menu &menu){cgotoxy(1, where);textcolor( CYAN );if (blankOK){if (Options.prev_name.length() && Options.remember_name){cprintf(EOL"Press <Enter> for \"%s\", or . to be prompted later."EOL,Options.prev_name.c_str());}else{cprintf(EOL"Press <Enter> to answer this after species and ""job are chosen." EOL);}}cprintf(EOL "What is your name today? ");if (!existing_chars.empty()){const int name_x = wherex(), name_y = wherey();menu.set_limits(name_y + 3, get_number_of_lines());menu.display();cgotoxy(name_x, name_y);}textcolor( LIGHTGREY );}static void _preprocess_character_name(std::string &name, bool blankOK){if (name.empty() && blankOK && Options.prev_name.length()&& Options.remember_name){name = Options.prev_name;}// '.', '?' and '*' are blanked.if (name.length() == 1&& (name[0] == '.' || name[0] == '*' || name[0] == '?')){name = "";}}static bool _is_good_name(std::string &name, bool blankOK, bool verbose){_preprocess_character_name(name, blankOK);// verification begins here {dlb}:if (name.empty()){if (blankOK)return (true);if (verbose)cprintf(EOL "That's a silly name!" EOL);return (false);}// If MULTIUSER is defined, userid will be tacked onto the end// of each character's files, making bones a valid player name.#ifndef MULTIUSER// This would cause big probs with ghosts.// What would? {dlb}// ... having the name "bones" of course! The problem comes from// the fact that bones files would have the exact same filename// as level files for a character named "bones". -- bwrif (stricmp(name.c_str(), "bones") == 0){if (verbose)cprintf(EOL "That's a silly name!" EOL);return (false);}#endifreturn (validate_player_name(name, verbose));}static int newname_keyfilter(int &ch){if (ch == CK_DOWN || ch == CK_PGDN || ch == '\t')return -1;return 1;}static bool _read_player_name(std::string &name,const std::vector<player_save_info> &existing,slider_menu &menu){const int name_x = wherex(), name_y = wherey();int (*keyfilter)(int &) = newname_keyfilter;if (existing.empty())keyfilter = NULL;char buf[kNameLen];// XXX: Prompt displays garbage otherwise, but don't really know why.// Other places don't do this. --robbuf[0] = '\0';line_reader reader(buf, sizeof(buf));reader.set_keyproc(keyfilter);while (true){cgotoxy(name_x, name_y);if (name_x <= 80)cprintf("%-*s", 80 - name_x + 1, "");cgotoxy(name_x, name_y);int ret = reader.read_line(false);if (!ret){name = buf;return (true);}if (ret == CK_ESCAPE)return (false);if (ret != CK_ESCAPE && existing.size()){menu.set_search(name);menu.show();const MenuEntry *sel = menu.selected_entry();if (sel){const player_save_info &p =*static_cast<player_save_info*>( sel->data );name = p.name;return (true);}}// Go back and prompt the user.}}static void _enter_player_name(bool blankOK){int prompt_start = wherey();bool ask_name = true;std::vector<player_save_info> existing_chars;slider_menu char_menu(MF_SINGLESELECT | MF_NOWRAP, false);if (!you.your_name.empty())ask_name = false;if (blankOK && (ask_name || !_is_good_name(you.your_name, false, false))){existing_chars = find_saved_characters();if (existing_chars.empty()){cgotoxy(1,12);formatted_string::parse_string(" If you've never been here before, you might want to try out" EOL" the Dungeon Crawl tutorial. To do this, press ""<white>Ctrl-T</white> on the next" EOL" screen.").display();}else{MenuEntry *title = new MenuEntry("Or choose an existing character:");title->colour = LIGHTCYAN;char_menu.set_title( title );for (unsigned int i = 0; i < existing_chars.size(); ++i){std::string desc = " " + existing_chars[i].short_desc();if (static_cast<int>(desc.length()) >= get_number_of_cols())desc = desc.substr(0, get_number_of_cols() - 1);#ifdef USE_TILEMenuEntry *me = new PlayerMenuEntry(desc);#elseMenuEntry *me = new MenuEntry(desc);#endifme->data = &existing_chars[i];char_menu.add_entry(me);}}}do{// Prompt for a new name if current one unsatisfactory {dlb}:if (ask_name){_show_name_prompt(prompt_start, blankOK, existing_chars, char_menu);// If the player wants out, we bail out.if (!_read_player_name(you.your_name, existing_chars, char_menu))end(0);trim_string(you.your_name);}}while (ask_name = !_is_good_name(you.your_name, blankOK, true));
bool validate_player_name(const std::string &name, bool verbose){#if defined(TARGET_OS_DOS) || defined(TARGET_OS_WINDOWS)// Quick check for CON -- blows up real good under DOS/Windows.if (stricmp(name.c_str(), "con") == 0|| stricmp(name.c_str(), "nul") == 0|| stricmp(name.c_str(), "prn") == 0|| strnicmp(name.c_str(), "LPT", 3) == 0){if (verbose)cprintf(EOL "Sorry, that name gives your OS a headache." EOL);return (false);}#endiffor (unsigned int i = 0; i < name.length(); i++){char c = name[i];// Note that this includes systems which may be using the// packaging system. The packaging system is very simple// and doesn't take the time to escape every character that// might be a problem for some random shell or OS... so we// play it very conservative here. -- bwrif (!isalnum(c) && c != '-' && c != '.' && c != '_' && c != ' '){if (verbose){cprintf( EOL"Alpha-numerics, spaces, dashes, periods ""and underscores only, please."EOL );}return (false);}}return (true);}