Subversion Repositories HelenOS

Rev

Rev 4285 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2009 Jiri Svoboda
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup kbd
  30.  * @brief   US QWERTY leyout.
  31.  * @{
  32.  */
  33.  
  34. #include <kbd.h>
  35. #include <kbd/kbd.h>
  36. #include <kbd/keycode.h>
  37. #include <bool.h>
  38. #include <layout.h>
  39.  
  40. static void layout_reset(void);
  41. static wchar_t layout_parse_ev(kbd_event_t *ev);
  42.  
  43. enum m_state {
  44.     ms_start,
  45.     ms_hacek,
  46.     ms_carka   
  47. };
  48.  
  49. static enum m_state mstate;
  50.  
  51. layout_op_t cz_op = {
  52.     layout_reset,
  53.     layout_parse_ev
  54. };
  55.  
  56. static wchar_t map_lcase[] = {
  57.     [KC_2] = L'ě',
  58.     [KC_3] = L'š',
  59.     [KC_4] = L'č',
  60.     [KC_5] = L'ř',
  61.     [KC_6] = L'ž',
  62.     [KC_7] = L'ý',
  63.     [KC_8] = L'á',
  64.     [KC_9] = L'í',
  65.     [KC_0] = L'é',
  66.  
  67.     [KC_LBRACKET] = L'ú',
  68.     [KC_SEMICOLON] = L'ů',
  69.  
  70.     [KC_Q] = 'q',
  71.     [KC_W] = 'w',
  72.     [KC_E] = 'e',
  73.     [KC_R] = 'r',
  74.     [KC_T] = 't',
  75.     [KC_Y] = 'z',
  76.     [KC_U] = 'u',
  77.     [KC_I] = 'i',
  78.     [KC_O] = 'o',
  79.     [KC_P] = 'p',
  80.  
  81.     [KC_A] = 'a',
  82.     [KC_S] = 's',
  83.     [KC_D] = 'd',
  84.     [KC_F] = 'f',
  85.     [KC_G] = 'g',
  86.     [KC_H] = 'h',
  87.     [KC_J] = 'j',
  88.     [KC_K] = 'k',
  89.     [KC_L] = 'l',
  90.  
  91.     [KC_Z] = 'y',
  92.     [KC_X] = 'x',
  93.     [KC_C] = 'c',
  94.     [KC_V] = 'v',
  95.     [KC_B] = 'b',
  96.     [KC_N] = 'n',
  97.     [KC_M] = 'm',
  98. };
  99.  
  100. static wchar_t map_ucase[] = {
  101.     [KC_2] = L'Ě',
  102.     [KC_3] = L'Š',
  103.     [KC_4] = L'Č',
  104.     [KC_5] = L'Ř',
  105.     [KC_6] = L'Ž',
  106.     [KC_7] = L'Ý',
  107.     [KC_8] = L'Á',
  108.     [KC_9] = L'Í',
  109.     [KC_0] = L'É',
  110.  
  111.     [KC_LBRACKET] = L'Ú',
  112.     [KC_SEMICOLON] = L'Ů',
  113.  
  114.     [KC_Q] = 'Q',
  115.     [KC_W] = 'W',
  116.     [KC_E] = 'E',
  117.     [KC_R] = 'R',
  118.     [KC_T] = 'T',
  119.     [KC_Y] = 'Z',
  120.     [KC_U] = 'U',
  121.     [KC_I] = 'I',
  122.     [KC_O] = 'O',
  123.     [KC_P] = 'P',
  124.  
  125.     [KC_A] = 'A',
  126.     [KC_S] = 'S',
  127.     [KC_D] = 'D',
  128.     [KC_F] = 'F',
  129.     [KC_G] = 'G',
  130.     [KC_H] = 'H',
  131.     [KC_J] = 'J',
  132.     [KC_K] = 'K',
  133.     [KC_L] = 'L',
  134.  
  135.     [KC_Z] = 'Y',
  136.     [KC_X] = 'X',
  137.     [KC_C] = 'C',
  138.     [KC_V] = 'V',
  139.     [KC_B] = 'B',
  140.     [KC_N] = 'N',
  141.     [KC_M] = 'M',
  142. };
  143.  
  144. static wchar_t map_not_shifted[] = {
  145.     [KC_BACKTICK] = ';',
  146.  
  147.     [KC_1] = '+',
  148.  
  149.     [KC_MINUS] = '=',
  150.  
  151.     [KC_RBRACKET] = ')',
  152.  
  153.     [KC_QUOTE] = L'§',
  154.  
  155.     [KC_COMMA] = ',',
  156.     [KC_PERIOD] = '.',
  157.     [KC_SLASH] = '-',
  158. };
  159.  
  160. static wchar_t map_shifted[] = {
  161.     [KC_1] = '1',
  162.     [KC_2] = '2',
  163.     [KC_3] = '3',
  164.     [KC_4] = '4',
  165.     [KC_5] = '5',
  166.     [KC_6] = '6',
  167.     [KC_7] = '7',
  168.     [KC_8] = '8',
  169.     [KC_9] = '9',
  170.     [KC_0] = '0',
  171.  
  172.     [KC_MINUS] = '%',
  173.  
  174.     [KC_LBRACKET] = '/',
  175.     [KC_RBRACKET] = '(',
  176.  
  177.     [KC_SEMICOLON] = '"',
  178.     [KC_QUOTE] = '!',
  179.     [KC_BACKSLASH] = '\'',
  180.  
  181.     [KC_COMMA] = '?',
  182.     [KC_PERIOD] = ':',
  183.     [KC_SLASH] = '_',
  184. };
  185.  
  186. static wchar_t map_neutral[] = {
  187.     [KC_BACKSPACE] = '\b',
  188.     [KC_TAB] = '\t',
  189.     [KC_ENTER] = '\n',
  190.     [KC_SPACE] = ' ',
  191.  
  192.     [KC_NSLASH] = '/',
  193.     [KC_NTIMES] = '*',
  194.     [KC_NMINUS] = '-',
  195.     [KC_NPLUS] = '+',
  196.     [KC_NENTER] = '\n'
  197. };
  198.  
  199. static wchar_t map_numeric[] = {
  200.     [KC_N7] = '7',
  201.     [KC_N8] = '8',
  202.     [KC_N9] = '9',
  203.     [KC_N4] = '4',
  204.     [KC_N5] = '5',
  205.     [KC_N6] = '6',
  206.     [KC_N1] = '1',
  207.     [KC_N2] = '2',
  208.     [KC_N3] = '3',
  209.  
  210.     [KC_N0] = '0',
  211.     [KC_NPERIOD] = '.'
  212. };
  213.  
  214. static wchar_t map_hacek_lcase[] = {
  215.     [KC_E] = L'ě',
  216.     [KC_R] = L'ř',
  217.     [KC_T] = L'ť',
  218.     [KC_Y] = L'ž',
  219.     [KC_U] = L'ů',
  220.  
  221.     [KC_S] = L'š',
  222.     [KC_D] = L'ď',
  223.  
  224.     [KC_C] = L'č',
  225.     [KC_N] = L'ň'
  226. };
  227.  
  228. static wchar_t map_hacek_ucase[] = {
  229.     [KC_E] = L'Ě',
  230.     [KC_R] = L'Ř',
  231.     [KC_T] = L'Ť',
  232.     [KC_Y] = L'Ž',
  233.     [KC_U] = L'Ů',
  234.  
  235.     [KC_S] = L'Š',
  236.     [KC_D] = L'Ď',
  237.  
  238.     [KC_C] = L'Č',
  239.     [KC_N] = L'Ň'
  240. };
  241.  
  242. static wchar_t map_carka_lcase[] = {
  243.     [KC_E] = L'é',
  244.     [KC_U] = L'ú',
  245.     [KC_I] = L'í',
  246.     [KC_O] = L'ó',
  247.  
  248.     [KC_A] = L'á',
  249.  
  250.     [KC_Z] = L'ý',
  251. };
  252.  
  253. static wchar_t map_carka_ucase[] = {
  254.     [KC_E] = L'É',
  255.     [KC_U] = L'Ú',
  256.     [KC_I] = L'Í',
  257.     [KC_O] = L'Ó',
  258.  
  259.     [KC_A] = L'Á',
  260.  
  261.     [KC_Z] = L'Ý',
  262. };
  263.  
  264. static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
  265. {
  266.     if (key >= map_length)
  267.         return 0;
  268.     return map[key];
  269. }
  270.  
  271. static wchar_t parse_ms_hacek(kbd_event_t *ev)
  272. {
  273.     wchar_t c;
  274.  
  275.     mstate = ms_start;
  276.  
  277.     /* Produce no characters when Ctrl or Alt is pressed. */
  278.     if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
  279.         return 0;
  280.  
  281.     if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
  282.         c = translate(ev->key, map_hacek_ucase, sizeof(map_hacek_ucase) / sizeof(wchar_t));
  283.     else
  284.         c = translate(ev->key, map_hacek_lcase, sizeof(map_hacek_lcase) / sizeof(wchar_t));
  285.  
  286.     return c;
  287. }
  288.  
  289. static wchar_t parse_ms_carka(kbd_event_t *ev)
  290. {
  291.     wchar_t c;
  292.  
  293.     mstate = ms_start;
  294.  
  295.     /* Produce no characters when Ctrl or Alt is pressed. */
  296.     if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
  297.         return 0;
  298.  
  299.     if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
  300.         c = translate(ev->key, map_carka_ucase, sizeof(map_carka_ucase) / sizeof(wchar_t));
  301.     else
  302.         c = translate(ev->key, map_carka_lcase, sizeof(map_carka_lcase) / sizeof(wchar_t));
  303.  
  304.     return c;
  305. }
  306.  
  307. static wchar_t parse_ms_start(kbd_event_t *ev)
  308. {
  309.     wchar_t c;
  310.  
  311.     /* Produce no characters when Ctrl or Alt is pressed. */
  312.     if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
  313.         return 0;
  314.  
  315.     if (ev->key == KC_EQUALS) {
  316.         if ((ev->mods & KM_SHIFT) != 0)
  317.             mstate = ms_hacek;
  318.         else
  319.             mstate = ms_carka;
  320.  
  321.         return 0;
  322.     }
  323.  
  324.     c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
  325.     if (c != 0)
  326.         return c;
  327.  
  328.     if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
  329.         c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
  330.     else
  331.         c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
  332.  
  333.     if (c != 0)
  334.         return c;
  335.  
  336.     if ((ev->mods & KM_SHIFT) != 0)
  337.         c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
  338.     else
  339.         c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
  340.  
  341.     if (c != 0)
  342.         return c;
  343.  
  344.     if ((ev->mods & KM_NUM_LOCK) != 0)
  345.         c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
  346.     else
  347.         c = 0;
  348.  
  349.     return c;
  350. }
  351.  
  352. static bool key_is_mod(unsigned key)
  353. {
  354.     switch (key) {
  355.     case KC_LSHIFT:
  356.     case KC_RSHIFT:
  357.     case KC_LALT:
  358.     case KC_RALT:
  359.     case KC_LCTRL:
  360.     case KC_RCTRL:
  361.         return true;
  362.     default:
  363.         return false;
  364.     }
  365. }
  366.  
  367. static void layout_reset(void)
  368. {
  369.     mstate = ms_start;
  370. }
  371.  
  372. static wchar_t layout_parse_ev(kbd_event_t *ev)
  373. {
  374.     if (ev->type != KE_PRESS)
  375.         return '\0';
  376.  
  377.     if (key_is_mod(ev->key))
  378.         return '\0';
  379.  
  380.     switch (mstate) {
  381.     case ms_start: return parse_ms_start(ev);
  382.     case ms_hacek: return parse_ms_hacek(ev);
  383.     case ms_carka: return parse_ms_carka(ev);
  384.     }
  385. }
  386.  
  387. /**
  388.  * @}
  389.  */
  390.