OSDN Git Service

Merge pull request #2944 from backwardsEric/sprintf-refactor-init_angband
[hengbandforosx/hengbandosx.git] / src / cmd-io / cmd-macro.cpp
1 #include "cmd-io/cmd-macro.h"
2 #include "cmd-io/cmd-gameoption.h"
3 #include "cmd-io/macro-util.h"
4 #include "core/asking-player.h"
5 #include "game-option/input-options.h"
6 #include "io/files-util.h"
7 #include "io/input-key-acceptor.h"
8 #include "io/input-key-requester.h"
9 #include "io/read-pref-file.h"
10 #include "main/sound-of-music.h"
11 #include "system/player-type-definition.h"
12 #include "term/screen-processor.h"
13 #include "term/term-color-types.h"
14 #include "term/z-form.h"
15 #include "util/angband-files.h"
16 #include "util/int-char-converter.h"
17 #include "util/string-processor.h"
18 #include "view/display-messages.h"
19
20 /*!
21  * @brief マクロ情報をprefファイルに保存する /
22  * @param fname ファイル名
23  */
24 static void macro_dump(FILE **fpp, concptr fname)
25 {
26     static concptr mark = "Macro Dump";
27     char buf[1024];
28     path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
29     if (!open_auto_dump(fpp, buf, mark)) {
30         return;
31     }
32
33     auto_dump_printf(*fpp, _("\n# 自動マクロセーブ\n\n", "\n# Automatic macro dump\n\n"));
34
35     for (int i = 0; i < macro__num; i++) {
36         ascii_to_text(buf, macro__act[i], sizeof(buf));
37         auto_dump_printf(*fpp, "A:%s\n", buf);
38         ascii_to_text(buf, macro__pat[i], sizeof(buf));
39         auto_dump_printf(*fpp, "P:%s\n", buf);
40         auto_dump_printf(*fpp, "\n");
41     }
42
43     close_auto_dump(fpp, mark);
44 }
45
46 /*!
47  * @brief マクロのトリガーキーを取得する /
48  * Hack -- ask for a "trigger" (see below)
49  * @param buf キー表記を保管するバッファ
50  * @details
51  * <pre>
52  * Note the complex use of the "inkey()" function from "util.c".
53  *
54  * Note that both "flush()" calls are extremely important.
55  * </pre>
56  */
57 static void do_cmd_macro_aux(char *buf)
58 {
59     flush();
60     inkey_base = true;
61     char i = inkey();
62     int n = 0;
63     while (i) {
64         buf[n++] = i;
65         inkey_base = true;
66         inkey_scan = true;
67         i = inkey();
68     }
69
70     buf[n] = '\0';
71     flush();
72     char tmp[1024];
73     ascii_to_text(tmp, buf, sizeof(tmp));
74     term_addstr(-1, TERM_WHITE, tmp);
75 }
76
77 /*!
78  * @brief マクロのキー表記からアスキーコードを得てターミナルに表示する /
79  * Hack -- ask for a keymap "trigger" (see below)
80  * @param buf キー表記を取得するバッファ
81  * @details
82  * <pre>
83  * Note that both "flush()" calls are extremely important.  This may
84  * no longer be true, since "util.c" is much simpler now.
85  * </pre>
86  */
87 static void do_cmd_macro_aux_keymap(char *buf)
88 {
89     char tmp[1024];
90     flush();
91     buf[0] = inkey();
92     buf[1] = '\0';
93     ascii_to_text(tmp, buf, sizeof(tmp));
94     term_addstr(-1, TERM_WHITE, tmp);
95     flush();
96 }
97
98 /*!
99  * @brief キーマップをprefファイルにダンプする /
100  * Hack -- append all keymaps to the given file
101  * @param fname ファイルネーム
102  * @return エラーコード
103  * @details
104  */
105 static errr keymap_dump(concptr fname)
106 {
107     FILE *auto_dump_stream;
108     static concptr mark = "Keymap Dump";
109     char key[1024];
110     char buf[1024];
111     BIT_FLAGS mode;
112     if (rogue_like_commands) {
113         mode = KEYMAP_MODE_ROGUE;
114     } else {
115         mode = KEYMAP_MODE_ORIG;
116     }
117
118     path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
119     if (!open_auto_dump(&auto_dump_stream, buf, mark)) {
120         return -1;
121     }
122
123     auto_dump_printf(auto_dump_stream, _("\n# 自動キー配置セーブ\n\n", "\n# Automatic keymap dump\n\n"));
124     for (int i = 0; i < 256; i++) {
125         concptr act;
126         act = keymap_act[mode][i];
127         if (!act) {
128             continue;
129         }
130
131         buf[0] = (char)i;
132         buf[1] = '\0';
133         ascii_to_text(key, buf, sizeof(key));
134         ascii_to_text(buf, act, sizeof(buf));
135         auto_dump_printf(auto_dump_stream, "A:%s\n", buf);
136         auto_dump_printf(auto_dump_stream, "C:%d:%s\n", mode, key);
137     }
138
139     close_auto_dump(&auto_dump_stream, mark);
140     return 0;
141 }
142
143 /*!
144  * @brief マクロを設定するコマンドのメインルーチン /
145  * Interact with "macros"
146  * @details
147  * <pre>
148  * Note that the macro "action" must be defined before the trigger.
149  *
150  * Could use some helpful instructions on this page.
151  * </pre>
152  */
153 void do_cmd_macros(PlayerType *player_ptr)
154 {
155     char tmp[1024];
156     char buf[1024];
157     static char macro_buf[1024];
158     FILE *auto_dump_stream;
159     BIT_FLAGS mode = rogue_like_commands ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG;
160     screen_save();
161     term_clear();
162
163     auto print_macro_menu = [] {
164         prt(_("[ マクロの設定 ]", "Interact with Macros"), 2, 0);
165         prt(_("(1) ユーザー設定ファイルのロード", "(1) Load a user pref file"), 4, 5);
166         prt(_("(2) ファイルにマクロを追加", "(2) Append macros to a file"), 5, 5);
167         prt(_("(3) マクロの確認", "(3) Query a macro"), 6, 5);
168         prt(_("(4) マクロの作成", "(4) Create a macro"), 7, 5);
169         prt(_("(5) マクロの削除", "(5) Remove a macro"), 8, 5);
170         prt(_("(6) ファイルにキー配置を追加", "(6) Append keymaps to a file"), 9, 5);
171         prt(_("(7) キー配置の確認", "(7) Query a keymap"), 10, 5);
172         prt(_("(8) キー配置の作成", "(8) Create a keymap"), 11, 5);
173         prt(_("(9) キー配置の削除", "(9) Remove a keymap"), 12, 5);
174         prt(_("(0) マクロ行動の入力", "(0) Enter a new action"), 13, 5);
175     };
176     print_macro_menu();
177
178     while (true) {
179         msg_print(_("コマンド: ", "Command: "));
180         const int key = inkey();
181         if (key == ESCAPE) {
182             break;
183         }
184         clear_from(1);
185         print_macro_menu();
186
187         if (key == '1') {
188             prt(_("コマンド: ユーザー設定ファイルのロード", "Command: Load a user pref file"), 16, 0);
189             prt(_("ファイル: ", "File: "), 18, 0);
190             strnfmt(tmp, sizeof(tmp), "%s.prf", player_ptr->base_name);
191             if (!askfor(tmp, 80)) {
192                 continue;
193             }
194
195             errr err = process_pref_file(player_ptr, tmp, true);
196             if (-2 == err) {
197                 msg_format(_("標準の設定ファイル'%s'を読み込みました。", "Loaded default '%s'."), tmp);
198             } else if (err) {
199                 msg_format(_("'%s'の読み込みに失敗しました!", "Failed to load '%s'!"), tmp);
200             } else {
201                 msg_format(_("'%s'を読み込みました。", "Loaded '%s'."), tmp);
202             }
203         } else if (key == '2') {
204             prt(_("コマンド: マクロをファイルに追加する", "Command: Append macros to a file"), 16, 0);
205             prt(_("ファイル: ", "File: "), 18, 0);
206             strnfmt(tmp, sizeof(tmp), "%s.prf", player_ptr->base_name);
207             if (!askfor(tmp, 80)) {
208                 continue;
209             }
210
211             macro_dump(&auto_dump_stream, tmp);
212             msg_print(_("マクロを追加しました。", "Appended macros."));
213         } else if (key == '3') {
214             prt(_("コマンド: マクロの確認", "Command: Query a macro"), 16, 0);
215             prt(_("マクロ行動が(もしあれば)下に表示されます:", "Current action (if any) shown below:"), 20, 0);
216             prt(_("トリガーキー: ", "Trigger: "), 18, 0);
217             do_cmd_macro_aux(buf);
218             int k = macro_find_exact(buf);
219             if (k < 0) {
220                 msg_print(_("そのキーにはマクロは定義されていません。", "Found no macro."));
221             } else {
222                 // マクロの作成時に参照するためmacro_bufにコピーする
223                 strncpy(macro_buf, macro__act[k].data(), sizeof(macro_buf) - 1);
224                 // too long macro must die
225                 strncpy(tmp, macro_buf, 80);
226                 tmp[80] = '\0';
227                 ascii_to_text(buf, tmp, sizeof(buf));
228                 prt(buf, 22, 0);
229                 msg_print(_("マクロを確認しました。", "Found a macro."));
230             }
231         } else if (key == '4') {
232             prt(_("コマンド: マクロの作成", "Command: Create a macro"), 16, 0);
233             prt(_("トリガーキー: ", "Trigger: "), 18, 0);
234             do_cmd_macro_aux(buf);
235             c_prt(TERM_L_RED,
236                 _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
237                     "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."),
238                 22, 0);
239             prt(_("マクロ行動: ", "Action: "), 20, 0);
240             // 最後に参照したマクロデータを元に作成する(コピーを行えるように)
241             macro_buf[80] = '\0';
242             ascii_to_text(tmp, macro_buf, sizeof(tmp));
243             if (askfor(tmp, 80)) {
244                 text_to_ascii(macro_buf, tmp, sizeof(macro_buf));
245                 macro_add(buf, macro_buf);
246                 msg_print(_("マクロを追加しました。", "Added a macro."));
247             }
248         } else if (key == '5') {
249             prt(_("コマンド: マクロの削除", "Command: Remove a macro"), 16, 0);
250             prt(_("トリガーキー: ", "Trigger: "), 18, 0);
251             do_cmd_macro_aux(buf);
252             macro_add(buf, buf);
253             msg_print(_("マクロを削除しました。", "Removed a macro."));
254         } else if (key == '6') {
255             prt(_("コマンド: キー配置をファイルに追加する", "Command: Append keymaps to a file"), 16, 0);
256             prt(_("ファイル: ", "File: "), 18, 0);
257             strnfmt(tmp, sizeof(tmp), "%s.prf", player_ptr->base_name);
258             if (!askfor(tmp, 80)) {
259                 continue;
260             }
261
262             (void)keymap_dump(tmp);
263             msg_print(_("キー配置を追加しました。", "Appended keymaps."));
264         } else if (key == '7') {
265             prt(_("コマンド: キー配置の確認", "Command: Query a keymap"), 16, 0);
266             prt(_("マクロ行動が(もしあれば)下に表示されます:", "Current action (if any) shown below:"), 20, 0);
267             prt(_("押すキー: ", "Keypress: "), 18, 0);
268             do_cmd_macro_aux_keymap(buf);
269             concptr act = keymap_act[mode][(byte)(buf[0])];
270             if (!act) {
271                 msg_print(_("キー配置は定義されていません。", "Found no keymap."));
272             } else {
273                 // マクロの作成時に参照するためmacro_bufにコピーする
274                 strncpy(macro_buf, act, sizeof(macro_buf) - 1);
275                 // too long macro must die
276                 strncpy(tmp, macro_buf, 80);
277                 tmp[80] = '\0';
278                 ascii_to_text(buf, tmp, sizeof(buf));
279                 prt(buf, 22, 0);
280                 msg_print(_("キー配置を確認しました。", "Found a keymap."));
281             }
282         } else if (key == '8') {
283             prt(_("コマンド: キー配置の作成", "Command: Create a keymap"), 16, 0);
284             prt(_("押すキー: ", "Keypress: "), 18, 0);
285             do_cmd_macro_aux_keymap(buf);
286             c_prt(TERM_L_RED,
287                 _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
288                     "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."),
289                 22, 0);
290             prt(_("行動: ", "Action: "), 20, 0);
291             // 最後に参照したマクロデータを元に作成する(コピーを行えるように)
292             macro_buf[80] = '\0';
293             ascii_to_text(tmp, macro_buf, sizeof(tmp));
294             if (askfor(tmp, 80)) {
295                 text_to_ascii(macro_buf, tmp, sizeof(macro_buf));
296                 string_free(keymap_act[mode][(byte)(buf[0])]);
297                 keymap_act[mode][(byte)(buf[0])] = string_make(macro_buf);
298                 msg_print(_("キー配置を追加しました。", "Added a keymap."));
299             }
300         } else if (key == '9') {
301             prt(_("コマンド: キー配置の削除", "Command: Remove a keymap"), 16, 0);
302             prt(_("押すキー: ", "Keypress: "), 18, 0);
303             do_cmd_macro_aux_keymap(buf);
304             string_free(keymap_act[mode][(byte)(buf[0])]);
305             keymap_act[mode][(byte)(buf[0])] = nullptr;
306             msg_print(_("キー配置を削除しました。", "Removed a keymap."));
307         } else if (key == '0') {
308             prt(_("コマンド: マクロ行動の入力", "Command: Enter a new action"), 16, 0);
309             c_prt(TERM_L_RED,
310                 _("カーソルキーの左右でカーソル位置を移動。BackspaceかDeleteで一文字削除。",
311                     "Press Left/Right arrow keys to move cursor. Backspace/Delete to delete a char."),
312                 22, 0);
313             prt(_("マクロ行動: ", "Action: "), 20, 0);
314             buf[0] = '\0';
315             if (!askfor(buf, 80)) {
316                 continue;
317             }
318
319             text_to_ascii(macro_buf, buf, sizeof(macro_buf));
320         } else {
321             bell();
322         }
323
324         msg_erase();
325     }
326
327     screen_load();
328 }