OSDN Git Service

[Refactor] #40413 Renamed my_f*() to angband_f*() in util.c/h; propably f means fuxk...
[hengband/hengband.git] / src / core / show-file.c
1 #include "core/show-file.h"
2 #include "io/files-util.h"
3 #include "system/angband-version.h"
4 #include "term/gameterm.h"
5 #include "term/term-color-types.h"
6
7 /*!
8  * todo 表示とそれ以外を分割する
9  * @brief ファイル内容の一行をコンソールに出力する
10  * Display single line of on-line help file
11  * @param str 出力する文字列
12  * @param cy コンソールの行
13  * @param shower 確認中
14  * @return なし
15  * @details
16  * <pre>
17  * You can insert some special color tag to change text color.
18  * Such as...
19  * WHITETEXT [[[[y|SOME TEXT WHICH IS DISPLAYED IN YELLOW| WHITETEXT
20  * A colored segment is between "[[[[y|" and the last "|".
21  * You can use any single character in place of the "|".
22  * </pre>
23  */
24 static void show_file_aux_line(concptr str, int cy, concptr shower)
25 {
26         char lcstr[1024];
27         if (shower)
28         {
29                 strcpy(lcstr, str);
30                 str_tolower(lcstr);
31         }
32
33         int cx = 0;
34         Term_gotoxy(cx, cy);
35
36         static const char tag_str[] = "[[[[";
37         byte color = TERM_WHITE;
38         char in_tag = '\0';
39         for (int i = 0; str[i];)
40         {
41                 int len = strlen(&str[i]);
42                 int showercol = len + 1;
43                 int bracketcol = len + 1;
44                 int endcol = len;
45                 concptr ptr;
46                 if (shower)
47                 {
48                         ptr = angband_strstr(&lcstr[i], shower);
49                         if (ptr) showercol = ptr - &lcstr[i];
50                 }
51
52                 ptr = in_tag ? angband_strchr(&str[i], in_tag) : angband_strstr(&str[i], tag_str);
53                 if (ptr) bracketcol = ptr - &str[i];
54                 if (bracketcol < endcol) endcol = bracketcol;
55                 if (showercol < endcol) endcol = showercol;
56
57                 Term_addstr(endcol, color, &str[i]);
58                 cx += endcol;
59                 i += endcol;
60
61                 if (shower && endcol == showercol)
62                 {
63                         int showerlen = strlen(shower);
64                         Term_addstr(showerlen, TERM_YELLOW, &str[i]);
65                         cx += showerlen;
66                         i += showerlen;
67                         continue;
68                 }
69
70                 if (endcol != bracketcol) continue;
71
72                 if (in_tag)
73                 {
74                         i++;
75                         in_tag = '\0';
76                         color = TERM_WHITE;
77                         continue;
78                 }
79
80                 i += sizeof(tag_str) - 1;
81                 color = color_char_to_attr(str[i]);
82                 if (color == 255 || str[i + 1] == '\0')
83                 {
84                         color = TERM_WHITE;
85                         Term_addstr(-1, TERM_WHITE, tag_str);
86                         cx += sizeof(tag_str) - 1;
87                         continue;
88                 }
89
90                 i++;
91                 in_tag = str[i];
92                 i++;
93         }
94
95         Term_erase(cx, cy, 255);
96 }
97
98
99 /*!
100  * todo 表示とそれ以外を分割する
101  * @brief ファイル内容をコンソールに出力する
102  * Recursive file perusal.
103  * @param creature_ptr プレーヤーへの参照ポインタ
104  * @param show_version TRUEならばコンソール上にゲームのバージョンを表示する
105  * @param name ファイル名の文字列
106  * @param what 内容キャプションの文字列
107  * @param line 表示の現在行
108  * @param mode オプション
109  * @return なし
110  * @details
111  * <pre>
112  * Process various special text in the input file, including
113  * the "menu" structures used by the "help file" system.
114  * Return FALSE on 'q' to exit from a deep, otherwise TRUE.
115  * </pre>
116  */
117 bool show_file(player_type *creature_ptr, bool show_version, concptr name, concptr what, int line, BIT_FLAGS mode)
118 {
119         int wid, hgt;
120         Term_get_size(&wid, &hgt);
121
122         char finder_str[81];
123         strcpy(finder_str, "");
124
125         char shower_str[81];
126         strcpy(shower_str, "");
127
128         char caption[128];
129         strcpy(caption, "");
130
131         char hook[68][32];
132         for (int i = 0; i < 68; i++)
133         {
134                 hook[i][0] = '\0';
135         }
136
137         char filename[1024];
138         strcpy(filename, name);
139         int n = strlen(filename);
140
141         concptr tag = NULL;
142         for (int i = 0; i < n; i++)
143         {
144                 if (filename[i] == '#')
145                 {
146                         filename[i] = '\0';
147                         tag = filename + i + 1;
148                         break;
149                 }
150         }
151
152         name = filename;
153         FILE *fff = NULL;
154         char path[1024];
155         if (what)
156         {
157                 strcpy(caption, what);
158                 strcpy(path, name);
159                 fff = angband_fopen(path, "r");
160         }
161
162         if (!fff)
163         {
164                 sprintf(caption, _("ヘルプ・ファイル'%s'", "Help file '%s'"), name);
165                 path_build(path, sizeof(path), ANGBAND_DIR_HELP, name);
166                 fff = angband_fopen(path, "r");
167         }
168
169         if (!fff)
170         {
171                 sprintf(caption, _("スポイラー・ファイル'%s'", "Info file '%s'"), name);
172                 path_build(path, sizeof(path), ANGBAND_DIR_INFO, name);
173                 fff = angband_fopen(path, "r");
174         }
175
176         if (!fff)
177         {
178                 path_build(path, sizeof(path), ANGBAND_DIR, name);
179
180                 for (int i = 0; path[i]; i++)
181                         if ('\\' == path[i])
182                                 path[i] = PATH_SEP[0];
183
184                 sprintf(caption, _("スポイラー・ファイル'%s'", "Info file '%s'"), name);
185                 fff = angband_fopen(path, "r");
186         }
187
188         if (!fff)
189         {
190                 msg_format(_("'%s'をオープンできません。", "Cannot open '%s'."), name);
191                 msg_print(NULL);
192
193                 return TRUE;
194         }
195
196         int skey;
197         int next = 0;
198         int size = 0;
199         int back = 0;
200         bool menu = FALSE;
201         char buf[1024];
202         bool reverse = (line < 0);
203         while (TRUE)
204         {
205                 char *str = buf;
206                 if (angband_fgets(fff, buf, sizeof(buf))) break;
207                 if (!prefix(str, "***** "))
208                 {
209                         next++;
210                         continue;
211                 }
212
213                 if ((str[6] == '[') && isalpha(str[7]))
214                 {
215                         int k = str[7] - 'A';
216                         menu = TRUE;
217                         if ((str[8] == ']') && (str[9] == ' '))
218                         {
219                                 strncpy(hook[k], str + 10, 31);
220                                 hook[k][31] = '\0';
221                         }
222
223                         continue;
224                 }
225
226                 if (str[6] != '<') continue;
227
228                 size_t len = strlen(str);
229                 if (str[len - 1] == '>')
230                 {
231                         str[len - 1] = '\0';
232                         if (tag && streq(str + 7, tag)) line = next;
233                 }
234         }
235
236         size = next;
237         int rows = hgt - 4;
238         if (line == -1)
239                 line = ((size - 1) / rows)*rows;
240
241         Term_clear();
242
243         concptr find = NULL;
244         while (TRUE)
245         {
246                 if (line >= size - rows)
247                         line = size - rows;
248                 if (line < 0) line = 0;
249
250                 if (next > line)
251                 {
252                         angband_fclose(fff);
253                         fff = angband_fopen(path, "r");
254                         if (!fff) return FALSE;
255
256                         next = 0;
257                 }
258
259                 while (next < line)
260                 {
261                         if (angband_fgets(fff, buf, sizeof(buf))) break;
262                         if (prefix(buf, "***** ")) continue;
263                         next++;
264                 }
265
266                 int row_count = 0;
267                 concptr shower = NULL;
268                 for (int i = 0; i < rows; i++)
269                 {
270                         concptr str = buf;
271                         if (!i) line = next;
272                         if (angband_fgets(fff, buf, sizeof(buf))) break;
273                         if (prefix(buf, "***** ")) continue;
274                         next++;
275                         if (find && !i)
276                         {
277                                 char lc_buf[1024];
278                                 strcpy(lc_buf, str);
279                                 str_tolower(lc_buf);
280                                 if (!angband_strstr(lc_buf, find)) continue;
281                         }
282
283                         find = NULL;
284                         show_file_aux_line(str, i + 2, shower);
285                         row_count++;
286                 }
287
288                 while (row_count < rows)
289                 {
290                         Term_erase(0, row_count + 2, 255);
291                         row_count++;
292                 }
293
294                 if (find)
295                 {
296                         bell();
297                         line = back;
298                         find = NULL;
299                         continue;
300                 }
301
302                 if (show_version)
303                 {
304                         prt(format(_("[変愚蛮怒 %d.%d.%d, %s, %d/%d]", "[Hengband %d.%d.%d, %s, Line %d/%d]"),
305                                 FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH,
306                                 caption, line, size), 0, 0);
307                 }
308                 else
309                 {
310                         prt(format(_("[%s, %d/%d]", "[%s, Line %d/%d]"),
311                                 caption, line, size), 0, 0);
312                 }
313
314                 if (size <= rows)
315                 {
316                         prt(_("[キー:(?)ヘルプ (ESC)終了]", "[Press ESC to exit.]"), hgt - 1, 0);
317                 }
318                 else
319                 {
320 #ifdef JP
321                         if (reverse)
322                                 prt("[キー:(RET/スペース)↑ (-)↓ (?)ヘルプ (ESC)終了]", hgt - 1, 0);
323                         else
324                                 prt("[キー:(RET/スペース)↓ (-)↑ (?)ヘルプ (ESC)終了]", hgt - 1, 0);
325 #else
326                         prt("[Press Return, Space, -, =, /, |, or ESC to exit.]", hgt - 1, 0);
327 #endif
328                 }
329
330                 skey = inkey_special(TRUE);
331                 switch (skey)
332                 {
333                 case '?':
334                         if (strcmp(name, _("jhelpinfo.txt", "helpinfo.txt")) != 0)
335                                 show_file(creature_ptr, TRUE, _("jhelpinfo.txt", "helpinfo.txt"), NULL, 0, mode);
336                         break;
337                 case '=':
338                         prt(_("強調: ", "Show: "), hgt - 1, 0);
339
340                         char back_str[81];
341                         strcpy(back_str, shower_str);
342                         if (askfor(shower_str, 80))
343                         {
344                                 if (shower_str[0])
345                                 {
346                                         str_tolower(shower_str);
347                                         shower = shower_str;
348                                 }
349                                 else shower = NULL;
350                         }
351                         else strcpy(shower_str, back_str);
352                         break;
353
354                 case '/':
355                 case KTRL('s'):
356                         prt(_("検索: ", "Find: "), hgt - 1, 0);
357                         strcpy(back_str, finder_str);
358                         if (askfor(finder_str, 80))
359                         {
360                                 if (finder_str[0])
361                                 {
362                                         find = finder_str;
363                                         back = line;
364                                         line = line + 1;
365                                         str_tolower(finder_str);
366                                         shower = finder_str;
367                                 }
368                                 else shower = NULL;
369                         }
370                         else strcpy(finder_str, back_str);
371                         break;
372
373                 case '#':
374                 {
375                         char tmp[81];
376                         prt(_("行: ", "Goto Line: "), hgt - 1, 0);
377                         strcpy(tmp, "0");
378
379                         if (askfor(tmp, 80)) line = atoi(tmp);
380                         break;
381                 }
382
383                 case SKEY_TOP:
384                         line = 0;
385                         break;
386
387                 case SKEY_BOTTOM:
388                         line = ((size - 1) / rows) * rows;
389                         break;
390
391                 case '%':
392                 {
393                         char tmp[81];
394                         prt(_("ファイル・ネーム: ", "Goto File: "), hgt - 1, 0);
395                         strcpy(tmp, _("jhelp.hlp", "help.hlp"));
396
397                         if (askfor(tmp, 80))
398                         {
399                                 if (!show_file(creature_ptr, TRUE, tmp, NULL, 0, mode)) skey = 'q';
400                         }
401
402                         break;
403                 }
404
405                 case '-':
406                         line = line + (reverse ? rows : -rows);
407                         if (line < 0) line = 0;
408                         break;
409
410                 case SKEY_PGUP:
411                         line = line - rows;
412                         if (line < 0) line = 0;
413                         break;
414
415                 case '\n':
416                 case '\r':
417                         line = line + (reverse ? -1 : 1);
418                         if (line < 0) line = 0;
419                         break;
420
421                 case '8':
422                 case SKEY_UP:
423                         line--;
424                         if (line < 0) line = 0;
425                         break;
426
427                 case '2':
428                 case SKEY_DOWN:
429                         line++;
430                         break;
431
432                 case ' ':
433                         line = line + (reverse ? -rows : rows);
434                         if (line < 0) line = 0;
435                         break;
436
437                 case SKEY_PGDOWN:
438                         line = line + rows;
439                         break;
440                 }
441
442                 if (menu)
443                 {
444                         int key = -1;
445                         if (!(skey & SKEY_MASK) && isalpha(skey))
446                                 key = skey - 'A';
447
448                         if ((key > -1) && hook[key][0])
449                         {
450                                 /* Recurse on that file */
451                                 if (!show_file(creature_ptr, TRUE, hook[key], NULL, 0, mode))
452                                         skey = 'q';
453                         }
454                 }
455
456                 if (skey == '|')
457                 {
458                         FILE *ffp;
459                         char buff[1024];
460                         char xtmp[82];
461
462                         strcpy(xtmp, "");
463
464                         if (!get_string(_("ファイル名: ", "File name: "), xtmp, 80)) continue;
465                         angband_fclose(fff);
466                         path_build(buff, sizeof(buff), ANGBAND_DIR_USER, xtmp);
467
468                         /* Hack -- Re-Open the file */
469                         fff = angband_fopen(path, "r");
470
471                         ffp = angband_fopen(buff, "w");
472
473                         if (!(fff && ffp))
474                         {
475                                 msg_print(_("ファイルを開けません。", "Failed to open file."));
476                                 skey = ESCAPE;
477                                 break;
478                         }
479
480                         sprintf(xtmp, "%s: %s", creature_ptr->name, what ? what : caption);
481                         angband_fputs(ffp, xtmp, 80);
482                         angband_fputs(ffp, "\n", 80);
483
484                         while (!angband_fgets(fff, buff, sizeof(buff)))
485                                 angband_fputs(ffp, buff, 80);
486                         angband_fclose(fff);
487                         angband_fclose(ffp);
488                         fff = angband_fopen(path, "r");
489                 }
490
491                 if ((skey == ESCAPE) || (skey == '<')) break;
492
493                 if (skey == KTRL('q')) skey = 'q';
494
495                 if (skey == 'q') break;
496         }
497
498         angband_fclose(fff);
499         return (skey != 'q');
500 }