Subversion Repositories HelenOS

Rev

Rev 4581 | Blame | Compare with Previous | 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 Czech QWERTZ layout.
  31.  * @{
  32.  */
  33.  
  34. #include <kbd.h>
  35. #include <io/console.h>
  36. #include <io/keycode.h>
  37. #include <bool.h>
  38. #include <layout.h>
  39.  
  40. static void layout_reset(void);
  41. static wchar_t layout_parse_ev(console_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_Q] = 'q',
  58.     [KC_W] = 'w',
  59.     [KC_E] = 'e',
  60.     [KC_R] = 'r',
  61.     [KC_T] = 't',
  62.     [KC_Y] = 'z',
  63.     [KC_U] = 'u',
  64.     [KC_I] = 'i',
  65.     [KC_O] = 'o',
  66.     [KC_P] = 'p',
  67.  
  68.     [KC_A] = 'a',
  69.     [KC_S] = 's',
  70.     [KC_D] = 'd',
  71.     [KC_F] = 'f',
  72.     [KC_G] = 'g',
  73.     [KC_H] = 'h',
  74.     [KC_J] = 'j',
  75.     [KC_K] = 'k',
  76.     [KC_L] = 'l',
  77.  
  78.     [KC_Z] = 'y',
  79.     [KC_X] = 'x',
  80.     [KC_C] = 'c',
  81.     [KC_V] = 'v',
  82.     [KC_B] = 'b',
  83.     [KC_N] = 'n',
  84.     [KC_M] = 'm',
  85. };
  86.  
  87. static wchar_t map_ucase[] = {
  88.     [KC_Q] = 'Q',
  89.     [KC_W] = 'W',
  90.     [KC_E] = 'E',
  91.     [KC_R] = 'R',
  92.     [KC_T] = 'T',
  93.     [KC_Y] = 'Z',
  94.     [KC_U] = 'U',
  95.     [KC_I] = 'I',
  96.     [KC_O] = 'O',
  97.     [KC_P] = 'P',
  98.  
  99.     [KC_A] = 'A',
  100.     [KC_S] = 'S',
  101.     [KC_D] = 'D',
  102.     [KC_F] = 'F',
  103.     [KC_G] = 'G',
  104.     [KC_H] = 'H',
  105.     [KC_J] = 'J',
  106.     [KC_K] = 'K',
  107.     [KC_L] = 'L',
  108.  
  109.     [KC_Z] = 'Y',
  110.     [KC_X] = 'X',
  111.     [KC_C] = 'C',
  112.     [KC_V] = 'V',
  113.     [KC_B] = 'B',
  114.     [KC_N] = 'N',
  115.     [KC_M] = 'M',
  116. };
  117.  
  118. static wchar_t map_not_shifted[] = {
  119.     [KC_BACKTICK] = ';',
  120.  
  121.     [KC_1] = '+',
  122.  
  123.     [KC_MINUS] = '=',
  124.  
  125.     [KC_RBRACKET] = ')',
  126.  
  127.     [KC_QUOTE] = L'§',
  128.  
  129.     [KC_COMMA] = ',',
  130.     [KC_PERIOD] = '.',
  131.     [KC_SLASH] = '-',
  132. };
  133.  
  134. static wchar_t map_shifted[] = {
  135.     [KC_1] = '1',
  136.     [KC_2] = '2',
  137.     [KC_3] = '3',
  138.     [KC_4] = '4',
  139.     [KC_5] = '5',
  140.     [KC_6] = '6',
  141.     [KC_7] = '7',
  142.     [KC_8] = '8',
  143.     [KC_9] = '9',
  144.     [KC_0] = '0',
  145.  
  146.     [KC_MINUS] = '%',
  147.  
  148.     [KC_LBRACKET] = '/',
  149.     [KC_RBRACKET] = '(',
  150.  
  151.     [KC_SEMICOLON] = '"',
  152.     [KC_QUOTE] = '!',
  153.     [KC_BACKSLASH] = '\'',
  154.  
  155.     [KC_COMMA] = '?',
  156.     [KC_PERIOD] = ':',
  157.     [KC_SLASH] = '_',
  158. };
  159.  
  160. static wchar_t map_ns_nocaps[] = {
  161.     [KC_2] = L'ě',
  162.     [KC_3] = L'š',
  163.     [KC_4] = L'č',
  164.     [KC_5] = L'ř',
  165.     [KC_6] = L'ž',
  166.     [KC_7] = L'ý',
  167.     [KC_8] = L'á',
  168.     [KC_9] = L'í',
  169.     [KC_0] = L'é',
  170.  
  171.     [KC_LBRACKET] = L'ú',
  172.     [KC_SEMICOLON] = L'ů'
  173. };
  174.  
  175. static wchar_t map_ns_caps[] = {
  176.     [KC_2] = L'Ě',
  177.     [KC_3] = L'Š',
  178.     [KC_4] = L'Č',
  179.     [KC_5] = L'Ř',
  180.     [KC_6] = L'Ž',
  181.     [KC_7] = L'Ý',
  182.     [KC_8] = L'Á',
  183.     [KC_9] = L'Í',
  184.     [KC_0] = L'É',
  185.  
  186.     [KC_LBRACKET] = L'Ú',
  187.     [KC_SEMICOLON] = L'Ů'
  188. };
  189.  
  190. static wchar_t map_neutral[] = {
  191.     [KC_BACKSPACE] = '\b',
  192.     [KC_TAB] = '\t',
  193.     [KC_ENTER] = '\n',
  194.     [KC_SPACE] = ' ',
  195.  
  196.     [KC_NSLASH] = '/',
  197.     [KC_NTIMES] = '*',
  198.     [KC_NMINUS] = '-',
  199.     [KC_NPLUS] = '+',
  200.     [KC_NENTER] = '\n'
  201. };
  202.  
  203. static wchar_t map_numeric[] = {
  204.     [KC_N7] = '7',
  205.     [KC_N8] = '8',
  206.     [KC_N9] = '9',
  207.     [KC_N4] = '4',
  208.     [KC_N5] = '5',
  209.     [KC_N6] = '6',
  210.     [KC_N1] = '1',
  211.     [KC_N2] = '2',
  212.     [KC_N3] = '3',
  213.  
  214.     [KC_N0] = '0',
  215.     [KC_NPERIOD] = '.'
  216. };
  217.  
  218. static wchar_t map_hacek_lcase[] = {
  219.     [KC_E] = L'ě',
  220.     [KC_R] = L'ř',
  221.     [KC_T] = L'ť',
  222.     [KC_Y] = L'ž',
  223.     [KC_U] = L'ů',
  224.  
  225.     [KC_S] = L'š',
  226.     [KC_D] = L'ď',
  227.  
  228.     [KC_C] = L'č',
  229.     [KC_N] = L'ň'
  230. };
  231.  
  232. static wchar_t map_hacek_ucase[] = {
  233.     [KC_E] = L'Ě',
  234.     [KC_R] = L'Ř',
  235.     [KC_T] = L'Ť',
  236.     [KC_Y] = L'Ž',
  237.     [KC_U] = L'Ů',
  238.  
  239.     [KC_S] = L'Š',
  240.     [KC_D] = L'Ď',
  241.  
  242.     [KC_C] = L'Č',
  243.     [KC_N] = L'Ň'
  244. };
  245.  
  246. static wchar_t map_carka_lcase[] = {
  247.     [KC_E] = L'é',
  248.     [KC_U] = L'ú',
  249.     [KC_I] = L'í',
  250.     [KC_O] = L'ó',
  251.  
  252.     [KC_A] = L'á',
  253.  
  254.     [KC_Z] = L'ý',
  255. };
  256.  
  257. static wchar_t map_carka_ucase[] = {
  258.     [KC_E] = L'É',
  259.     [KC_U] = L'Ú',
  260.     [KC_I] = L'Í',
  261.     [KC_O] = L'Ó',
  262.  
  263.     [KC_A] = L'Á',
  264.  
  265.     [KC_Z] = L'Ý',
  266. };
  267.  
  268. static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
  269. {
  270.     if (key >= map_length)
  271.         return 0;
  272.     return map[key];
  273. }
  274.  
  275. static wchar_t parse_ms_hacek(console_event_t *ev)
  276. {
  277.     wchar_t c;
  278.  
  279.     mstate = ms_start;
  280.  
  281.     /* Produce no characters when Ctrl or Alt is pressed. */
  282.     if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
  283.         return 0;
  284.  
  285.     if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
  286.         c = translate(ev->key, map_hacek_ucase, sizeof(map_hacek_ucase) / sizeof(wchar_t));
  287.     else
  288.         c = translate(ev->key, map_hacek_lcase, sizeof(map_hacek_lcase) / sizeof(wchar_t));
  289.  
  290.     return c;
  291. }
  292.  
  293. static wchar_t parse_ms_carka(console_event_t *ev)
  294. {
  295.     wchar_t c;
  296.  
  297.     mstate = ms_start;
  298.  
  299.     /* Produce no characters when Ctrl or Alt is pressed. */
  300.     if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
  301.         return 0;
  302.  
  303.     if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
  304.         c = translate(ev->key, map_carka_ucase, sizeof(map_carka_ucase) / sizeof(wchar_t));
  305.     else
  306.         c = translate(ev->key, map_carka_lcase, sizeof(map_carka_lcase) / sizeof(wchar_t));
  307.  
  308.     return c;
  309. }
  310.  
  311. static wchar_t parse_ms_start(console_event_t *ev)
  312. {
  313.     wchar_t c;
  314.  
  315.     /* Produce no characters when Ctrl or Alt is pressed. */
  316.     if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
  317.         return 0;
  318.  
  319.     if (ev->key == KC_EQUALS) {
  320.         if ((ev->mods & KM_SHIFT) != 0)
  321.             mstate = ms_hacek;
  322.         else
  323.             mstate = ms_carka;
  324.  
  325.         return 0;
  326.     }
  327.  
  328.     c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
  329.     if (c != 0)
  330.         return c;
  331.  
  332.     if ((ev->mods & KM_SHIFT) == 0) {
  333.         if ((ev->mods & KM_CAPS_LOCK) != 0)
  334.             c = translate(ev->key, map_ns_caps, sizeof(map_ns_caps) / sizeof(wchar_t));
  335.         else
  336.             c = translate(ev->key, map_ns_nocaps, sizeof(map_ns_nocaps) / sizeof(wchar_t));
  337.  
  338.         if (c != 0)
  339.             return c;
  340.     }  
  341.  
  342.     if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
  343.         c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
  344.     else
  345.         c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
  346.  
  347.     if (c != 0)
  348.         return c;
  349.  
  350.     if ((ev->mods & KM_SHIFT) != 0)
  351.         c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
  352.     else
  353.         c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
  354.  
  355.     if (c != 0)
  356.         return c;
  357.  
  358.     if ((ev->mods & KM_NUM_LOCK) != 0)
  359.         c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
  360.     else
  361.         c = 0;
  362.  
  363.     return c;
  364. }
  365.  
  366. static bool key_is_mod(unsigned key)
  367. {
  368.     switch (key) {
  369.     case KC_LSHIFT:
  370.     case KC_RSHIFT:
  371.     case KC_LALT:
  372.     case KC_RALT:
  373.     case KC_LCTRL:
  374.     case KC_RCTRL:
  375.         return true;
  376.     default:
  377.         return false;
  378.     }
  379. }
  380.  
  381. static void layout_reset(void)
  382. {
  383.     mstate = ms_start;
  384. }
  385.  
  386. static wchar_t layout_parse_ev(console_event_t *ev)
  387. {
  388.     if (ev->type != KEY_PRESS)
  389.         return 0;
  390.    
  391.     if (key_is_mod(ev->key))
  392.         return 0;
  393.    
  394.     switch (mstate) {
  395.     case ms_start:
  396.         return parse_ms_start(ev);
  397.     case ms_hacek:
  398.         return parse_ms_hacek(ev);
  399.     case ms_carka:
  400.         return parse_ms_carka(ev);
  401.     }
  402.    
  403.     return 0;
  404. }
  405.  
  406. /**
  407.  * @}
  408.  */
  409.