OSDN Git Service

Replace sprintf() simply. Does part of the work to resolve https://github.com/hengba...
[hengbandforosx/hengbandosx.git] / src / cmd-visual / cmd-draw.cpp
1 #include "cmd-visual/cmd-draw.h"
2 #include "core/asking-player.h"
3 #include "core/player-redraw-types.h"
4 #include "core/player-update-types.h"
5 #include "core/stuff-handler.h"
6 #include "core/window-redrawer.h"
7 #include "io/files-util.h"
8 #include "io/input-key-acceptor.h"
9 #include "main/sound-of-music.h"
10 #include "player-base/player-race.h"
11 #include "player-info/race-types.h"
12 #include "player/process-name.h"
13 #include "racial/racial-android.h"
14 #include "system/player-type-definition.h"
15 #include "term/gameterm.h"
16 #include "term/screen-processor.h"
17 #include "term/term-color-types.h"
18 #include "term/z-form.h"
19 #include "util/int-char-converter.h"
20 #include "util/string-processor.h"
21 #include "view/display-messages.h"
22 #include "view/display-player.h"
23 #include "world/world.h"
24
25 /*!
26  * @brief 画面を再描画するコマンドのメインルーチン
27  * Hack -- redraw the screen
28  * @param player_ptr プレイヤーへの参照ポインタ
29  * @details
30  * <pre>
31  * This command performs various low level updates, clears all the "extra"
32  * windows, does a total redraw of the main window, and requests all of the
33  * interesting updates and redraws that I can think of.
34  *
35  * This command is also used to "instantiate" the results of the user
36  * selecting various things, such as graphics mode, so it must call
37  * the "TERM_XTRA_REACT" hook before redrawing the windows.
38  * </pre>
39  */
40 void do_cmd_redraw(PlayerType *player_ptr)
41 {
42     term_xtra(TERM_XTRA_REACT, 0);
43
44     player_ptr->update |= (PU_COMBINE | PU_REORDER);
45     player_ptr->update |= (PU_TORCH);
46     player_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS);
47     player_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
48     player_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE);
49     player_ptr->update |= (PU_MONSTERS);
50
51     player_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
52
53     player_ptr->window_flags |= (PW_INVEN | PW_EQUIP | PW_SPELL | PW_PLAYER);
54     player_ptr->window_flags |= (PW_MESSAGE | PW_OVERHEAD | PW_DUNGEON | PW_MONSTER | PW_OBJECT);
55
56     update_playtime();
57     handle_stuff(player_ptr);
58     if (PlayerRace(player_ptr).equals(PlayerRaceType::ANDROID)) {
59         calc_android_exp(player_ptr);
60     }
61
62     term_type *old = game_term;
63     for (auto i = 0U; i < angband_terms.size(); ++i) {
64         if (!angband_terms[i]) {
65             continue;
66         }
67
68         term_activate(angband_terms[i]);
69         term_redraw();
70         term_fresh();
71         term_activate(old);
72     }
73 }
74
75 /*!
76  * @brief プレイヤーのステータス表示
77  */
78 void do_cmd_player_status(PlayerType *player_ptr)
79 {
80     int mode = 0;
81     char tmp[160];
82     screen_save();
83     while (true) {
84         update_playtime();
85         (void)display_player(player_ptr, mode);
86
87         if (mode == 5) {
88             mode = 0;
89             (void)display_player(player_ptr, mode);
90         }
91
92         term_putstr(2, 23, -1, TERM_WHITE,
93             _("['c'で名前変更, 'f'でファイルへ書出, 'h'でモード変更, ESCで終了]", "['c' to change name, 'f' to file, 'h' to change mode, or ESC]"));
94         char c = inkey();
95         if (c == ESCAPE) {
96             break;
97         }
98
99         if (c == 'c') {
100             get_name(player_ptr);
101             process_player_name(player_ptr);
102         } else if (c == 'f') {
103             strnfmt(tmp, sizeof(tmp), "%s.txt", player_ptr->base_name);
104             if (get_string(_("ファイル名: ", "File name: "), tmp, 80)) {
105                 if (tmp[0] && (tmp[0] != ' ')) {
106                     update_playtime();
107                     file_character(player_ptr, tmp);
108                 }
109             }
110         } else if (c == 'h') {
111             mode++;
112         } else {
113             bell();
114         }
115
116         msg_erase();
117     }
118
119     screen_load();
120     player_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
121     handle_stuff(player_ptr);
122 }
123
124 /*!
125  * @brief 最近表示されたメッセージを再表示するコマンドのメインルーチン
126  * Recall the most recent message
127  */
128 void do_cmd_message_one(void)
129 {
130     prt(format("> %s", message_str(0)), 0, 0);
131 }
132
133 /*!
134  * @brief メッセージのログを表示するコマンドのメインルーチン
135  * Recall the most recent message
136  * @details
137  * <pre>
138  * Show previous messages to the user   -BEN-
139  *
140  * The screen format uses line 0 and 23 for headers and prompts,
141  * skips line 1 and 22, and uses line 2 thru 21 for old messages.
142  *
143  * This command shows you which commands you are viewing, and allows
144  * you to "search" for strings in the recall.
145  *
146  * Note that messages may be longer than 80 characters, but they are
147  * displayed using "infinite" length, with a special sub-command to
148  * "slide" the virtual display to the left or right.
149  *
150  * Attempt to only hilite the matching portions of the string.
151  * </pre>
152  */
153 void do_cmd_messages(int num_now)
154 {
155     char shower_str[81];
156     char finder_str[81];
157     char back_str[81];
158     concptr shower = nullptr;
159     int wid, hgt;
160     term_get_size(&wid, &hgt);
161     int num_lines = hgt - 4;
162     strcpy(finder_str, "");
163     strcpy(shower_str, "");
164     int n = message_num();
165     int i = 0;
166     screen_save();
167     term_clear();
168     while (true) {
169         int j;
170         int skey;
171         for (j = 0; (j < num_lines) && (i + j < n); j++) {
172             concptr msg = message_str(i + j);
173             c_prt((i + j < num_now ? TERM_WHITE : TERM_SLATE), msg, num_lines + 1 - j, 0);
174             if (!shower || !shower[0]) {
175                 continue;
176             }
177
178             concptr str = msg;
179             while ((str = angband_strstr(str, shower)) != nullptr) {
180                 int len = strlen(shower);
181                 term_putstr(str - msg, num_lines + 1 - j, len, TERM_YELLOW, shower);
182                 str += len;
183             }
184         }
185
186         for (; j < num_lines; j++) {
187             term_erase(0, num_lines + 1 - j, 255);
188         }
189
190         prt(format(_("以前のメッセージ %d-%d 全部で(%d)", "Message Recall (%d-%d of %d)"), i, i + j - 1, n), 0, 0);
191         prt(_("[ 'p' で更に古いもの, 'n' で更に新しいもの, '/' で検索, ESC で中断 ]", "[Press 'p' for older, 'n' for newer, ..., or ESCAPE]"), hgt - 1, 0);
192         skey = inkey_special(true);
193         if (skey == ESCAPE) {
194             break;
195         }
196
197         j = i;
198         switch (skey) {
199         case '=':
200             prt(_("強調: ", "Show: "), hgt - 1, 0);
201             strcpy(back_str, shower_str);
202             if (askfor(shower_str, 80)) {
203                 shower = shower_str[0] ? shower_str : nullptr;
204             } else {
205                 strcpy(shower_str, back_str);
206             }
207
208             continue;
209         case '/':
210         case KTRL('s'): {
211             prt(_("検索: ", "Find: "), hgt - 1, 0);
212             strcpy(back_str, finder_str);
213             if (!askfor(finder_str, 80)) {
214                 strcpy(finder_str, back_str);
215                 continue;
216             } else if (!finder_str[0]) {
217                 shower = nullptr;
218                 continue;
219             }
220
221             shower = finder_str;
222             for (int z = i + 1; z < n; z++) {
223                 concptr msg = message_str(z);
224                 if (angband_strstr(msg, finder_str)) {
225                     i = z;
226                     break;
227                 }
228             }
229         }
230
231         break;
232
233         case SKEY_TOP:
234             i = n - num_lines;
235             break;
236         case SKEY_BOTTOM:
237             i = 0;
238             break;
239         case '8':
240         case SKEY_UP:
241         case '\n':
242         case '\r':
243             i = std::min(i + 1, n - num_lines);
244             break;
245         case '+':
246             i = std::min(i + 10, n - num_lines);
247             break;
248         case 'p':
249         case KTRL('P'):
250         case ' ':
251         case SKEY_PGUP:
252             i = std::min(i + num_lines, n - num_lines);
253             break;
254         case 'n':
255         case KTRL('N'):
256         case SKEY_PGDOWN:
257             i = std::max(0, i - num_lines);
258             break;
259         case '-':
260             i = std::max(0, i - 10);
261             break;
262         case '2':
263         case SKEY_DOWN:
264             i = std::max(0, i - 1);
265             break;
266         }
267
268         if (i == j) {
269             bell();
270         }
271     }
272
273     screen_load();
274 }