OSDN Git Service

[Refactor] #40457 Moved io-dump-related files from io/ to io-dump/
[hengbandforosx/hengbandosx.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 "system/angband.h"
18 #include "io-dump/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 "io/files-util.h"
23 #include "io/pref-file-expressor.h"
24 #include "world/world.h"
25 #include "system/system-variables.h"
26 #include "autopick/autopick-reader-writer.h"
27
28 // todo コールバック関数に変更するので、いずれ消す.
29 #define PREF_TYPE_NORMAL   0
30 #define PREF_TYPE_AUTOPICK 1
31 #define PREF_TYPE_HISTPREF 2
32
33 char auto_dump_header[] = "# vvvvvvv== %s ==vvvvvvv";
34 char auto_dump_footer[] = "# ^^^^^^^== %s ==^^^^^^^";
35
36 // Mark strings for auto dump
37
38 // Variables for auto dump
39 static int auto_dump_line_num;
40
41 /*!
42  * todo 関数名を変更する
43  * @brief process_pref_fileのサブルーチン /
44  * Open the "user pref file" and parse it.
45  * @param creature_ptr プレーヤーへの参照ポインタ
46  * @param name 読み込むファイル名
47  * @param preftype prefファイルのタイプ
48  * @return エラーコード
49  */
50 static errr process_pref_file_aux(player_type *creature_ptr, concptr name, int preftype, void(*process_autopick_file_command)(char*))
51 {
52         FILE *fp;
53         fp = my_fopen(name, "r");
54         if (!fp) return -1;
55
56         char buf[1024];
57         char old[1024];
58         int line = -1;
59         errr err = 0;
60         bool bypass = FALSE;
61         while (my_fgets(fp, buf, sizeof(buf)) == 0)
62         {
63                 line++;
64                 if (!buf[0]) continue;
65
66 #ifdef JP
67                 if (!iskanji(buf[0]))
68 #endif
69                         if (iswspace(buf[0])) continue;
70
71                 if (buf[0] == '#') continue;
72                 strcpy(old, buf);
73
74                 /* Process "?:<expr>" */
75                 if ((buf[0] == '?') && (buf[1] == ':'))
76                 {
77                         char f;
78                         char *s;
79                         s = buf + 2;
80                         concptr v = process_pref_file_expr(creature_ptr, &s, &f);
81                         bypass = streq(v, "0");
82                         continue;
83                 }
84
85                 if (bypass) continue;
86
87                 /* Process "%:<file>" */
88                 if (buf[0] == '%')
89                 {
90                         static int depth_count = 0;
91                         if (depth_count > 20) continue;
92
93                         depth_count++;
94                         switch (preftype)
95                         {
96                         case PREF_TYPE_AUTOPICK:
97                                 (void)process_autopick_file(creature_ptr, buf + 2, process_autopick_file_command);
98                                 break;
99                         case PREF_TYPE_HISTPREF:
100                                 (void)process_histpref_file(creature_ptr, buf + 2, process_autopick_file_command);
101                                 break;
102                         default:
103                                 (void)process_pref_file(creature_ptr, buf + 2, process_autopick_file_command);
104                                 break;
105                         }
106
107                         depth_count--;
108                         continue;
109                 }
110
111                 err = interpret_pref_file(creature_ptr, buf);
112                 if (err != 0)
113                 {
114                         if (preftype != PREF_TYPE_AUTOPICK)
115                                 break;
116                         
117                         (*process_autopick_file_command)(buf);
118                         err = 0;
119                 }
120         }
121
122         if (err != 0)
123         {
124                 /* Print error message */
125                 /* ToDo: Add better error messages */
126                 msg_format(_("ファイル'%s'の%d行でエラー番号%dのエラー。", "Error %d in line %d of file '%s'."),
127                         _(name, err), line, _(err, name));
128                 msg_format(_("('%s'を解析中)", "Parsing '%s'"), old);
129                 msg_print(NULL);
130         }
131
132         my_fclose(fp);
133         return (err);
134 }
135
136
137 /*!
138  * @brief pref設定ファイルを読み込み設定を反映させる /
139  * Process the "user pref file" with the given name
140  * @param creature_ptr プレーヤーへの参照ポインタ
141  * @param name 読み込むファイル名
142  * @return エラーコード
143  * @details
144  * <pre>
145  * See the functions above for a list of legal "commands".
146  * We also accept the special "?" and "%" directives, which
147  * allow conditional evaluation and filename inclusion.
148  * </pre>
149  */
150 errr process_pref_file(player_type *creature_ptr, concptr name, void(*process_autopick_file_command)(char*))
151 {
152         char buf[1024];
153         path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, name);
154
155         errr err1 = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_NORMAL, process_autopick_file_command);
156         if (err1 > 0) return err1;
157
158         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
159         errr err2 = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_NORMAL, process_autopick_file_command);
160         if (err2 < 0 && !err1)
161                 return -2;
162
163         return err2;
164 }
165
166
167 /*!
168  * @brief 自動拾いファイルを読み込む /
169  * @param creature_ptr プレーヤーへの参照ポインタ
170  * @param name ファイル名
171  * @details
172  */
173 errr process_autopick_file(player_type *creature_ptr, concptr name, void(*process_autopick_file_command)(char*))
174 {
175         char buf[1024];
176         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
177         errr err = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_AUTOPICK, process_autopick_file_command);
178         return err;
179 }
180
181
182 /*!
183  * @brief プレイヤーの生い立ちファイルを読み込む /
184  * Process file for player's history editor.
185  * @param creature_ptr プレーヤーへの参照ポインタ
186  * @param name ファイル名
187  * @return エラーコード
188  * @details
189  */
190 errr process_histpref_file(player_type *creature_ptr, concptr name, void(*process_autopick_file_command)(char*))
191 {
192         bool old_character_xtra = current_world_ptr->character_xtra;
193         char buf[1024];
194         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, name);
195
196         /* Hack -- prevent modification birth options in this file */
197         current_world_ptr->character_xtra = TRUE;
198         errr err = process_pref_file_aux(creature_ptr, buf, PREF_TYPE_HISTPREF, process_autopick_file_command);
199         current_world_ptr->character_xtra = old_character_xtra;
200         return err;
201 }
202
203
204 /*!
205  * @brief prfファイルのフォーマットに従った内容を出力する /
206  * Dump a formatted line, using "vstrnfmt()".
207  * @param fmt 出力内容
208  */
209 void auto_dump_printf(FILE *auto_dump_stream, concptr fmt, ...)
210 {
211         va_list vp;
212         char buf[1024];
213         va_start(vp, fmt);
214         (void)vstrnfmt(buf, sizeof(buf), fmt, vp);
215         va_end(vp);
216         for (concptr p = buf; *p; p++)
217         {
218                 if (*p == '\n') auto_dump_line_num++;
219         }
220
221         fprintf(auto_dump_stream, "%s", buf);
222 }
223
224
225 /*!
226  * @brief prfファイルをファイルオープンする /
227  * Open file to append auto dump.
228  * @param buf ファイル名
229  * @param mark 出力するヘッダマーク
230  * @return ファイルポインタを取得できたらTRUEを返す
231  */
232 bool open_auto_dump(FILE **fpp, concptr buf, concptr mark)
233 {
234         char header_mark_str[80];
235         concptr auto_dump_mark = mark;
236         sprintf(header_mark_str, auto_dump_header, auto_dump_mark);
237         remove_auto_dump(buf, mark);
238         *fpp = my_fopen(buf, "a");
239         if (!fpp)
240         {
241                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
242                 msg_print(NULL);
243                 return FALSE;
244         }
245
246         fprintf(*fpp, "%s\n", header_mark_str);
247         auto_dump_line_num = 0;
248         auto_dump_printf(*fpp, _("# *警告!!* 以降の行は自動生成されたものです。\n",
249                 "# *Warning!*  The lines below are an automatic dump.\n"));
250         auto_dump_printf(*fpp, _("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
251                 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
252         return TRUE;
253 }
254
255 /*!
256  * @brief prfファイルをファイルクローズする /
257  * Append foot part and close auto dump.
258  * @return なし
259  */
260 void close_auto_dump(FILE **fpp, concptr auto_dump_mark)
261 {
262         char footer_mark_str[80];
263         sprintf(footer_mark_str, auto_dump_footer, auto_dump_mark);
264         auto_dump_printf(*fpp, _("# *警告!!* 以降の行は自動生成されたものです。\n",
265                 "# *Warning!*  The lines below are an automatic dump.\n"));
266         auto_dump_printf(*fpp, _("# *警告!!* 後で自動的に削除されるので編集しないでください。\n",
267                 "# Don't edit them; changes will be deleted and replaced automatically.\n"));
268         fprintf(*fpp, "%s (%d)\n", footer_mark_str, auto_dump_line_num);
269         my_fclose(*fpp);
270 }
271
272 /*!
273  * @brief 全ユーザプロファイルをロードする / Load some "user pref files"
274  * @paaram player_ptr プレーヤーへの参照ポインタ
275  * @return なし
276  * @note
277  * Modified by Arcum Dagsson to support
278  * separate macro files for different realms.
279  */
280 void load_all_pref_files(player_type* player_ptr)
281 {
282     char buf[1024];
283     sprintf(buf, "user.prf");
284     process_pref_file(player_ptr, buf, process_autopick_file_command);
285     sprintf(buf, "user-%s.prf", ANGBAND_SYS);
286     process_pref_file(player_ptr, buf, process_autopick_file_command);
287     sprintf(buf, "%s.prf", rp_ptr->title);
288     process_pref_file(player_ptr, buf, process_autopick_file_command);
289     sprintf(buf, "%s.prf", cp_ptr->title);
290     process_pref_file(player_ptr, buf, process_autopick_file_command);
291     sprintf(buf, "%s.prf", player_ptr->base_name);
292     process_pref_file(player_ptr, buf, process_autopick_file_command);
293     if (player_ptr->realm1 != REALM_NONE) {
294         sprintf(buf, "%s.prf", realm_names[player_ptr->realm1]);
295         process_pref_file(player_ptr, buf, process_autopick_file_command);
296     }
297
298     if (player_ptr->realm2 != REALM_NONE) {
299         sprintf(buf, "%s.prf", realm_names[player_ptr->realm2]);
300         process_pref_file(player_ptr, buf, process_autopick_file_command);
301     }
302
303     autopick_load_pref(player_ptr, FALSE);
304 }
305
306 /*!
307  * @brief 生い立ちメッセージをファイルからロードする。
308  * @return なし
309  */
310 bool read_histpref(player_type *creature_ptr, void (*process_autopick_file_command)(char *))
311 {
312     char buf[80];
313     errr err;
314     int i, j, n;
315     char *s, *t;
316     char temp[64 * 4];
317     char histbuf[HISTPREF_LIMIT];
318
319     if (!get_check(_("生い立ち設定ファイルをロードしますか? ", "Load background history preference file? ")))
320         return FALSE;
321
322     histbuf[0] = '\0';
323     histpref_buf = histbuf;
324
325     sprintf(buf, _("histedit-%s.prf", "histpref-%s.prf"), creature_ptr->base_name);
326     err = process_histpref_file(creature_ptr, buf, process_autopick_file_command);
327
328     if (0 > err) {
329         strcpy(buf, _("histedit.prf", "histpref.prf"));
330         err = process_histpref_file(creature_ptr, buf, process_autopick_file_command);
331     }
332
333     if (err) {
334         msg_print(_("生い立ち設定ファイルの読み込みに失敗しました。", "Failed to load background history preference."));
335         msg_print(NULL);
336         histpref_buf = NULL;
337         return FALSE;
338     } else if (!histpref_buf[0]) {
339         msg_print(_("有効な生い立ち設定はこのファイルにありません。", "There does not exist valid background history preference."));
340         msg_print(NULL);
341         histpref_buf = NULL;
342         return FALSE;
343     }
344
345     for (i = 0; i < 4; i++)
346         creature_ptr->history[i][0] = '\0';
347
348     /* loop */
349     for (s = histpref_buf; *s == ' '; s++)
350         ;
351
352     n = strlen(s);
353     while ((n > 0) && (s[n - 1] == ' '))
354         s[--n] = '\0';
355
356     roff_to_buf(s, 60, temp, sizeof(temp));
357     t = temp;
358     for (i = 0; i < 4; i++) {
359         if (t[0] == 0)
360             break;
361         else {
362             strcpy(creature_ptr->history[i], t);
363             t += strlen(t) + 1;
364         }
365     }
366
367     for (i = 0; i < 4; i++) {
368         /* loop */
369         for (j = 0; creature_ptr->history[i][j]; j++)
370             ;
371
372         for (; j < 59; j++)
373             creature_ptr->history[i][j] = ' ';
374         creature_ptr->history[i][59] = '\0';
375     }
376
377     histpref_buf = NULL;
378     return TRUE;
379 }