qmk

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.z3bra.org/qmk.git
Log | Files | Refs | Submodules | LICENSE

process_unicode_common.c (7359B)


      1 /* Copyright 2017 Jack Humbert
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 2 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15  */
     16 
     17 #include "process_unicode_common.h"
     18 #include "eeprom.h"
     19 #include <ctype.h>
     20 #include <string.h>
     21 
     22 unicode_config_t unicode_config;
     23 uint8_t          unicode_saved_mods;
     24 
     25 #if UNICODE_SELECTED_MODES != -1
     26 static uint8_t selected[]     = {UNICODE_SELECTED_MODES};
     27 static uint8_t selected_count = sizeof selected / sizeof *selected;
     28 static uint8_t selected_index;
     29 #endif
     30 
     31 void unicode_input_mode_init(void) {
     32     unicode_config.raw = eeprom_read_byte(EECONFIG_UNICODEMODE);
     33 #if UNICODE_SELECTED_MODES != -1
     34 #    if UNICODE_CYCLE_PERSIST
     35     // Find input_mode in selected modes
     36     uint8_t i;
     37     for (i = 0; i < selected_count; i++) {
     38         if (selected[i] == unicode_config.input_mode) {
     39             selected_index = i;
     40             break;
     41         }
     42     }
     43     if (i == selected_count) {
     44         // Not found: input_mode isn't selected, change to one that is
     45         unicode_config.input_mode = selected[selected_index = 0];
     46     }
     47 #    else
     48     // Always change to the first selected input mode
     49     unicode_config.input_mode = selected[selected_index = 0];
     50 #    endif
     51 #endif
     52     dprintf("Unicode input mode init to: %u\n", unicode_config.input_mode);
     53 }
     54 
     55 uint8_t get_unicode_input_mode(void) { return unicode_config.input_mode; }
     56 
     57 void set_unicode_input_mode(uint8_t mode) {
     58     unicode_config.input_mode = mode;
     59     persist_unicode_input_mode();
     60     dprintf("Unicode input mode set to: %u\n", unicode_config.input_mode);
     61 }
     62 
     63 void cycle_unicode_input_mode(uint8_t offset) {
     64 #if UNICODE_SELECTED_MODES != -1
     65     selected_index            = (selected_index + offset) % selected_count;
     66     unicode_config.input_mode = selected[selected_index];
     67 #    if UNICODE_CYCLE_PERSIST
     68     persist_unicode_input_mode();
     69 #    endif
     70     dprintf("Unicode input mode cycle to: %u\n", unicode_config.input_mode);
     71 #endif
     72 }
     73 
     74 void persist_unicode_input_mode(void) { eeprom_update_byte(EECONFIG_UNICODEMODE, unicode_config.input_mode); }
     75 
     76 __attribute__((weak)) void unicode_input_start(void) {
     77     unicode_saved_mods = get_mods();  // Save current mods
     78     clear_mods();                     // Unregister mods to start from a clean state
     79 
     80     switch (unicode_config.input_mode) {
     81         case UC_OSX:
     82             register_code(UNICODE_KEY_OSX);
     83             break;
     84         case UC_LNX:
     85             tap_code16(UNICODE_KEY_LNX);
     86             break;
     87         case UC_WIN:
     88             register_code(KC_LALT);
     89             tap_code(KC_PPLS);
     90             break;
     91         case UC_WINC:
     92             tap_code(UNICODE_KEY_WINC);
     93             tap_code(KC_U);
     94             break;
     95     }
     96 
     97     wait_ms(UNICODE_TYPE_DELAY);
     98 }
     99 
    100 __attribute__((weak)) void unicode_input_finish(void) {
    101     switch (unicode_config.input_mode) {
    102         case UC_OSX:
    103             unregister_code(UNICODE_KEY_OSX);
    104             break;
    105         case UC_LNX:
    106             tap_code(KC_SPC);
    107             break;
    108         case UC_WIN:
    109             unregister_code(KC_LALT);
    110             break;
    111         case UC_WINC:
    112             tap_code(KC_ENTER);
    113             break;
    114     }
    115 
    116     set_mods(unicode_saved_mods);  // Reregister previously set mods
    117 }
    118 
    119 __attribute__((weak)) void unicode_input_cancel(void) {
    120     switch (unicode_config.input_mode) {
    121         case UC_OSX:
    122             unregister_code(UNICODE_KEY_OSX);
    123             break;
    124         case UC_LNX:
    125         case UC_WINC:
    126             tap_code(KC_ESC);
    127             break;
    128         case UC_WIN:
    129             unregister_code(KC_LALT);
    130             break;
    131     }
    132 
    133     set_mods(unicode_saved_mods);  // Reregister previously set mods
    134 }
    135 
    136 __attribute__((weak)) uint16_t hex_to_keycode(uint8_t hex) {
    137     if (hex == 0x0) {
    138         return KC_0;
    139     } else if (hex < 0xA) {
    140         return KC_1 + (hex - 0x1);
    141     } else {
    142         return KC_A + (hex - 0xA);
    143     }
    144 }
    145 
    146 void register_hex(uint16_t hex) {
    147     for (int i = 3; i >= 0; i--) {
    148         uint8_t digit = ((hex >> (i * 4)) & 0xF);
    149         tap_code(hex_to_keycode(digit));
    150     }
    151 }
    152 
    153 void send_unicode_hex_string(const char *str) {
    154     if (!str) {
    155         return;
    156     }
    157 
    158     while (*str) {
    159         // Find the next code point (token) in the string
    160         for (; *str == ' '; str++)
    161             ;
    162         size_t n = strcspn(str, " ");  // Length of the current token
    163         char   code_point[n + 1];
    164         strncpy(code_point, str, n);
    165         code_point[n] = '\0';  // Make sure it's null-terminated
    166 
    167         // Normalize the code point: make all hex digits lowercase
    168         for (char *p = code_point; *p; p++) {
    169             *p = tolower((unsigned char)*p);
    170         }
    171 
    172         // Send the code point as a Unicode input string
    173         unicode_input_start();
    174         send_string(code_point);
    175         unicode_input_finish();
    176 
    177         str += n;  // Move to the first ' ' (or '\0') after the current token
    178     }
    179 }
    180 
    181 bool process_unicode_common(uint16_t keycode, keyrecord_t *record) {
    182     if (record->event.pressed) {
    183         switch (keycode) {
    184             case UNICODE_MODE_FORWARD:
    185                 cycle_unicode_input_mode(+1);
    186                 break;
    187             case UNICODE_MODE_REVERSE:
    188                 cycle_unicode_input_mode(-1);
    189                 break;
    190 
    191             case UNICODE_MODE_OSX:
    192                 set_unicode_input_mode(UC_OSX);
    193 #if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_OSX)
    194                 static float song_osx[][2] = UNICODE_SONG_OSX;
    195                 PLAY_SONG(song_osx);
    196 #endif
    197                 break;
    198             case UNICODE_MODE_LNX:
    199                 set_unicode_input_mode(UC_LNX);
    200 #if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_LNX)
    201                 static float song_lnx[][2] = UNICODE_SONG_LNX;
    202                 PLAY_SONG(song_lnx);
    203 #endif
    204                 break;
    205             case UNICODE_MODE_WIN:
    206                 set_unicode_input_mode(UC_WIN);
    207 #if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_WIN)
    208                 static float song_win[][2] = UNICODE_SONG_WIN;
    209                 PLAY_SONG(song_win);
    210 #endif
    211                 break;
    212             case UNICODE_MODE_BSD:
    213                 set_unicode_input_mode(UC_BSD);
    214 #if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_BSD)
    215                 static float song_bsd[][2] = UNICODE_SONG_BSD;
    216                 PLAY_SONG(song_bsd);
    217 #endif
    218                 break;
    219             case UNICODE_MODE_WINC:
    220                 set_unicode_input_mode(UC_WINC);
    221 #if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_WINC)
    222                 static float song_winc[][2] = UNICODE_SONG_WINC;
    223                 PLAY_SONG(song_winc);
    224 #endif
    225                 break;
    226         }
    227     }
    228 #if defined(UNICODE_ENABLE)
    229     return process_unicode(keycode, record);
    230 #elif defined(UNICODEMAP_ENABLE)
    231     return process_unicodemap(keycode, record);
    232 #elif defined(UCIS_ENABLE)
    233     return process_ucis(keycode, record);
    234 #else
    235     return true;
    236 #endif
    237 }