LCOV - code coverage report
Current view: top level - src - keysym.cc (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 46 46 100.0 %
Date: 2022-06-15 20:16:21 Functions: 5 7 71.4 %
Branches: 40 42 95.2 %

           Branch data     Line data    Source code
       1                 :            : #ifdef RUN_TESTS
       2                 :            : # include <gtest/gtest.h>
       3                 :            : #endif
       4                 :            : /** @file keysym.cc
       5                 :            :  * @brief Defines InterpretInput()
       6                 :            :  */
       7                 :            : 
       8                 :            : #include <unordered_map>
       9                 :            : #include <cstdio> // sprintf
      10                 :            : 
      11                 :            : #include "keysym.hh"
      12                 :            : #include "ctype.hh"
      13                 :            : 
      14                 :            : /** Define mappings between SDL keys and ESC[ sequences */
      15                 :            : static const std::unordered_map<int, std::pair<int/*num*/,char/*letter*/>> lore
      16                 :            : {
      17                 :            :     { SDLK_F1,       {1,'P'} },  { SDLK_LEFT,     {1,'D'} },
      18                 :            :     { SDLK_F2,       {1,'Q'} },  { SDLK_RIGHT,    {1,'C'} },
      19                 :            :     { SDLK_F3,       {1,'R'} },  { SDLK_UP,       {1,'A'} },
      20                 :            :     { SDLK_F4,       {1,'S'} },  { SDLK_DOWN,     {1,'B'} },
      21                 :            :     { SDLK_F5,       {15,'~'} }, { SDLK_HOME,     {1,'H'} },
      22                 :            :     { SDLK_F6,       {17,'~'} }, { SDLK_END,      {1,'F'} },
      23                 :            :     { SDLK_F7,       {18,'~'} }, { SDLK_INSERT,   {2,'~'} },
      24                 :            :     { SDLK_F8,       {19,'~'} }, { SDLK_DELETE,   {3,'~'} },
      25                 :            :     { SDLK_F9,       {20,'~'} }, { SDLK_PAGEUP,   {5,'~'} },
      26                 :            :     { SDLK_F10,      {21,'~'} }, { SDLK_PAGEDOWN, {6,'~'} },
      27                 :            :     { SDLK_F11,      {23,'~'} },
      28                 :            :     { SDLK_F12,      {24,'~'} },
      29                 :            : };
      30                 :            : /** Mappings between SDL keys and ASCII sequences */
      31                 :            : static const std::unordered_map<int, char> lore2
      32                 :            : {
      33                 :            :     { SDLK_a, 'a' }, { SDLK_b, 'b' }, { SDLK_c, 'c' }, { SDLK_d, 'd' },
      34                 :            :     { SDLK_e, 'e' }, { SDLK_f, 'f' }, { SDLK_g, 'g' }, { SDLK_h, 'h' },
      35                 :            :     { SDLK_i, 'i' }, { SDLK_j, 'j' }, { SDLK_k, 'k' }, { SDLK_l, 'l' },
      36                 :            :     { SDLK_m, 'm' }, { SDLK_n, 'n' }, { SDLK_o, 'o' }, { SDLK_p, 'p' },
      37                 :            :     { SDLK_q, 'q' }, { SDLK_r, 'r' }, { SDLK_s, 's' }, { SDLK_t, 't' },
      38                 :            :     { SDLK_u, 'u' }, { SDLK_v, 'v' }, { SDLK_w, 'w' }, { SDLK_x, 'x' },
      39                 :            :     { SDLK_y, 'y' }, { SDLK_z, 'z' }, { SDLK_ESCAPE, '\33' },
      40                 :            :     { SDLK_0, '0' }, { SDLK_1, '1' }, { SDLK_2, '2' }, { SDLK_3, '3' },
      41                 :            :     { SDLK_4, '4' }, { SDLK_5, '5' }, { SDLK_6, '6' }, { SDLK_7, '7' },
      42                 :            :     { SDLK_8, '8' }, { SDLK_9, '9' }, { SDLK_PERIOD, '.' },
      43                 :            :     { SDLK_COMMA, ',' }, { SDLK_SLASH, '-' },
      44                 :            :     { SDLK_RETURN, '\r' }, { SDLK_BACKSPACE, '\177' }, { SDLK_TAB, '\t' },
      45                 :            :     { SDLK_SPACE, ' ' }, { SDLK_KP_ENTER, '\r' },
      46                 :            : };
      47                 :            : 
      48                 :        552 : std::string InterpretInput(bool shift, bool alt, bool ctrl, SDL_Keycode sym)
      49                 :            : {
      50         [ +  + ]:        552 :     if(auto i = lore.find(sym); i != lore.end())
      51                 :            :     {
      52         [ +  + ]:        173 :         const auto& d = i->second;
      53                 :        173 :         unsigned delta = 1 + shift*1 + alt*2 + ctrl*4, len;
      54                 :        173 :         char bracket = '[', Buf[16];
      55         [ +  + ]:        173 :         if(d.second >= 'P' && d.second <= 'S') bracket = 'O';
      56   [ +  +  +  + ]:        173 :         if(d.second >= 'A' && d.second <= 'D' && delta == 1) bracket = 'O'; // less requires this for up&down, alsamixer requires this for left&right
      57         [ +  + ]:        173 :         if(delta != 1)
      58                 :        158 :             len = std::sprintf(Buf, "\33%c%d;%d%c", bracket, d.first, delta, d.second);
      59         [ +  + ]:         15 :         else if(d.first == 1)
      60                 :          7 :             len = std::sprintf(Buf, "\33%c%c", bracket, d.second);
      61                 :            :         else
      62                 :          8 :             len = std::sprintf(Buf, "\33%c%d%c", bracket, d.first, d.second);
      63                 :        173 :         return std::string(Buf,len);
      64                 :            :     }
      65                 :            : 
      66         [ +  + ]:        379 :     if(auto i = lore2.find(sym); i != lore2.end())
      67                 :            :     {
      68         [ +  + ]:        367 :         char32_t cval = i->second;
      69                 :        367 :         bool digit = cval >= '0' && cval <= '9', alpha = cval >= 'a' && cval <= 'z';
      70         [ +  + ]:        367 :         if(shift && alpha) cval &= ~0x20; // Turn uppercase
      71         [ +  + ]:        367 :         if(ctrl && digit) cval = "01\0\33\34\35\36\37\1779"[cval-'0'];
      72   [ +  +  +  + ]:        367 :         if(ctrl && i->second=='\177') cval = '\b';
      73         [ +  + ]:        363 :         else if(ctrl && !digit) cval &= 0x1F; // Turn into a control character
      74                 :            :         // CTRL a..z becomes 01..1A
      75                 :            :         // CTRL 0..9 becomes 10..19, should become xx,xx,00,1B-1F,7F,xx
      76         [ +  + ]:        367 :         if(alt) cval |= 0x80;  // Add ALT
      77   [ +  +  +  + ]:        367 :         if((!alpha && !digit) || ctrl||alt)
      78                 :            :         {
      79                 :            :             //std::fprintf(stderr, "lore input(%c)(%d) with keysym=%d\n", char(cval), int(cval), sym);
      80   [ +  +  +  + ]:        293 :             if(shift && cval == '\t')
      81         [ +  - ]:          4 :                 return std::string("\33[Z", 3);
      82                 :            :             else
      83         [ +  - ]:        289 :                 return ToUTF8(std::u32string_view(&cval,1));
      84                 :            :         }
      85                 :            :     }
      86                 :            : 
      87                 :        552 :     return {};
      88                 :            : }
      89                 :            : 
      90                 :            : 
      91                 :            : #ifdef RUN_TESTS
      92                 :          3 : TEST(keysym, control_keys)
      93                 :            : {
      94                 :          2 :     EXPECT_EQ(InterpretInput(false,false,false, SDLK_F1), "\033OP");
      95                 :          2 :     EXPECT_EQ(InterpretInput(true, false,false, SDLK_F1), "\033O1;2P");
      96                 :          2 :     EXPECT_EQ(InterpretInput(false,false, true, SDLK_F1), "\033O1;5P");
      97                 :          2 :     EXPECT_EQ(InterpretInput(true, false, true, SDLK_F1), "\033O1;6P");
      98                 :          2 :     EXPECT_EQ(InterpretInput(true,  true, true, SDLK_F1), "\033O1;8P");
      99                 :          2 :     EXPECT_EQ(InterpretInput(false,false,false, SDLK_INSERT),   "\033[2~");
     100                 :          2 :     EXPECT_EQ(InterpretInput(false,false,false, SDLK_DELETE),   "\033[3~");
     101                 :          2 :     EXPECT_EQ(InterpretInput(false,false,false, SDLK_PAGEUP),   "\033[5~");
     102                 :          2 :     EXPECT_EQ(InterpretInput(false,false,false, SDLK_PAGEDOWN), "\033[6~");
     103                 :          1 : }
     104                 :          3 : TEST(keysym, regular_keys)
     105                 :            : {
     106                 :            :     // Alphabetic input is disabled in order to not conflict with SDL TextInput
     107                 :          2 :     EXPECT_EQ(InterpretInput(false,false,false, SDLK_a), "");
     108                 :          2 :     EXPECT_EQ(InterpretInput(true, false,false, SDLK_a), "");
     109                 :          2 :     EXPECT_EQ(InterpretInput(false,false, true, SDLK_c), "\3"); // ctrl-c
     110                 :          2 :     EXPECT_EQ(InterpretInput(false,false,false, SDLK_TAB),    "\t");
     111                 :          2 :     EXPECT_EQ(InterpretInput(true,false,false, SDLK_TAB),     "\033[Z");
     112                 :          2 :     EXPECT_EQ(InterpretInput(false,false,false, SDLK_RETURN), "\r");
     113                 :          2 :     EXPECT_EQ(InterpretInput(false,false,false, SDLK_SPACE),  " ");
     114                 :          1 : }
     115                 :            : #endif

Generated by: LCOV version 1.16