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