keyboard.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /* MegaZeux
  2. *
  3. * Copyright (C) 2004-2006 Gilead Kutnick <exophase@adelphia.net>
  4. * Copyright (C) 2007 Alistair John Strachan <alistair@devzero.co.uk>
  5. * Copyright (C) 2007 Alan Williams <mralert@gmail.com>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include "../../src/graphics.h"
  22. #include "../../src/render.h"
  23. #include "../../src/renderers.h"
  24. #include "../../src/util.h"
  25. #include <3ds.h>
  26. #include <citro3d.h>
  27. #include "event.h"
  28. #include "keyboard.h"
  29. #include "render.h"
  30. #define MAX_KEYS_DOWN 8
  31. C3D_Tex *keyboard_tex;
  32. static enum keycode keys_down[] =
  33. {
  34. IKEY_UNKNOWN, IKEY_UNKNOWN, IKEY_UNKNOWN, IKEY_UNKNOWN,
  35. IKEY_UNKNOWN, IKEY_UNKNOWN, IKEY_UNKNOWN, IKEY_UNKNOWN
  36. };
  37. static u8 keys_down_count = 0;
  38. static boolean force_zoom_out = false;
  39. static touch_area_t touch_areas[] =
  40. {
  41. { 2, 118, 22, 16, IKEY_ESCAPE, 0 },
  42. { 23, 118, 22, 16, IKEY_F1, 0 },
  43. { 44, 118, 22, 16, IKEY_F2, 0 },
  44. { 65, 118, 22, 16, IKEY_F3, 0 },
  45. { 86, 118, 22, 16, IKEY_F4, 0 },
  46. { 107, 118, 22, 16, IKEY_F5, 0 },
  47. { 128, 118, 22, 16, IKEY_F6, 0 },
  48. { 149, 118, 22, 16, IKEY_F7, 0 },
  49. { 170, 118, 22, 16, IKEY_F8, 0 },
  50. { 191, 118, 22, 16, IKEY_F9, 0 },
  51. { 212, 118, 22, 16, IKEY_F10, 0 },
  52. { 233, 118, 22, 16, IKEY_F11, 0 },
  53. { 254, 118, 22, 16, IKEY_F12, 0 },
  54. { 275, 118, 22, 16, IKEY_INSERT, 0 },
  55. { 296, 118, 22, 16, IKEY_DELETE, 0 },
  56. { 2, 133, 22, 22, IKEY_BACKQUOTE, 0 },
  57. { 23, 133, 22, 22, IKEY_1, 0 },
  58. { 44, 133, 22, 22, IKEY_2, 0 },
  59. { 65, 133, 22, 22, IKEY_3, 0 },
  60. { 86, 133, 22, 22, IKEY_4, 0 },
  61. { 107, 133, 22, 22, IKEY_5, 0 },
  62. { 128, 133, 22, 22, IKEY_6, 0 },
  63. { 149, 133, 22, 22, IKEY_7, 0 },
  64. { 170, 133, 22, 22, IKEY_8, 0 },
  65. { 191, 133, 22, 22, IKEY_9, 0 },
  66. { 212, 133, 22, 22, IKEY_0, 0 },
  67. { 233, 133, 22, 22, IKEY_MINUS, 0 },
  68. { 254, 133, 22, 22, IKEY_EQUALS, 0 },
  69. { 275, 133, 43, 22, IKEY_BACKSPACE, 0 },
  70. { 2, 154, 34, 22, IKEY_TAB, 0 },
  71. { 35, 154, 22, 22, IKEY_q, 0 },
  72. { 56, 154, 22, 22, IKEY_w, 0 },
  73. { 77, 154, 22, 22, IKEY_e, 0 },
  74. { 98, 154, 22, 22, IKEY_r, 0 },
  75. { 119, 154, 22, 22, IKEY_t, 0 },
  76. { 140, 154, 22, 22, IKEY_y, 0 },
  77. { 161, 154, 22, 22, IKEY_u, 0 },
  78. { 182, 154, 22, 22, IKEY_i, 0 },
  79. { 203, 154, 22, 22, IKEY_o, 0 },
  80. { 224, 154, 22, 22, IKEY_p, 0 },
  81. { 245, 154, 22, 22, IKEY_LEFTBRACKET, 0 },
  82. { 266, 154, 22, 22, IKEY_RIGHTBRACKET, 0 },
  83. { 287, 154, 31, 22, IKEY_BACKSLASH, 0 },
  84. { 2, 175, 41, 22, IKEY_LCTRL, 0 },
  85. { 42, 175, 22, 22, IKEY_a, 0 },
  86. { 63, 175, 22, 22, IKEY_s, 0 },
  87. { 84, 175, 22, 22, IKEY_d, 0 },
  88. { 105, 175, 22, 22, IKEY_f, 0 },
  89. { 126, 175, 22, 22, IKEY_g, 0 },
  90. { 147, 175, 22, 22, IKEY_h, 0 },
  91. { 168, 175, 22, 22, IKEY_j, 0 },
  92. { 189, 175, 22, 22, IKEY_k, 0 },
  93. { 210, 175, 22, 22, IKEY_l, 0 },
  94. { 231, 175, 22, 22, IKEY_SEMICOLON, 0 },
  95. { 252, 175, 22, 22, IKEY_QUOTE, 0 },
  96. { 273, 175, 45, 22, IKEY_RETURN, 0 },
  97. { 2, 196, 54, 22, IKEY_LSHIFT, 0 },
  98. { 55, 196, 22, 22, IKEY_z, 0 },
  99. { 76, 196, 22, 22, IKEY_x, 0 },
  100. { 97, 196, 22, 22, IKEY_c, 0 },
  101. { 118, 196, 22, 22, IKEY_v, 0 },
  102. { 139, 196, 22, 22, IKEY_b, 0 },
  103. { 160, 196, 22, 22, IKEY_n, 0 },
  104. { 181, 196, 22, 22, IKEY_m, 0 },
  105. { 202, 196, 22, 22, IKEY_COMMA, 0 },
  106. { 223, 196, 22, 22, IKEY_PERIOD, 0 },
  107. { 244, 196, 22, 22, IKEY_SLASH, 0 },
  108. { 265, 196, 53, 22, IKEY_RSHIFT, 0 },
  109. { 29, 217, 37, 22, IKEY_LALT, 0 },
  110. { 65, 217, 190, 22, IKEY_SPACE, 0 },
  111. { 254, 217, 37, 22, IKEY_RALT, 0 }
  112. };
  113. #define touch_areas_len (sizeof(touch_areas) / sizeof(touch_area_t))
  114. static inline boolean ctr_is_modifier(enum keycode keycode)
  115. {
  116. return keycode >= IKEY_RSHIFT && keycode <= IKEY_RSUPER;
  117. }
  118. static inline boolean ctr_key_touched(touchPosition *pos, touch_area_t *area)
  119. {
  120. return (pos->px >= area->x) && (pos->py >= area->y) &&
  121. (pos->px < (area->x + area->w)) && (pos->py < (area->y + area->h));
  122. }
  123. boolean ctr_keyboard_force_zoom_out(void)
  124. {
  125. return force_zoom_out;
  126. }
  127. void ctr_keyboard_init(struct ctr_render_data *render_data)
  128. {
  129. keyboard_tex = ctr_load_png("romfs:/kbd_display.png");
  130. }
  131. void ctr_keyboard_draw(struct ctr_render_data *render_data)
  132. {
  133. Uint32 i, j;
  134. ctr_draw_2d_texture(render_data, keyboard_tex, 0, 0, 320, 240, 0, 0, 320, 240,
  135. 4.0f, 0xffffffff, false);
  136. if(ctr_is_2d())
  137. {
  138. ctr_draw_2d_texture(render_data, keyboard_tex, force_zoom_out ? 16 : 0, 240,
  139. 16, 16, 302, 2, 16, 16, 3.0f, 0xffffffff, false);
  140. }
  141. if(keys_down_count > 0)
  142. {
  143. for(i = 0; i < touch_areas_len; i++)
  144. {
  145. touch_area_t *area = &touch_areas[i];
  146. for(j = 0; j < keys_down_count; j++)
  147. {
  148. if(keys_down[j] == area->keycode)
  149. {
  150. ctr_draw_2d_texture(render_data, keyboard_tex, area->x,
  151. 240 - area->y - area->h, area->w, area->h,
  152. area->x, area->y + 1, area->w, area->h - 1,
  153. 3.0f, 0x808080ff, false);
  154. break;
  155. }
  156. }
  157. }
  158. }
  159. }
  160. static enum keycode convert_internal_unicode(enum keycode key)
  161. {
  162. if(key >= 32 && key <= 126)
  163. {
  164. if(get_shift_status(keycode_internal))
  165. {
  166. if((key >= IKEY_a) && (key <= IKEY_z))
  167. return (key - 32);
  168. // TODO based on a US keyboard right now since that's as good as any
  169. // default and possibly what most users are going to expect. It would
  170. // be nice to have more locales at some point if someone requests them.
  171. switch(key)
  172. {
  173. case IKEY_BACKQUOTE: return '~';
  174. case IKEY_1: return '!';
  175. case IKEY_2: return '@';
  176. case IKEY_3: return '#';
  177. case IKEY_4: return '$';
  178. case IKEY_5: return '%';
  179. case IKEY_6: return '^';
  180. case IKEY_7: return '&';
  181. case IKEY_8: return '*';
  182. case IKEY_9: return '(';
  183. case IKEY_0: return ')';
  184. case IKEY_MINUS: return '_';
  185. case IKEY_EQUALS: return '+';
  186. case IKEY_LEFTBRACKET: return '{';
  187. case IKEY_RIGHTBRACKET: return '}';
  188. case IKEY_BACKSLASH: return '|';
  189. case IKEY_SEMICOLON: return ':';
  190. case IKEY_QUOTE: return '"';
  191. case IKEY_COMMA: return '<';
  192. case IKEY_PERIOD: return '>';
  193. case IKEY_SLASH: return '?';
  194. default: return IKEY_UNKNOWN;
  195. }
  196. }
  197. return key;
  198. }
  199. return IKEY_UNKNOWN;
  200. }
  201. boolean ctr_keyboard_update(struct buffered_status *status)
  202. {
  203. touchPosition pos;
  204. Uint32 down, up, i;
  205. boolean retval = false;
  206. enum keycode unicode;
  207. if(get_bottom_screen_mode() != BOTTOM_SCREEN_MODE_KEYBOARD)
  208. return retval;
  209. down = hidKeysDown();
  210. up = hidKeysUp();
  211. hidTouchRead(&pos);
  212. if(down & KEY_TOUCH)
  213. {
  214. if(ctr_is_2d() && pos.px >= 302 && pos.py >= 2 && pos.px < 318 &&
  215. pos.py < 18)
  216. {
  217. force_zoom_out = !force_zoom_out;
  218. }
  219. for(i = 0; i < touch_areas_len; i++)
  220. {
  221. touch_area_t *area = &touch_areas[i];
  222. if(ctr_key_touched(&pos, area))
  223. {
  224. unicode = convert_internal_unicode(area->keycode);
  225. key_press(status, area->keycode, unicode);
  226. keys_down[keys_down_count++] = area->keycode;
  227. retval = true;
  228. break;
  229. }
  230. }
  231. }
  232. if(up & KEY_TOUCH && keys_down_count > 0 &&
  233. !ctr_is_modifier(keys_down[keys_down_count - 1]))
  234. {
  235. for(; keys_down_count > 0; keys_down_count--)
  236. {
  237. key_release(status, keys_down[keys_down_count - 1]);
  238. keys_down[keys_down_count - 1] = IKEY_UNKNOWN;
  239. }
  240. retval = true;
  241. }
  242. return retval;
  243. }