OSDN Git Service

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