OSDN Git Service

Merge branch 'For2.2.2-Fix-Hourier' into For2.2.2-Refactoring
[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/read-pref-file.h"
19 #include "io/interpret-pref-file.h"
20 #include "autopick.h"
21 #include "files.h" // 暫定。コールバック化して後で消す.
22 #include "world.h"
23
24 // todo コールバック関数に変更するので、いずれ消す.
25 #define PREF_TYPE_NORMAL   0
26 #define PREF_TYPE_AUTOPICK 1
27 #define PREF_TYPE_HISTPREF 2
28
29 // Mark strings for auto dump
30 static char auto_dump_header[] = "# vvvvvvv== %s ==vvvvvvv";
31 static char auto_dump_footer[] = "# ^^^^^^^== %s ==^^^^^^^";
32
33 // Variables for auto dump
34 static FILE *auto_dump_stream;
35 static concptr auto_dump_mark;
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)
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);
95                                 break;
96                         case PREF_TYPE_HISTPREF:
97                                 (void)process_histpref_file(creature_ptr, buf + 2);
98                                 break;
99                         default:
100                                 (void)process_pref_file(creature_ptr, buf + 2);
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)
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);
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);
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)
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);
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)
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);
196         current_world_ptr->character_xtra = old_character_xtra;
197         return err;
198 }
199
200
201 /*!
202  * @brief prf出力内容を消去する /
203  * Remove old lines automatically generated before.
204  * @param orig_file 消去を行うファイル名
205  */
206 static void remove_auto_dump(concptr orig_file)
207 {
208         char header_mark_str[80];
209         char footer_mark_str[80];
210         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
211         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
212         size_t mark_len = strlen(footer_mark_str);
213         FILE *orig_fff;
214         orig_fff = my_fopen(orig_file, "r");
215         if (!orig_fff) return;
216
217         char tmp_file[1024];
218         FILE *tmp_fff;
219         tmp_fff = my_fopen_temp(tmp_file, 1024);
220         if (!tmp_fff)
221         {
222                 msg_format(_("一時ファイル %s を作成できませんでした。", "Failed to create temporary file %s."), tmp_file);
223                 msg_print(NULL);
224                 return;
225         }
226
227         char buf[1024];
228         bool between_mark = FALSE;
229         bool changed = FALSE;
230         int line_num = 0;
231         long header_location = 0;
232         while (TRUE)
233         {
234                 if (my_fgets(orig_fff, buf, sizeof(buf)))
235                 {
236                         if (between_mark)
237                         {
238                                 fseek(orig_fff, header_location, SEEK_SET);
239                                 between_mark = FALSE;
240                                 continue;
241                         }
242                         else
243                         {
244                                 break;
245                         }
246                 }
247
248                 if (!between_mark)
249                 {
250                         if (!strcmp(buf, header_mark_str))
251                         {
252                                 header_location = ftell(orig_fff);
253                                 line_num = 0;
254                                 between_mark = TRUE;
255                                 changed = TRUE;
256                         }
257                         else
258                         {
259                                 fprintf(tmp_fff, "%s\n", buf);
260                         }
261
262                         continue;
263                 }
264
265                 if (!strncmp(buf, footer_mark_str, mark_len))
266                 {
267                         int tmp;
268                         if (!sscanf(buf + mark_len, " (%d)", &tmp)
269                                 || tmp != line_num)
270                         {
271                                 fseek(orig_fff, header_location, SEEK_SET);
272                         }
273
274                         between_mark = FALSE;
275                         continue;
276                 }
277
278                 line_num++;
279         }
280
281         my_fclose(orig_fff);
282         my_fclose(tmp_fff);
283
284         if (changed)
285         {
286                 tmp_fff = my_fopen(tmp_file, "r");
287                 orig_fff = my_fopen(orig_file, "w");
288                 while (!my_fgets(tmp_fff, buf, sizeof(buf)))
289                         fprintf(orig_fff, "%s\n", buf);
290
291                 my_fclose(orig_fff);
292                 my_fclose(tmp_fff);
293         }
294
295         fd_kill(tmp_file);
296 }
297
298
299 /*!
300  * @brief prfファイルのフォーマットに従った内容を出力する /
301  * Dump a formatted line, using "vstrnfmt()".
302  * @param fmt 出力内容
303  */
304 void auto_dump_printf(concptr fmt, ...)
305 {
306         va_list vp;
307         char buf[1024];
308         va_start(vp, fmt);
309         (void)vstrnfmt(buf, sizeof(buf), fmt, vp);
310         va_end(vp);
311         for (concptr p = buf; *p; p++)
312         {
313                 if (*p == '\n') auto_dump_line_num++;
314         }
315
316         fprintf(auto_dump_stream, "%s", buf);
317 }
318
319
320 /*!
321  * @brief prfファイルをファイルオープンする /
322  * Open file to append auto dump.
323  * @param buf ファイル名
324  * @param mark 出力するヘッダマーク
325  * @return ファイルポインタを取得できたらTRUEを返す
326  */
327 bool open_auto_dump(concptr buf, concptr mark)
328 {
329         char header_mark_str[80];
330         auto_dump_mark = mark;
331         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
332         remove_auto_dump(buf);
333         auto_dump_stream = my_fopen(buf, "a");
334         if (!auto_dump_stream)
335         {
336                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
337                 msg_print(NULL);
338                 return FALSE;
339         }
340
341         fprintf(auto_dump_stream, "%s\n", header_mark_str);
342         auto_dump_line_num = 0;
343         auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
344                 "# *Warning!*  The lines below are an automatic dump.\n"));
345         auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
346                 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
347         return TRUE;
348 }
349
350 /*!
351  * @brief prfファイルをファイルクローズする /
352  * Append foot part and close auto dump.
353  * @return なし
354  */
355 void close_auto_dump(void)
356 {
357         char footer_mark_str[80];
358         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
359         auto_dump_printf(_("# *警告!!* 以降の行は自動生成されたものです。\n",
360                 "# *Warning!*  The lines below are an automatic dump.\n"));
361         auto_dump_printf(_("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
362                 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
363         fprintf(auto_dump_stream, "%s (%d)\n", footer_mark_str, auto_dump_line_num);
364         my_fclose(auto_dump_stream);
365 }