OSDN Git Service

Merge pull request #1058 from sikabane-works/feature/enum-virtue
[hengbandforosx/hengbandosx.git] / src / main-win / main-win-cfg-reader.cpp
1 /*!
2  * @file main-win-cfg-reader.cpp
3  * @brief Windows版固有実装(.cfgファイル処理)
4  */
5
6 #include "main-win/main-win-cfg-reader.h"
7 #include "main-win/main-win-define.h"
8 #include "main-win/main-win-file-utils.h"
9 #include "main-win/main-win-tokenizer.h"
10 #include "main-win/main-win-windows.h"
11 #include "term/z-term.h"
12 #include "util/angband-files.h"
13
14 #include "main/sound-definitions-table.h"
15
16 // 1つの項目に設定可能な最大ファイル数
17 #define SAMPLE_MAX 16
18
19 /*!
20  * @brief マップのキーを生成する
21  * @details
22  * typeを上位16ビット, valを下位16ビットに設定した値をマップのキーとする。
23  * @param type the "actions" value of "term_xtra()". see:z-term.h TERM_XTRA_xxxxx
24  * @param val the 2nd parameter of "term_xtra()"
25  * @return 生成したキーを返す
26  */
27 static cfg_key make_cfg_key(int type, int val)
28 {
29     return ((type << 16) | (val & 0xffff));
30 }
31
32 /*!
33  * @brief マップのキーに対応する値を取得する
34  * @param key1_type the "actions" value of "term_xtra()". see:z-term.h TERM_XTRA_xxxxx
35  * @param key2_val the 2nd parameter of "term_xtra()"
36  * @return キーに対応する値を返す。登録されていない場合はNULLを返す。
37  */
38 static cfg_values *get_map_value(cfg_map *map, int key1_type, int key2_val)
39 {
40     cfg_values *value = NULL;
41     auto ite = map->find(make_cfg_key(key1_type, key2_val));
42     if (ite != map->end()) {
43         value = ite->second;
44     }
45     return value;
46 }
47
48 /*!
49  * @brief 登録されている中からランダムに選択する
50  * @param type the "actions" value of "term_xtra()". see:z-term.h TERM_XTRA_xxxxx
51  * @param val the 2nd parameter of "term_xtra()"
52  * @return キーに対応する値、複数のファイル名の中からからランダムに返す。登録されていない場合はNULLを返す。
53  */
54 concptr CfgData::get_rand(int key1_type, int key2_val)
55 {
56     cfg_values *filenames = get_map_value(this->map, key1_type, key2_val);
57     if (!filenames) {
58         return NULL;
59     }
60
61     return filenames->at(Rand_external(filenames->size()));
62 }
63
64 bool CfgData::has_key(int key1_type, int key2_val)
65 {
66     auto ite = map->find(make_cfg_key(key1_type, key2_val));
67     return (ite != map->end());
68 }
69
70 void CfgData::insert(int key1_type, int key2_val, cfg_values *value)
71 {
72     this->map->insert(std::make_pair(make_cfg_key(key1_type, key2_val), value));
73 }
74
75 /*!
76  * @param dir .cfgファイルのディレクトリ
77  * @param files .cfgファイル名。複数指定可能で、最初に見つかったファイルから読み取る。
78  */
79 CfgReader::CfgReader(concptr dir, std::initializer_list<concptr> files)
80 {
81     this->dir = dir;
82     this->cfg_path = find_any_file(dir, files);
83 }
84
85 /*!
86  * @brief データの読み込みを行う。
87  * @param sections 読み取るデータの指定
88  * @return 読み込んだデータを登録したCfgDataを返す。
89  */
90 CfgData *CfgReader::read_sections(std::initializer_list<cfg_section> sections)
91 {
92     CfgData *result = new CfgData();
93
94     if (!check_file(this->cfg_path.c_str())) {
95         return result;
96     }
97
98     char key_buf[80];
99     char buf[MAIN_WIN_MAX_PATH];
100     char path[MAIN_WIN_MAX_PATH];
101     char *tokens[SAMPLE_MAX];
102
103     for (auto &section : sections) {
104     
105         bool has_data = false;
106         int index = 0;
107         concptr read_key;
108         while ((read_key = section.key_at(index, key_buf)) != NULL) {
109             GetPrivateProfileStringA(section.section_name, read_key, "", buf, MAIN_WIN_MAX_PATH, this->cfg_path.c_str());
110             if (*buf != '\0') {
111                 cfg_values *filenames = new cfg_values();
112                 const int num = tokenize_whitespace(buf, SAMPLE_MAX, tokens);
113                 for (int j = 0; j < num; j++) {
114                     path_build(path, MAIN_WIN_MAX_PATH, dir, tokens[j]);
115                     if (check_file(path))
116                         filenames->push_back(string_make(tokens[j]));
117                 }
118                 if (filenames->empty()) {
119                     delete filenames;
120                 } else {
121                     result->insert(section.action_type, index, filenames);
122                     has_data = true;
123                 }
124             }
125
126             index++;
127         }
128
129         if (section.has_data) {
130             *(section.has_data) = has_data;
131         }
132     }
133
134     return result;
135 }