1 /*
2 * This file is part of EasyRPG Player.
3 *
4 * EasyRPG Player is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * EasyRPG Player is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <string>
19 #include <algorithm>
20
21 #include "window_keyboard.h"
22 #include "game_system.h"
23 #include "input.h"
24 #include "bitmap.h"
25 #include "font.h"
26
27 const char* const Window_Keyboard::DONE = "<Done>";
28 const char* const Window_Keyboard::SPACE = "SPACE";
29 const char* const Window_Keyboard::NEXT_PAGE = "<Page>";
30 const char* const Window_Keyboard::DONE_JP = "<決定>";
31 const char* const Window_Keyboard::DONE_RU = "<OK>";
32 const char* const Window_Keyboard::DONE_KO = "<결정>";
33 const char* const Window_Keyboard::DONE_ZH_CN = "<确定>";
34 const char* const Window_Keyboard::DONE_ZH_TW = "<確定>";
35
36 /*
37 * Hiragana <-> Katakana; Hangul 1 <-> Hangul 2; Simp. Chinese 1 <-> Simp. Chinese 2;
38 * Trad. Chinese 1 <-> Trad. Chinese 2; Rus.Cyrillic <-> Rus.Latin; letter <-> symbol
39 */
40
41 Keyboard_Layout Window_Keyboard::layouts[Window_Keyboard::MODE_END] = {
42 {
43 "<かな>",
44 { // Hiragana
45 {"あ", "い", "う", "え", "お", "が", "ぎ", "ぐ", "げ", "ご"},
46 {"か", "き", "く", "け", "こ", "ざ", "じ", "ず", "ぜ", "ぞ"},
47 {"さ", "し", "す", "せ", "そ", "だ", "ぢ", "づ", "で", "ど"},
48 {"た", "ち", "つ", "て", "と", "ば", "び", "ぶ", "べ", "ぼ"},
49 {"な", "に", "ぬ", "ね", "の", "ぱ", "ぴ", "ぷ", "ぺ", "ぽ"},
50 {"は", "ひ", "ふ", "へ", "ほ", "ぁ", "ぃ", "ぅ", "ぇ", "ぉ"},
51 {"ま", "み", "む", "め", "も", "っ", "ゃ", "ゅ", "ょ", "ゎ"},
52 {"や", "ゆ", "よ", "わ", "ん", "ー", "~", "・", "=", "☆"},
53 {"ら", "り", "る", "れ", "ろ", "ヴ", NEXT_PAGE, "", DONE}
54 }
55 },
56 {
57 "<カナ>",
58 { // Katakana
59 {"ア", "イ", "ウ", "エ", "オ", "ガ", "ギ", "グ", "ゲ", "ゴ"},
60 {"カ", "キ", "ク", "ケ", "コ", "ザ", "ジ", "ズ", "ゼ", "ゾ"},
61 {"サ", "シ", "ス", "セ", "ソ", "ダ", "ヂ", "ヅ", "デ", "ド"},
62 {"タ", "チ", "ツ", "テ", "ト", "バ", "ビ", "ブ", "ベ", "ボ"},
63 {"ナ", "ニ", "ヌ", "ネ", "ノ", "パ", "ピ", "プ", "ペ", "ポ"},
64 {"ハ", "ヒ", "フ", "ヘ", "ホ", "ァ", "ィ", "ゥ", "ェ", "ォ"},
65 {"マ", "ミ", "ム", "メ", "モ", "ッ", "ャ", "ュ", "ョ", "ヮ"},
66 {"ヤ", "ユ", "ヨ", "ワ", "ン", "ー", "~", "・", "=", "☆"},
67 {"ラ", "リ", "ル", "レ", "ロ", "ヴ", NEXT_PAGE, "", DONE}
68 }
69 },
70 {
71 "<앞P>",
72 { // Hangul 1
73 {"가", "갸", "거", "겨", "고", "교", "구", "계", "그", "기"},
74 {"나", "냐", "너", "녀", "노", "뇨", "누", "뉴", "느", "녹"},
75 {"다", "댜", "더", "뎌", "도", "됴", "두", "듀", "드", "디"},
76 {"라", "랴", "러", "려", "로", "료", "루", "류", "르", "리"},
77 {"마", "먀", "머", "며", "모", "묘", "무", "물", "므", "미"},
78 {"바", "뱌", "버", "벼", "보", "뵤", "부", "뷰", "비", "밤"},
79 {"사", "색", "서", "세", "소", "쇼", "수", "슈", "신", "심"},
80 {"아", "야", "어", "여", "오", "요", "우", "유", "으", "이"},
81 {"〜", "·", ".", "☆", SPACE, "", NEXT_PAGE, "", DONE}
82 }
83
84 },
85 {
86 "<뒤P>",
87 { // Hangul 2
88 {"자", "쟈", "저", "져", "조", "죠", "주", "쥬", "즈", "지"},
89 {"차", "챠", "처", "쳐", "초", "쵸", "추", "츄", "츠", "치"},
90 {"카", "캬", "커", "켜", "코", "쿄", "쿠", "큐", "크", "키"},
91 {"타", "탸", "터", "텨", "토", "툐", "투", "튜", "트", "티"},
92 {"파", "퍄", "퍼", "펴", "포", "표", "푸", "퓨", "프", "피"},
93 {"하", "햐", "허", "혀", "호", "효", "후", "휴", "흐", "해"},
94 {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"},
95 {"진", "녘", "의", "민", "예", "건", "현", "운", "걔", "임"},
96 {"영", "은", "성", "준", SPACE, "", NEXT_PAGE, "", DONE}
97 },
98 },
99 {
100 "<翻页>",
101 { // Simp. Chinese 1
102 {"阿", "艾", "安", "奥", "巴", "拜", "班", "邦", "贝", "本"},
103 {"比", "宾", "波", "伯", "布", "查", "达", "丹", "当", "道"},
104 {"德", "登", "迪", "蒂", "丁", "度", "杜", "顿", "多", "厄"},
105 {"尔", "恩", "法", "凡", "菲", "费", "芬", "佛", "弗", "夫"},
106 {"盖", "格", "戈", "冈", "古", "哈", "海", "汉", "豪", "赫"},
107 {"华", "霍", "基", "吉", "加", "杰", "捷", "金", "卡", "凯"},
108 {"科", "克", "肯", "拉", "莱", "兰", "朗", "劳", "勒", "雷"},
109 {"里", "利", "立", "丽", "莉", "林", "琳", "留", "隆", "鲁"},
110 {"路", "伦", "罗", "洛", "律", "", NEXT_PAGE, "", DONE}
111 }
112 },
113 {
114 "<前页>",
115 { // Simp. Chinese 2
116 {"玛", "迈", "曼", "梅", "美", "门", "米", "密", "明", "缪"},
117 {"摩", "莫", "姆", "穆", "那", "娜", "纳", "奈", "南", "尼"},
118 {"宁", "纽", "奴", "诺", "欧", "帕", "派", "佩", "皮", "普"},
119 {"奇", "琪", "琼", "丘", "萨", "撒", "赛", "桑", "瑟", "森"},
120 {"沙", "山", "珊", "史", "世", "斯", "丝", "司", "苏", "所"},
121 {"索", "塔", "泰", "坦", "汤", "特", "提", "汀", "统", "瓦"},
122 {"威", "维", "韦", "卫", "温", "沃", "乌", "西", "希", "夏"},
123 {"辛", "修", "休", "雅", "亚", "林", "琳", "留", "隆", "鲁"},
124 {"伊", "英", "尤", "则", "扎", "", NEXT_PAGE, "", DONE}
125 }
126 },
127 {
128 "<翻頁>",
129 { // Trad. Chinese 1
130 {"泉", "聲", "咽", "危", "石", "日", "色", "冷", "青", "松"},
131 {"薄", "暮", "空", "潭", "曲", "安", "禪", "制", "毒", "龍"},
132 {"海", "內", "存", "知", "己", "天", "涯", "若", "比", "鄰"},
133 {"滿", "階", "芳", "草", "綠", "一", "片", "杏", "花", "香"},
134 {"恨", "無", "千", "日", "酒", "空", "斷", "九", "迴", "腸"},
135 {"當", "路", "誰", "相", "假", "知", "音", "世", "所", "稀"},
136 {"只", "應", "守", "寂", "寞", "還", "掩", "故", "園", "扉"},
137 {"坐", "觀", "垂", "釣", "者", "-", "~", "’", "=", "☆"},
138 {"徒", "有", "羨", "魚", "情", "的", NEXT_PAGE, "", DONE}
139 }
140 },
141 {
142 "<前頁>",
143 { // Trad. Chinese 2
144 {"幾", "行", "歸", "塞", "盡", "念", "爾", "獨", "何", "之"},
145 {"暮", "雨", "相", "呼", "失", "寒", "塘", "欲", "下", "遲"},
146 {"霞", "光", "連", "碧", "彩", "湖", "岸", "水", "連", "灘"},
147 {"天", "地", "丹", "青", "繪", "人", "間", "錦", "秀", "看"},
148 {"返", "景", "入", "深", "林", "復", "照", "青", "苔", "上"},
149 {"中", "歲", "頗", "好", "道", "晚", "家", "南", "山", "睡"},
150 {"興", "來", "每", "獨", "往", "勝", "事", "空", "自", "知"},
151 {"遙", "夜", "泛", "清", "瑟", "-", "~", "’", "=", "☆"},
152 {"西", "風", "生", "翠", "蘿", "的", NEXT_PAGE, "", DONE}
153 }
154 },
155 {
156 "<Абвг>",
157 { // Cp1251 Russian Cyrillic (+ Bel. and Ukr. letters in the last row)
158 {"А", "Б", "В", "Г", "Д", "а", "б", "в", "г", "д"},
159 {"Е", "Ё", "Ж", "З", "И", "е", "ё", "ж", "з", "и"},
160 {"Й", "К", "Л", "М", "Н", "й", "к", "л", "м", "н"},
161 {"О", "П", "Р", "С", "Т", "о", "п", "р", "с", "т"},
162 {"У", "Ф", "Х", "Ц", "Ч", "у", "ф", "х", "ц", "ч"},
163 {"Ш", "Щ", "Ъ", "Ы", "Ь", "ш", "щ", "ъ", "ы", "ь"},
164 {"Э", "Ю", "Я", "", "", "э", "ю", "я", "", ""},
165 {"Ґ", "Є", "І", "Ї", "Ў", "ґ", "є", "і", "ї", "ў"},
166 {"ʼ", "", "", "", "", "", NEXT_PAGE, "", DONE}
167 }
168 },
169 {
170 "<Abcd>",
171 { // Letter
172 {"A", "B", "C", "D", "E", "a", "b", "c", "d", "e"},
173 {"F", "G", "H", "I", "J", "f", "g", "h", "i", "j"},
174 {"K", "L", "M", "N", "O", "k", "l", "m", "n", "o"},
175 {"P", "Q", "R", "S", "T", "p", "q", "r", "s", "t"},
176 {"U", "V", "W", "X", "Y", "u", "v", "w", "x", "y"},
177 {"Z", "" , "" , "" , "" , "z"},
178 {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},
179 {SPACE},
180 {"" , "" , "" , "" , "" , "" , NEXT_PAGE, "", DONE}
181 }
182 },
183 {
184 "<$A$B>",
185 { // Symbol
186 {"$A", "$B", "$C", "$D", "$E", "$a", "$b", "$c", "$d", "$e"},
187 {"$F", "$G", "$H", "$I", "$J", "$f", "$g", "$h", "$i", "$j"},
188 {"$K", "$L", "$M", "$N", "$O", "$k", "$l", "$m", "$n", "$o"},
189 {"$P", "$Q", "$R", "$S", "$T", "$p", "$q", "$r", "$s", "$t"},
190 {"$U", "$V", "$W", "$X", "$Y", "$u", "$v", "$w", "$x", "$y"},
191 {"$Z", "" , "" , "" , "" , "$z"},
192 {},
193 {},
194 { "" , "" , "" , "" , "" , "" , NEXT_PAGE, "", DONE}
195 }
196 }
197 };
198
Window_Keyboard(int ix,int iy,int iwidth,int iheight,const char * ndone_text)199 Window_Keyboard::Window_Keyboard(int ix, int iy, int iwidth, int iheight, const char* ndone_text)
200 : Window_Base(ix, iy, iwidth, iheight)
201 , done_text(ndone_text)
202 , play_cursor(false)
203 {
204 row = 0;
205 col = 0;
206
207 SetContents(Bitmap::Create(width - 16, height - 16));
208
209 row_spacing = 16;
210 col_spacing = (contents->GetWidth() - 2 * border_x) / col_max;
211
212 mode = Letter;
213 next_mode = Symbol;
214
215 Refresh();
216 UpdateCursorRect();
217 }
218
SetMode(Window_Keyboard::Mode nmode,Window_Keyboard::Mode nnext_mode)219 void Window_Keyboard::SetMode(Window_Keyboard::Mode nmode, Window_Keyboard::Mode nnext_mode) {
220 mode = nmode;
221 next_mode = nnext_mode;
222 Refresh();
223 UpdateCursorRect();
224 }
225
GetKey(int row,int col) const226 std::string const& Window_Keyboard::GetKey(int row, int col) const {
227 std::string const& str = layouts[mode].items[row][col];
228 if (str == NEXT_PAGE) {
229 return layouts[next_mode].key_text;
230 }
231 else if (str == DONE) {
232 return done_text;
233 }
234 else {
235 return str;
236 }
237 }
238
GetSelected() const239 std::string const& Window_Keyboard::GetSelected() const {
240 return layouts[mode].items[row][col];
241 }
242
GetItemRect(int row,int col) const243 Rect Window_Keyboard::GetItemRect(int row, int col) const {
244 return Rect(col * col_spacing + border_x,
245 row * row_spacing + border_y,
246 Font::Default()->GetSize(GetKey(row, col)).width + 8,
247 row_spacing);
248 }
249
UpdateCursorRect()250 void Window_Keyboard::UpdateCursorRect() {
251 Rect r = GetItemRect(row, col);
252 r.y -= 2;
253 SetCursorRect(r);
254 }
255
Refresh()256 void Window_Keyboard::Refresh() {
257 contents->Clear();
258
259 for (int j = 0; j < row_max; j++) {
260 for (int i = 0; i < col_max; i++) {
261 Rect r = GetItemRect(j, i);
262 contents->TextDraw(r.x + 4, r.y, Font::ColorDefault, GetKey(j, i));
263 }
264 }
265 }
266
Update()267 void Window_Keyboard::Update() {
268 Window_Base::Update();
269
270 // move left on wide fields
271 int skip_dir = -1;
272
273 if (active) {
274 if (Input::IsRepeated(Input::DOWN)) {
275 play_cursor = true;
276 row = (row + 1) % row_max;
277 }
278 if (Input::IsRepeated(Input::UP)) {
279 play_cursor = true;
280 row = (row + row_max - 1) % row_max;
281 }
282 if (Input::IsRepeated(Input::RIGHT)) {
283 play_cursor = true;
284 col = (col + 1) % col_max;
285 skip_dir = 1;
286 }
287 if (Input::IsRepeated(Input::LEFT)) {
288 play_cursor = true;
289 col = (col + col_max - 1) % col_max;
290 }
291 }
292
293 // Special handling for wide fields
294 if (col > 0) {
295 // page switch and done are always in the bottom right corner
296 if ((row == row_max - 1 && (col == col_max - 3 || col == col_max - 1))
297 || GetKey(row, col - 1) == SPACE)
298 col = std::min(col + skip_dir, col_max - 1);
299 }
300
301 // Skip empty cells
302 if (GetSelected().empty()) {
303 Update();
304 return;
305 }
306
307 if (play_cursor) {
308 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cursor));
309 play_cursor = false;
310 }
311 UpdateCursorRect();
312 }
313