OSDN Git Service

[Refactor] #3496 optional 型の存在判定 has_value() を撤廃した その4
[hengbandforosx/hengbandosx.git] / src / player / process-name.cpp
1 #include "player/process-name.h"
2 #include "autopick/autopick-reader-writer.h"
3 #include "core/asking-player.h"
4 #include "game-option/birth-options.h"
5 #include "io/files-util.h"
6 #include "player/player-personality.h"
7 #include "system/player-type-definition.h"
8 #include "term/screen-processor.h"
9 #include "term/term-color-types.h"
10 #include "util/angband-files.h"
11 #include "util/finalizer.h"
12 #include "util/string-processor.h"
13 #include "view/display-player-misc-info.h"
14 #include "world/world.h"
15 #include <sstream>
16 #ifdef SAVEFILE_USE_UID
17 #include "main-unix/unix-user-ids.h"
18 #endif
19
20 /*!
21  * @brief プレイヤーの名前をチェックして修正する
22  * Process the player name.
23  * @param player_ptr プレイヤーへの参照ポインタ
24  * @param sf セーブファイル名に合わせた修正を行うならばTRUE
25  * @details
26  * Extract a clean "base name".
27  * Build the savefile name if needed.
28  */
29 void process_player_name(PlayerType *player_ptr, bool is_new_savefile)
30 {
31     char old_player_base[32] = "";
32     if (w_ptr->character_generated) {
33         strcpy(old_player_base, player_ptr->base_name);
34     }
35
36     for (int i = 0; player_ptr->name[i]; i++) {
37 #ifdef JP
38         if (iskanji(player_ptr->name[i])) {
39             i++;
40             continue;
41         }
42
43         if (iscntrl((unsigned char)player_ptr->name[i]))
44 #else
45         if (iscntrl(player_ptr->name[i]))
46 #endif
47         {
48             quit_fmt(_("'%s' という名前は不正なコントロールコードを含んでいます。", "The name '%s' contains control chars!"), player_ptr->name);
49         }
50     }
51
52     int k = 0;
53     for (int i = 0; player_ptr->name[i]; i++) {
54 #ifdef JP
55         unsigned char c = player_ptr->name[i];
56 #else
57         char c = player_ptr->name[i];
58 #endif
59
60 #ifdef JP
61         if (iskanji(c)) {
62             if (k + 2 >= (int)sizeof(player_ptr->base_name) || !player_ptr->name[i + 1]) {
63                 break;
64             }
65
66             player_ptr->base_name[k++] = c;
67             i++;
68             player_ptr->base_name[k++] = player_ptr->name[i];
69         }
70 #ifdef SJIS
71         else if (iskana(c))
72             player_ptr->base_name[k++] = c;
73 #endif
74         else
75 #endif
76             if (!strncmp(PATH_SEP, player_ptr->name + i, strlen(PATH_SEP))) {
77             player_ptr->base_name[k++] = '_';
78             i += strlen(PATH_SEP);
79         }
80 #if defined(WINDOWS)
81         else if (angband_strchr("\"*,/:;<>?\\|", c))
82             player_ptr->base_name[k++] = '_';
83 #endif
84         else if (isprint(c)) {
85             player_ptr->base_name[k++] = c;
86         }
87     }
88
89     player_ptr->base_name[k] = '\0';
90     if (!player_ptr->base_name[0]) {
91         strcpy(player_ptr->base_name, "PLAYER");
92     }
93
94     auto is_modified = false;
95     if (is_new_savefile && (savefile.empty() || !keep_savefile)) {
96         std::stringstream ss;
97
98 #ifdef SAVEFILE_USE_UID
99         ss << UnixUserIds::get_instance().get_user_id();
100         ss << '.' << player_ptr->base_name;
101 #else
102         ss << player_ptr->base_name;
103 #endif
104         savefile = path_build(ANGBAND_DIR_SAVE, ss.str());
105         is_modified = true;
106     }
107
108     if (is_modified || savefile_base.empty()) {
109 #ifdef SAVEFILE_USE_UID
110         const auto &savefile_str = savefile.filename().string();
111         const auto split = str_split(savefile_str, '.');
112         savefile_base = split[1];
113 #else
114         savefile_base = savefile.filename().string();
115 #endif
116     }
117
118     if (w_ptr->character_generated && !streq(old_player_base, player_ptr->base_name)) {
119         autopick_load_pref(player_ptr, false);
120     }
121 }
122
123 /*!
124  * @brief プレイヤーの名前を変更する
125  * @param player_ptr プレイヤーへの参照ポインタ
126  * @details PlayerType::name は32バイトで定義されているが、
127  * スコアファイル(lib/apex/scores.raw)に保存されているプレイヤー名が最大16バイト (ヌル文字含)となっている
128  * このため最大値を16バイトに制限する
129  */
130 void get_name(PlayerType *player_ptr)
131 {
132     const auto finalizer = util::make_finalizer([player_ptr]() {
133         display_player_misc_info(player_ptr);
134     });
135
136     std::string initial_name(player_ptr->name);
137     const auto max_name_size = 15;
138     const auto copy_size = sizeof(player_ptr->name);
139     constexpr auto prompt = _("キャラクターの名前を入力して下さい: ", "Enter a name for your character: ");
140     const auto name = input_string(prompt, max_name_size, initial_name);
141     if (name) {
142         if (!name->empty()) {
143             angband_strcpy(player_ptr->name, name.value(), copy_size);
144         }
145
146         return;
147     }
148
149     if (initial_name.empty()) {
150         angband_strcpy(player_ptr->name, "PLAYER", copy_size);
151     }
152 }