OSDN Git Service

Merge branch 'master' of https://github.com/hengband/hengband
[hengbandforosx/hengbandosx.git] / src / autopick / autopick-reader-writer.cpp
1 #include "autopick/autopick-reader-writer.h"
2 #include "autopick/autopick-initializer.h"
3 #include "autopick/autopick-pref-processor.h"
4 #include "autopick/autopick-util.h"
5 #include "io/files-util.h"
6 #include "io/read-pref-file.h"
7 #include "system/player-type-definition.h"
8 #include "util/angband-files.h"
9 #include "util/string-processor.h"
10 #include "view/display-messages.h"
11 #include <stdexcept>
12 #include <string>
13 #include <string_view>
14 #include <vector>
15
16 /*!
17  * @brief Load an autopick preference file
18  */
19 void autopick_load_pref(PlayerType *player_ptr, bool disp_mes)
20 {
21     GAME_TEXT buf[80];
22     init_autopick();
23     angband_strcpy(buf, pickpref_filename(player_ptr, PT_WITH_PNAME).data(), sizeof(buf));
24     errr err = process_autopick_file(player_ptr, buf);
25     if (err == 0 && disp_mes) {
26         msg_format(_("%sを読み込みました。", "Loaded '%s'."), buf);
27     }
28
29     if (err < 0) {
30         angband_strcpy(buf, pickpref_filename(player_ptr, PT_DEFAULT).data(), sizeof(buf));
31         err = process_autopick_file(player_ptr, buf);
32         if (err == 0 && disp_mes) {
33             msg_format(_("%sを読み込みました。", "Loaded '%s'."), buf);
34         }
35     }
36
37     if (err && disp_mes) {
38         msg_print(_("自動拾い設定ファイルの読み込みに失敗しました。", "Failed to reload autopick preference."));
39     }
40 }
41
42 /*!
43  * @brief Get file name for autopick preference
44  */
45 std::string pickpref_filename(PlayerType *player_ptr, int filename_mode)
46 {
47     static const char namebase[] = _("picktype", "pickpref");
48
49     switch (filename_mode) {
50     case PT_DEFAULT:
51         return format("%s.prf", namebase);
52
53     case PT_WITH_PNAME:
54         return format("%s-%s.prf", namebase, player_ptr->base_name);
55
56     default:
57         throw std::invalid_argument(format("The value of argument 'filename_mode' is invalid: %d", filename_mode));
58     }
59 }
60
61 /*!
62  * @brief Read whole lines of a file to memory
63  */
64 static std::vector<concptr> read_text_lines(std::string_view filename)
65 {
66     const auto &path = path_build(ANGBAND_DIR_USER, filename);
67     auto *fff = angband_fopen(path, FileOpenMode::READ);
68     if (!fff) {
69         return {};
70     }
71
72     auto lines = 0;
73     std::vector<concptr> lines_list(MAX_LINES);
74     char buf[1024]{};
75     while (angband_fgets(fff, buf, sizeof(buf)) == 0) {
76         lines_list[lines++] = string_make(buf);
77         if (is_greater_autopick_max_line(lines)) {
78             break;
79         }
80     }
81
82     if (lines == 0) {
83         lines_list[0] = string_make("");
84     }
85
86     angband_fclose(fff);
87     return lines_list;
88 }
89
90 /*!
91  * @brief Copy the default autopick file to the user directory
92  */
93 static void prepare_default_pickpref(PlayerType *player_ptr)
94 {
95     const std::vector<std::string> messages = { _("あなたは「自動拾いエディタ」を初めて起動しました。", "You have activated the Auto-Picker Editor for the first time."),
96         _("自動拾いのユーザー設定ファイルがまだ書かれていないので、", "Since user pref file for autopick is not yet created,"),
97         _("基本的な自動拾い設定ファイルをlib/pref/picktype.prfからコピーします。", "the default setting is loaded from lib/pref/pickpref.prf .") };
98
99     const auto filename = pickpref_filename(player_ptr, PT_DEFAULT);
100     for (const auto &message : messages) {
101         msg_print(message);
102     }
103
104     msg_print(nullptr);
105     const auto &path_user = path_build(ANGBAND_DIR_USER, filename);
106     auto *user_fp = angband_fopen(path_user, FileOpenMode::WRITE);
107     if (!user_fp) {
108         return;
109     }
110
111     fprintf(user_fp, "#***\n");
112     for (const auto &message : messages) {
113         fprintf(user_fp, "#***  %s\n", message.data());
114     }
115
116     fprintf(user_fp, "#***\n\n\n");
117     const auto &path_pref = path_build(ANGBAND_DIR_PREF, filename);
118     auto *pref_fp = angband_fopen(path_pref, FileOpenMode::READ);
119     if (!pref_fp) {
120         angband_fclose(user_fp);
121         return;
122     }
123
124     char buf[1024]{};
125     while (!angband_fgets(pref_fp, buf, sizeof(buf))) {
126         fprintf(user_fp, "%s\n", buf);
127     }
128
129     angband_fclose(user_fp);
130     angband_fclose(pref_fp);
131 }
132
133 /*!
134  * @brief Read an autopick prefence file to memory
135  * Prepare default if no user file is found
136  */
137 std::vector<concptr> read_pickpref_text_lines(PlayerType *player_ptr, int *filename_mode_p)
138 {
139     /* Try a filename with player name */
140     *filename_mode_p = PT_WITH_PNAME;
141     auto filename = pickpref_filename(player_ptr, *filename_mode_p);
142     std::vector<concptr> lines_list = read_text_lines(filename);
143
144     if (lines_list.empty()) {
145         *filename_mode_p = PT_DEFAULT;
146         filename = pickpref_filename(player_ptr, *filename_mode_p);
147         lines_list = read_text_lines(filename);
148     }
149
150     if (lines_list.empty()) {
151         prepare_default_pickpref(player_ptr);
152         lines_list = read_text_lines(filename);
153     }
154
155     if (lines_list.empty()) {
156         lines_list.resize(MAX_LINES);
157         lines_list[0] = string_make("");
158     }
159
160     return lines_list;
161 }
162
163 /*!
164  * @brief Write whole lines of memory to a file.
165  */
166 bool write_text_lines(std::string_view filename, const std::vector<concptr> &lines)
167 {
168     const auto &path = path_build(ANGBAND_DIR_USER, filename);
169     auto *fff = angband_fopen(path, FileOpenMode::WRITE);
170     if (!fff) {
171         return false;
172     }
173
174     for (const auto *line : lines) {
175         if (line == nullptr) {
176             break;
177         }
178
179         angband_fputs(fff, line, 1024);
180     }
181
182     angband_fclose(fff);
183     return true;
184 }