OSDN Git Service

[Refactor] #39964 Removed the dependency from read-pref-file to autopick-pref-processor
[hengband/hengband.git] / src / cmd / cmd-process-screen.c
1 /*!
2 * @file cmd-process-screen.c
3 * @brief 記念撮影のセーブとロード
4 * @date 2020/04/22
5 * @Author Hourier
6 */
7
8 #include "angband.h"
9 #include "cmd/cmd-process-screen.h"
10 #include "cmd/cmd-draw.h"
11 #include "files.h"
12 #include "gameterm.h"
13
14 // Encode the screen colors
15 static char hack[17] = "dwsorgbuDWvyRGBU";
16
17 static concptr tags[4] = { "HEADER_START:", "HEADER_END:", "FOOTER_START:", "FOOTER_END:", };
18 static concptr html_head[3] = { "<html>\n<body text=\"#ffffff\" bgcolor=\"#000000\">\n", "<pre>", 0, };
19 static concptr html_foot[3] = { "</pre>\n", "</body>\n</html>\n", 0, };
20
21 /*!
22  * todo io/ 以下に移したいところだが、このファイルの行数も大したことがないので一旦保留
23  * @brief 一時ファイルを読み込み、ファイルに書き出す
24  * @param fff ファイルへの参照ポインタ
25  * @param tempfff 一時ファイルへの参照ポインタ
26  * @param buf バッファ
27  * @param buf_size バッファサイズ
28  * @param num_tag タグ番号
29  */
30 static void read_temporary_file(FILE *fff, FILE *tmpfff, char buf[], size_t buf_size, int num_tag)
31 {
32         bool is_first_line = TRUE;
33         int next_tag = num_tag + 1;
34         while (!my_fgets(tmpfff, buf, buf_size))
35         {
36                 if (is_first_line)
37                 {
38                         if (strncmp(buf, tags[num_tag], strlen(tags[num_tag])) == 0)
39                                 is_first_line = FALSE;
40
41                         continue;
42                 }
43
44                 if (strncmp(buf, tags[next_tag], strlen(tags[next_tag])) == 0)
45                         break;
46
47                 fprintf(fff, "%s\n", buf);
48         }
49 }
50
51
52 /*!
53  * @brief 記念撮影を1行ダンプする
54  * @param wid 幅
55  * @param y 現在の行位置
56  * @param fff 記念撮影ファイルへの参照ポインタ
57  * @return なし
58  */
59 static void screen_dump_one_line(int wid, int y, FILE *fff)
60 {
61         TERM_COLOR a = 0, old_a = 0;
62         char c = ' ';
63         for (TERM_LEN x = 0; x < wid - 1; x++)
64         {
65                 concptr cc = NULL;
66                 (void)(Term_what(x, y, &a, &c));
67                 switch (c)
68                 {
69                 case '&': cc = "&amp;"; break;
70                 case '<': cc = "&lt;"; break;
71                 case '>': cc = "&gt;"; break;
72 #ifdef WINDOWS
73                 case 0x1f: c = '.'; break;
74                 case 0x7f: c = (a == 0x09) ? '%' : '#'; break;
75 #endif
76                 }
77
78                 a = a & 0x0F;
79                 if ((y == 0 && x == 0) || a != old_a)
80                 {
81                         int rv = angband_color_table[a][1];
82                         int gv = angband_color_table[a][2];
83                         int bv = angband_color_table[a][3];
84                         fprintf(fff, "%s<font color=\"#%02x%02x%02x\">",
85                                 ((y == 0 && x == 0) ? "" : "</font>"), rv, gv, bv);
86                         old_a = a;
87                 }
88
89                 if (cc)
90                         fprintf(fff, "%s", cc);
91                 else
92                         fprintf(fff, "%c", c);
93         }
94 }
95
96
97 /*!
98  * @brief 記念撮影を行方向にスイープする
99  * @param wid 幅
100  * @param hgt 高さ
101  * @param fff 記念撮影ファイルへの参照ポインタ
102  * @return なし
103  */
104 static void screen_dump_lines(int wid, int hgt, FILE *fff)
105 {
106         for (TERM_LEN y = 0; y < hgt; y++)
107         {
108                 if (y != 0)
109                         fprintf(fff, "\n");
110
111                 screen_dump_one_line(wid, y, fff);
112         }
113 }
114
115
116 /*!
117  * @brief ファイルへ書き込めない場合にエラーを表示する
118  * @param fff ダンプファイルへの参照ポインタ
119  * @param buf バッファ
120  * @return ファイルへ書き込めるならTRUE、書き込めないならFALSE
121  */
122 static bool check_screen_html_can_open(FILE *fff, char *filename, int message)
123 {
124         if (fff) return TRUE;
125         if (message == 0) return FALSE;
126
127         msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), filename);
128         msg_print(NULL);
129         return FALSE;
130 }
131
132
133 /*!
134  * @brief HTMLヘッダを書き込む
135  * @param tmpfff 一時ファイルへの参照ポインタ
136  * @param fff 記念撮影ファイルへの参照ポインタ
137  * @param buf バッファ
138  * @param buf_size バッファサイズ
139  */
140 static void write_html_header(FILE *tmpfff, FILE *fff, char buf[], size_t buf_size)
141 {
142         if (tmpfff)
143         {
144                 read_temporary_file(fff, tmpfff, buf, buf_size, 0);
145                 return;
146         }
147
148         for (int i = 0; html_head[i]; i++)
149                 fputs(html_head[i], fff);
150 }
151
152
153 /*!
154  * @brief HTMLフッタを書き込む
155  * @param tmpfff 一時ファイルへの参照ポインタ
156  * @param fff 記念撮影ファイルへの参照ポインタ
157  * @param buf バッファ
158  * @param buf_size バッファサイズ
159  */
160 static void write_html_footer(FILE *tmpfff, FILE *fff, char buf[], size_t buf_size)
161 {
162         fprintf(fff, "</font>");
163         if (!tmpfff)
164         {
165                 for (int i = 0; html_foot[i]; i++)
166                         fputs(html_foot[i], fff);
167         }
168         else
169         {
170                 rewind(tmpfff);
171                 read_temporary_file(fff, tmpfff, buf, buf_size, 2);
172                 my_fclose(tmpfff);
173         }
174
175         fprintf(fff, "\n");
176 }
177
178
179 void do_cmd_save_screen_html_aux(char *filename, int message)
180 {
181         TERM_LEN wid, hgt;
182         Term_get_size(&wid, &hgt);
183         FILE_TYPE(FILE_TYPE_TEXT);
184         FILE *fff;
185         fff = my_fopen(filename, "w");
186         if (!check_screen_html_can_open(fff, filename, message)) return;
187
188         if (message) screen_save();
189
190         char buf[2048];
191         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "htmldump.prf");
192         FILE *tmpfff;
193         tmpfff = my_fopen(buf, "r");
194         write_html_header(tmpfff, fff, buf, sizeof(buf));
195         screen_dump_lines(wid, hgt, fff);
196         write_html_footer(tmpfff, fff, buf, sizeof(buf));
197         my_fclose(fff);
198         if (message)
199         {
200                 msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
201                 msg_print(NULL);
202         }
203
204         if (message)
205                 screen_load();
206 }
207
208
209 /*!
210  * @brief HTML方式で記念撮影する / Save a screen dump to a file
211  * @param なし
212  * @return なし
213  */
214 static void do_cmd_save_screen_html(void)
215 {
216         char buf[1024], tmp[256] = "screen.html";
217
218         if (!get_string(_("ファイル名: ", "File name: "), tmp, 80))
219                 return;
220         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
221
222         msg_print(NULL);
223
224         do_cmd_save_screen_html_aux(buf, 1);
225 }
226
227
228 /*!
229  * @brief 記念撮影の方式を問い合わせる
230  * @param html_dump HTMLダンプするか否か
231  * @return ダンプするならTRUE、キャンセルならFALSE
232  */
233 static bool ask_html_dump(bool *html_dump)
234 {
235         while (TRUE)
236         {
237                 char c = inkey();
238                 if (c == 'Y' || c == 'y')
239                 {
240                         *html_dump = FALSE;
241                         return TRUE;
242                 }
243                 
244                 if (c == 'H' || c == 'h')
245                 {
246                         *html_dump = TRUE;
247                         return TRUE;
248                 }
249
250                 prt("", 0, 0);
251                 return FALSE;
252         }
253
254         // コンパイル警告対応.
255         return FALSE;
256 }
257
258
259 /*!
260  * @brief ファイルへ書き込めない場合にエラーを表示する
261  * @param fff ダンプファイルへの参照ポインタ
262  * @param buf バッファ
263  * @return ファイルへ書き込めるならTRUE、書き込めないならFALSE
264  */
265 static bool check_screen_text_can_open(FILE *fff, char buf[])
266 {
267         if (fff) return TRUE;
268
269         msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), buf);
270         msg_print(NULL);
271         return FALSE;
272 }
273
274
275 /*!
276  * todo どこかバグっていて、(恐らく初期化されていない)変な文字列まで出力される
277  * @brief テキスト方式で記念撮影する
278  * @param wid 幅
279  * @param hgt 高さ
280  * @return 記念撮影に成功したらTRUE、ファイルが開けなかったらFALSE
281  */
282 static bool do_cmd_save_screen_text(int wid, int hgt)
283 {
284         TERM_COLOR a = 0;
285         SYMBOL_CODE c = ' ';
286         FILE *fff;
287         char buf[1024];
288         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
289         FILE_TYPE(FILE_TYPE_TEXT);
290         fff = my_fopen(buf, "w");
291         if (!check_screen_text_can_open(fff, buf)) return FALSE;
292
293         screen_save();
294         for (TERM_LEN y = 0; y < hgt; y++)
295         {
296                 TERM_LEN x;
297                 for (x = 0; x < wid - 1; x++)
298                 {
299                         (void)(Term_what(x, y, &a, &c));
300                         buf[x] = c;
301                 }
302
303                 buf[x] = '\0';
304                 fprintf(fff, "%s\n", buf);
305         }
306
307         fprintf(fff, "\n");
308         for (TERM_LEN y = 0; y < hgt; y++)
309         {
310                 TERM_LEN x;
311                 for (x = 0; x < wid - 1; x++)
312                 {
313                         (void)(Term_what(x, y, &a, &c));
314                         buf[x] = hack[a & 0x0F];
315                 }
316
317                 buf[x] = '\0';
318                 fprintf(fff, "%s\n", buf);
319         }
320
321         fprintf(fff, "\n");
322         my_fclose(fff);
323         msg_print(_("画面(記念撮影)をファイルに書き出しました。", "Screen dump saved."));
324         msg_print(NULL);
325         screen_load();
326         return TRUE;
327 }
328
329
330 /*!
331  * @brief 記念撮影のためにグラフィック使用をOFFにする
332  * @param creature_ptr プレーヤーへの参照ポインタ
333  * @param handle_stuff 画面更新用の関数ポインタ
334  * @return 記念撮影直前のグラフィックオプション
335  */
336 static bool update_use_graphics(player_type *creature_ptr, void(*handle_stuff)(player_type*), void(*process_autopick_file_command)(char*))
337 {
338         if (!use_graphics) return TRUE;
339
340         use_graphics = FALSE;
341         reset_visuals(creature_ptr, process_autopick_file_command);
342         creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
343         (*handle_stuff)(creature_ptr);
344         return FALSE;
345 }
346
347
348 /*
349  * Save a screen dump to a file
350  * @param creature_ptr プレーヤーへの参照ポインタ
351  * @param handle_stuff 画面更新用の関数ポインタ
352  * @return なし
353  */
354 void do_cmd_save_screen(player_type *creature_ptr, void(*handle_stuff)(player_type*), void(*process_autopick_file_command)(char*))
355 {
356         prt(_("記念撮影しますか? [(y)es/(h)tml/(n)o] ", "Save screen dump? [(y)es/(h)tml/(n)o] "), 0, 0);
357         bool html_dump;
358         if (!ask_html_dump(&html_dump)) return;
359
360         int wid, hgt;
361         Term_get_size(&wid, &hgt);
362
363         bool old_use_graphics = update_use_graphics(creature_ptr, handle_stuff, process_autopick_file_command);
364
365         if (html_dump)
366         {
367                 do_cmd_save_screen_html();
368                 do_cmd_redraw(creature_ptr);
369         }
370         else if (!do_cmd_save_screen_text(wid, hgt))
371         {
372                 return;
373         }
374
375         if (old_use_graphics) return;
376
377         use_graphics = TRUE;
378         reset_visuals(creature_ptr, process_autopick_file_command);
379         creature_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY);
380         handle_stuff(creature_ptr);
381 }
382
383
384 /*!
385  * @brief 白文字だけ画面に描画する (todo 目的は不明瞭)
386  * @param buf 描画用バッファ
387  * @param fff 記念撮影ファイルへの参照ポインタ
388  * @param wid 幅
389  * @param hgt 高さ
390  * @return ファイルが読み込めなくなったらFALSEで抜ける
391  */
392 static bool draw_white_characters(char buf[], FILE *fff, int wid, int hgt)
393 {
394         bool okay = TRUE;
395         for (TERM_LEN y = 0; okay; y++)
396         {
397                 if (!fgets(buf, 1024, fff)) okay = FALSE;
398
399                 if (buf[0] == '\n' || buf[0] == '\0') break;
400                 if (y >= hgt) continue;
401
402                 for (TERM_LEN x = 0; x < wid - 1; x++)
403                 {
404                         if (buf[x] == '\n' || buf[x] == '\0') break;
405
406                         Term_draw(x, y, TERM_WHITE, buf[x]);
407                 }
408         }
409
410         return okay;
411 }
412
413
414 /*!
415  * @brief 白以外の文字を画面に描画する (todo 目的は不明瞭)
416  * @param buf 描画用バッファ
417  * @param fff 記念撮影ファイルへの参照ポインタ
418  * @param wid 幅
419  * @param hgt 高さ
420  * @param 白文字が途中で読み込めなくなっていたらTRUE
421  * @return なし
422  */
423 static void draw_colored_characters(char buf[], FILE *fff, int wid, int hgt, bool okay)
424 {
425         TERM_COLOR a = TERM_DARK;
426         SYMBOL_CODE c = ' ';
427         for (TERM_LEN y = 0; okay; y++)
428         {
429                 if (!fgets(buf, 1024, fff)) okay = FALSE;
430
431                 if (buf[0] == '\n' || buf[0] == '\0') break;
432                 if (y >= hgt) continue;
433
434                 for (TERM_LEN x = 0; x < wid - 1; x++)
435                 {
436                         if (buf[x] == '\n' || buf[x] == '\0') break;
437
438                         (void)(Term_what(x, y, &a, &c));
439                         for (int i = 0; i < 16; i++)
440                         {
441                                 if (hack[i] == buf[x]) a = (byte)i;
442                         }
443
444                         Term_draw(x, y, a, c);
445                 }
446         }
447 }
448
449
450 /*
451  * @brief Load a screen dump from a file
452  * @param なし
453  * @return なし
454  */
455 void do_cmd_load_screen(void)
456 {
457         FILE *fff;
458         char buf[1024];
459         TERM_LEN wid, hgt;
460         Term_get_size(&wid, &hgt);
461         path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
462         fff = my_fopen(buf, "r");
463         if (!fff)
464         {
465                 msg_format(_("%s を開くことができませんでした。", "Failed to open %s."), buf);
466                 msg_print(NULL);
467                 return;
468         }
469
470         screen_save();
471         Term_clear();
472         bool okay = draw_white_characters(buf, fff, wid, hgt);
473         draw_colored_characters(buf, fff, wid, hgt, okay);
474
475         my_fclose(fff);
476         prt(_("ファイルに書き出された画面(記念撮影)をロードしました。", "Screen dump loaded."), 0, 0);
477         flush();
478         inkey();
479         screen_load();
480 }