OSDN Git Service

[Refactor] #39964 Removed the dependency from read-pref-file to autopick-pref-processor
[hengband/hengband.git] / src / io / read-pref-file.c
1 /*
2  * @file cmd-dump.c
3  * @brief プレイヤーのインターフェイスに関するコマンドの実装 / Interface commands
4  * @date 2020/03/01
5  * @author Mogami & Hourier
6  * -Mogami-
7  * remove_auto_dump(orig_file, mark)
8  *     Remove the old automatic dump of type "mark".
9  * auto_dump_printf(fmt, ...)
10  *     Dump a formatted string using fprintf().
11  * open_auto_dump(buf, mark)
12  *     Open a file, remove old dump, and add new header.
13  * close_auto_dump(void)
14  *     Add a footer, and close the file.
15  */
16
17 #include "angband.h"
18 #include "io/dump-remover.h"
19 #include "io/read-pref-file.h"
20 #include "io/interpret-pref-file.h"
21 #include "autopick/autopick-pref-processor.h"
22 #include "files.h" // 暫定。コールバック化して後で消す.
23 #include "world.h"
24
25 // todo コールバック関数に変更するので、いずれ消す.
26 #define PREF_TYPE_NORMAL   0
27 #define PREF_TYPE_AUTOPICK 1
28 #define PREF_TYPE_HISTPREF 2
29
30 char auto_dump_header[] = "# vvvvvvv== %s ==vvvvvvv";
31 char auto_dump_footer[] = "# ^^^^^^^== %s ==^^^^^^^";
32
33 // Mark strings for auto dump
34
35 // Variables for auto dump
36 static int auto_dump_line_num;
37
38 /*!
39  * todo 関数名を変更する
40  * @brief process_pref_fileのサブルーチン /
41  * Open the "user pref file" and parse it.
42  * @param creature_ptr プレーヤーへの参照ポインタ
43  * @param name 読み込むファイル名
44  * @param preftype prefファイルのタイプ
45  * @return エラーコード
46  */
47 static errr process_pref_file_aux(player_type *creature_ptr, concptr name, int preftype, void(*process_autopick_file_command)(char*))
48 {
49         FILE *fp;
50         fp = my_fopen(name, "r");
51         if (!fp) return -1;
52
53         char buf[1024];
54         char old[1024];
55         int line = -1;
56         errr err = 0;
57         bool bypass = FALSE;
58         while (my_fgets(fp, buf, sizeof(buf)) == 0)
59         {
60                 line++;
61                 if (!buf[0]) continue;
62
63 #ifdef JP
64                 if (!iskanji(buf[0]))
65 #endif
66                         if (iswspace(buf[0])) continue;
67
68                 if (buf[0] == '#') continue;
69                 strcpy(old, buf);
70
71                 /* Process "?:<expr>" */
72                 if ((buf[0] == '?') && (buf[1] == ':'))
73                 {
74                         char f;
75                         char *s;
76                         s = buf + 2;
77                         concptr v = process_pref_file_expr(creature_ptr, &s, &f);
78                         bypass = streq(v, "0");
79                         continue;
80                 }
81
82                 if (bypass) continue;
83
84                 /* Process "%:<file>" */
85                 if (buf[0] == '%')
86                 {
87                         static int depth_count = 0;
88                         if (depth_count > 20) continue;
89
90                         depth_count++;
91                         switch (preftype)
92                         {
93                         case PREF_TYPE_AUTOPICK:
94                                 (void)process_autopick_file(creature_ptr, buf + 2, process_autopick_file_command);
95                                 break;
96                         case PREF_TYPE_HISTPREF:
97                                 (void)process_histpref_file(creature_ptr, buf + 2, process_autopick_file_command);
98                                 break;
99                         default:
100                                 (void)process_pref_file(creature_ptr, buf + 2, process_autopick_file_command);
101                                 break;
102                         }
103
104                         depth_count--;
105                         continue;
106                 }
107
108                 err = interpret_pref_file(creature_ptr, buf);
109                 if (err != 0)
110                 {
111                         if (preftype != PREF_TYPE_AUTOPICK)
112                                 break;
113                         
114                         (*process_autopick_file_command)(buf);
115                         err = 0;
116                 }
117         }
118
119         if (err != 0)
120         {
121                 /* Print error message */
122                 /* ToDo: Add better error messages */
123                 msg_format(_("ファイル'%s'の%d行でエラー番号%dのエラー。", "Error %d in line %d of file '%s'."),
124                         _(name, err), line, _(err, name));
125                 msg_format(_("('%s'を解析中)", "Parsing '%s'"), old);
126                 msg_print(NULL);
127         }
128
129         my_fclose(fp);
130         return (err);
131 }
132
133
134 /*!
135  * @brief pref設定ファイルを読み込み設定を反映させる /
136  * Process the "user pref file" with the given name
137  * @param creature_ptr プレーヤーへの参照ポインタ
138  * @param name 読み込むファイル名
139  * @return エラーコード
140  * @details
141  * <pre>
142  * See the functions above for a list of legal "commands".
143  * We also accept the special "?" and "%" directives, which
144  * allow conditional evaluation and filename inclusion.
145  * </pre>
146  */
147 errr process_pref_file(player_type *creature_ptr, concptr name, void(*process_autopick_file_command)(char*))
148 {
149         char buf[1024];
150         path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, name);
151
152         errr err1 = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_NORMAL, process_autopick_file_command);
153         if (err1 > 0) return err1;
154
155         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
156         errr err2 = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_NORMAL, process_autopick_file_command);
157         if (err2 < 0 && !err1)
158                 return -2;
159
160         return err2;
161 }
162
163
164 /*!
165  * @brief 自動拾いファイルを読み込む /
166  * @param creature_ptr プレーヤーへの参照ポインタ
167  * @param name ファイル名
168  * @details
169  */
170 errr process_autopick_file(player_type *creature_ptr, concptr name, void(*process_autopick_file_command)(char*))
171 {
172         char buf[1024];
173         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
174         errr err = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_AUTOPICK, process_autopick_file_command);
175         return err;
176 }
177
178
179 /*!
180  * @brief プレイヤーの生い立ちファイルを読み込む /
181  * Process file for player's history editor.
182  * @param creature_ptr プレーヤーへの参照ポインタ
183  * @param name ファイル名
184  * @return エラーコード
185  * @details
186  */
187 errr process_histpref_file(player_type *creature_ptr, concptr name, void(*process_autopick_file_command)(char*))
188 {
189         bool old_character_xtra = current_world_ptr->character_xtra;
190         char buf[1024];
191         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
192
193         /* Hack -- prevent modification birth options in this file */
194         current_world_ptr->character_xtra = TRUE;
195         errr err = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_HISTPREF, process_autopick_file_command);
196         current_world_ptr->character_xtra = old_character_xtra;
197         return err;
198 }
199
200
201 /*!
202  * @brief prfファイルのフォーマットに従った内容を出力する /
203  * Dump a formatted line, using "vstrnfmt()".
204  * @param fmt 出力内容
205  */
206 void auto_dump_printf(FILE *auto_dump_stream, concptr fmt, ...)
207 {
208         va_list vp;
209         char buf[1024];
210         va_start(vp, fmt);
211         (void)vstrnfmt(buf, sizeof(buf), fmt, vp);
212         va_end(vp);
213         for (concptr p = buf; *p; p++)
214         {
215                 if (*p == '\n') auto_dump_line_num++;
216         }
217
218         fprintf(auto_dump_stream, "%s", buf);
219 }
220
221
222 /*!
223  * @brief prfファイルをファイルオープンする /
224  * Open file to append auto dump.
225  * @param buf ファイル名
226  * @param mark 出力するヘッダマーク
227  * @return ファイルポインタを取得できたらTRUEを返す
228  */
229 bool open_auto_dump(FILE **fpp, concptr buf, concptr mark)
230 {
231         char header_mark_str[80];
232         concptr auto_dump_mark = mark;
233         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
234         remove_auto_dump(buf, mark);
235         *fpp = my_fopen(buf, "a");
236         if (!fpp)
237         {
238                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
239                 msg_print(NULL);
240                 return FALSE;
241         }
242
243         fprintf(*fpp, "%s\n", header_mark_str);
244         auto_dump_line_num = 0;
245         auto_dump_printf(*fpp, _("# *警告!!* 以降の行は自動生成されたものです。\n",
246                 "# *Warning!*  The lines below are an automatic dump.\n"));
247         auto_dump_printf(*fpp, _("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
248                 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
249         return TRUE;
250 }
251
252 /*!
253  * @brief prfファイルをファイルクローズする /
254  * Append foot part and close auto dump.
255  * @return なし
256  */
257 void close_auto_dump(FILE **fpp, concptr auto_dump_mark)
258 {
259         char footer_mark_str[80];
260         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
261         auto_dump_printf(*fpp, _("# *警告!!* 以降の行は自動生成されたものです。\n",
262                 "# *Warning!*  The lines below are an automatic dump.\n"));
263         auto_dump_printf(*fpp, _("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
264                 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
265         fprintf(*fpp, "%s (%d)\n", footer_mark_str, auto_dump_line_num);
266         my_fclose(*fpp);
267 }