OSDN Git Service

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