OSDN Git Service

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