OSDN Git Service

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