OSDN Git Service

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