OSDN Git Service

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