cz.c

00001 /*
00002  * Copyright (c) 2009 Jiri Svoboda
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00034 #include <kbd.h>
00035 #include <io/console.h>
00036 #include <io/keycode.h>
00037 #include <bool.h>
00038 #include <layout.h>
00039 
00040 static void layout_reset(void);
00041 static wchar_t layout_parse_ev(console_event_t *ev);
00042 
00043 enum m_state {
00044         ms_start,
00045         ms_hacek,
00046         ms_carka
00047 };
00048 
00049 static enum m_state mstate;
00050 
00051 layout_op_t cz_op = {
00052         layout_reset,
00053         layout_parse_ev
00054 };
00055 
00056 static wchar_t map_lcase[] = {
00057         [KC_Q] = 'q',
00058         [KC_W] = 'w',
00059         [KC_E] = 'e',
00060         [KC_R] = 'r',
00061         [KC_T] = 't',
00062         [KC_Y] = 'z',
00063         [KC_U] = 'u',
00064         [KC_I] = 'i',
00065         [KC_O] = 'o',
00066         [KC_P] = 'p',
00067 
00068         [KC_A] = 'a',
00069         [KC_S] = 's',
00070         [KC_D] = 'd',
00071         [KC_F] = 'f',
00072         [KC_G] = 'g',
00073         [KC_H] = 'h',
00074         [KC_J] = 'j',
00075         [KC_K] = 'k',
00076         [KC_L] = 'l',
00077 
00078         [KC_Z] = 'y',
00079         [KC_X] = 'x',
00080         [KC_C] = 'c',
00081         [KC_V] = 'v',
00082         [KC_B] = 'b',
00083         [KC_N] = 'n',
00084         [KC_M] = 'm',
00085 };
00086 
00087 static wchar_t map_ucase[] = {
00088         [KC_Q] = 'Q',
00089         [KC_W] = 'W',
00090         [KC_E] = 'E',
00091         [KC_R] = 'R',
00092         [KC_T] = 'T',
00093         [KC_Y] = 'Z',
00094         [KC_U] = 'U',
00095         [KC_I] = 'I',
00096         [KC_O] = 'O',
00097         [KC_P] = 'P',
00098 
00099         [KC_A] = 'A',
00100         [KC_S] = 'S',
00101         [KC_D] = 'D',
00102         [KC_F] = 'F',
00103         [KC_G] = 'G',
00104         [KC_H] = 'H',
00105         [KC_J] = 'J',
00106         [KC_K] = 'K',
00107         [KC_L] = 'L',
00108 
00109         [KC_Z] = 'Y',
00110         [KC_X] = 'X',
00111         [KC_C] = 'C',
00112         [KC_V] = 'V',
00113         [KC_B] = 'B',
00114         [KC_N] = 'N',
00115         [KC_M] = 'M',
00116 };
00117 
00118 static wchar_t map_not_shifted[] = {
00119         [KC_BACKTICK] = ';',
00120 
00121         [KC_1] = '+',
00122 
00123         [KC_MINUS] = '=',
00124 
00125         [KC_RBRACKET] = ')',
00126 
00127         [KC_QUOTE] = L'§',
00128 
00129         [KC_COMMA] = ',',
00130         [KC_PERIOD] = '.',
00131         [KC_SLASH] = '-',
00132 };
00133 
00134 static wchar_t map_shifted[] = {
00135         [KC_1] = '1',
00136         [KC_2] = '2',
00137         [KC_3] = '3',
00138         [KC_4] = '4',
00139         [KC_5] = '5',
00140         [KC_6] = '6',
00141         [KC_7] = '7',
00142         [KC_8] = '8',
00143         [KC_9] = '9',
00144         [KC_0] = '0',
00145 
00146         [KC_MINUS] = '%',
00147 
00148         [KC_LBRACKET] = '/',
00149         [KC_RBRACKET] = '(',
00150 
00151         [KC_SEMICOLON] = '"',
00152         [KC_QUOTE] = '!',
00153         [KC_BACKSLASH] = '\'',
00154 
00155         [KC_COMMA] = '?',
00156         [KC_PERIOD] = ':',
00157         [KC_SLASH] = '_',
00158 };
00159 
00160 static wchar_t map_ns_nocaps[] = {
00161         [KC_2] = L'ě',
00162         [KC_3] = L'š',
00163         [KC_4] = L'č',
00164         [KC_5] = L'ř',
00165         [KC_6] = L'ž',
00166         [KC_7] = L'ý',
00167         [KC_8] = L'á',
00168         [KC_9] = L'í',
00169         [KC_0] = L'é',
00170 
00171         [KC_LBRACKET] = L'ú',
00172         [KC_SEMICOLON] = L'ů'
00173 };
00174 
00175 static wchar_t map_ns_caps[] = {
00176         [KC_2] = L'Ě',
00177         [KC_3] = L'Š',
00178         [KC_4] = L'Č',
00179         [KC_5] = L'Ř',
00180         [KC_6] = L'Ž',
00181         [KC_7] = L'Ý',
00182         [KC_8] = L'Á',
00183         [KC_9] = L'Í',
00184         [KC_0] = L'É',
00185 
00186         [KC_LBRACKET] = L'Ú',
00187         [KC_SEMICOLON] = L'Ů'
00188 };
00189 
00190 static wchar_t map_neutral[] = {
00191         [KC_BACKSPACE] = '\b',
00192         [KC_TAB] = '\t',
00193         [KC_ENTER] = '\n',
00194         [KC_SPACE] = ' ',
00195 
00196         [KC_NSLASH] = '/',
00197         [KC_NTIMES] = '*',
00198         [KC_NMINUS] = '-',
00199         [KC_NPLUS] = '+',
00200         [KC_NENTER] = '\n'
00201 };
00202 
00203 static wchar_t map_numeric[] = {
00204         [KC_N7] = '7',
00205         [KC_N8] = '8',
00206         [KC_N9] = '9',
00207         [KC_N4] = '4',
00208         [KC_N5] = '5',
00209         [KC_N6] = '6',
00210         [KC_N1] = '1',
00211         [KC_N2] = '2',
00212         [KC_N3] = '3',
00213 
00214         [KC_N0] = '0',
00215         [KC_NPERIOD] = '.'
00216 };
00217 
00218 static wchar_t map_hacek_lcase[] = {
00219         [KC_E] = L'ě',
00220         [KC_R] = L'ř',
00221         [KC_T] = L'ť',
00222         [KC_Y] = L'ž',
00223         [KC_U] = L'ů',
00224 
00225         [KC_S] = L'š',
00226         [KC_D] = L'ď',
00227 
00228         [KC_C] = L'č',
00229         [KC_N] = L'ň'
00230 };
00231 
00232 static wchar_t map_hacek_ucase[] = {
00233         [KC_E] = L'Ě',
00234         [KC_R] = L'Ř',
00235         [KC_T] = L'Ť',
00236         [KC_Y] = L'Ž',
00237         [KC_U] = L'Ů',
00238 
00239         [KC_S] = L'Š',
00240         [KC_D] = L'Ď',
00241 
00242         [KC_C] = L'Č',
00243         [KC_N] = L'Ň'
00244 };
00245 
00246 static wchar_t map_carka_lcase[] = {
00247         [KC_E] = L'é',
00248         [KC_U] = L'ú',
00249         [KC_I] = L'í',
00250         [KC_O] = L'ó',
00251 
00252         [KC_A] = L'á',
00253 
00254         [KC_Z] = L'ý',
00255 };
00256 
00257 static wchar_t map_carka_ucase[] = {
00258         [KC_E] = L'É',
00259         [KC_U] = L'Ú',
00260         [KC_I] = L'Í',
00261         [KC_O] = L'Ó',
00262 
00263         [KC_A] = L'Á',
00264 
00265         [KC_Z] = L'Ý',
00266 };
00267 
00268 static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
00269 {
00270         if (key >= map_length)
00271                 return 0;
00272         return map[key];
00273 }
00274 
00275 static wchar_t parse_ms_hacek(console_event_t *ev)
00276 {
00277         wchar_t c;
00278 
00279         mstate = ms_start;
00280 
00281         /* Produce no characters when Ctrl or Alt is pressed. */
00282         if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
00283                 return 0;
00284 
00285         if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
00286                 c = translate(ev->key, map_hacek_ucase, sizeof(map_hacek_ucase) / sizeof(wchar_t));
00287         else
00288                 c = translate(ev->key, map_hacek_lcase, sizeof(map_hacek_lcase) / sizeof(wchar_t));
00289 
00290         return c;
00291 }
00292 
00293 static wchar_t parse_ms_carka(console_event_t *ev)
00294 {
00295         wchar_t c;
00296 
00297         mstate = ms_start;
00298 
00299         /* Produce no characters when Ctrl or Alt is pressed. */
00300         if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
00301                 return 0;
00302 
00303         if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
00304                 c = translate(ev->key, map_carka_ucase, sizeof(map_carka_ucase) / sizeof(wchar_t));
00305         else
00306                 c = translate(ev->key, map_carka_lcase, sizeof(map_carka_lcase) / sizeof(wchar_t));
00307 
00308         return c;
00309 }
00310 
00311 static wchar_t parse_ms_start(console_event_t *ev)
00312 {
00313         wchar_t c;
00314 
00315         /* Produce no characters when Ctrl or Alt is pressed. */
00316         if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
00317                 return 0;
00318 
00319         if (ev->key == KC_EQUALS) {
00320                 if ((ev->mods & KM_SHIFT) != 0)
00321                         mstate = ms_hacek;
00322                 else
00323                         mstate = ms_carka;
00324 
00325                 return 0;
00326         }
00327 
00328         c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
00329         if (c != 0)
00330                 return c;
00331 
00332         if ((ev->mods & KM_SHIFT) == 0) {
00333                 if ((ev->mods & KM_CAPS_LOCK) != 0)
00334                         c = translate(ev->key, map_ns_caps, sizeof(map_ns_caps) / sizeof(wchar_t));
00335                 else
00336                         c = translate(ev->key, map_ns_nocaps, sizeof(map_ns_nocaps) / sizeof(wchar_t));
00337 
00338                 if (c != 0)
00339                         return c;
00340         }       
00341 
00342         if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
00343                 c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
00344         else
00345                 c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
00346 
00347         if (c != 0)
00348                 return c;
00349 
00350         if ((ev->mods & KM_SHIFT) != 0)
00351                 c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
00352         else
00353                 c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
00354 
00355         if (c != 0)
00356                 return c;
00357 
00358         if ((ev->mods & KM_NUM_LOCK) != 0)
00359                 c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
00360         else
00361                 c = 0;
00362 
00363         return c;
00364 }
00365 
00366 static bool key_is_mod(unsigned key)
00367 {
00368         switch (key) {
00369         case KC_LSHIFT:
00370         case KC_RSHIFT:
00371         case KC_LALT:
00372         case KC_RALT:
00373         case KC_LCTRL:
00374         case KC_RCTRL:
00375                 return true;
00376         default:
00377                 return false;
00378         }
00379 }
00380 
00381 static void layout_reset(void)
00382 {
00383         mstate = ms_start;
00384 }
00385 
00386 static wchar_t layout_parse_ev(console_event_t *ev)
00387 {
00388         if (ev->type != KEY_PRESS)
00389                 return 0;
00390         
00391         if (key_is_mod(ev->key))
00392                 return 0;
00393         
00394         switch (mstate) {
00395         case ms_start:
00396                 return parse_ms_start(ev);
00397         case ms_hacek:
00398                 return parse_ms_hacek(ev);
00399         case ms_carka:
00400                 return parse_ms_carka(ev);
00401         }
00402         
00403         return 0;
00404 }
00405 

Generated on Thu Jun 2 07:45:50 2011 for HelenOS/USB by  doxygen 1.4.7