URI: 
       keys.c - ledit - Text editor (WIP)
  HTML git clone git://lumidify.org/ledit.git (fast, but not encrypted)
  HTML git clone https://lumidify.org/ledit.git (encrypted, but very slow)
  HTML git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ledit.git (over tor)
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       keys.c (3571B)
       ---
            1 #include <limits.h>
            2 
            3 #include <X11/Xlib.h>
            4 #include <X11/Xutil.h>
            5 #include <X11/keysym.h>
            6 #include <X11/XF86keysym.h>
            7 #include <pango/pangoxft.h>
            8 #include <X11/extensions/Xdbe.h>
            9 
           10 #include "memory.h"
           11 #include "common.h"
           12 #include "txtbuf.h"
           13 #include "window.h"
           14 #include "keys.h"
           15 
           16 /* FIXME: Does this break anything? */
           17 /* FIXME: ShiftMask is currently masked away when the key contains text - is this correct? */
           18 /* FIXME: The Mod*Masks can be remapped, so it isn't really clear what is what */
           19 /* LockMask and Mod2Mask in particular are disabled (caps lock and numlock usually) */
           20 static unsigned int importantmod = ShiftMask | ControlMask | Mod1Mask | Mod3Mask | Mod4Mask | Mod5Mask;
           21 
           22 #define KEY_TEXT_INITIAL_SIZE 32
           23 static char *key_text = NULL;
           24 static size_t key_text_alloc = 0;
           25 
           26 void
           27 key_processing_cleanup(void) {
           28         free(key_text);
           29 }
           30 
           31 int
           32 match_key(unsigned int mask, unsigned int state)
           33 {
           34         return mask == XK_ANY_MOD || mask == (state & importantmod);
           35 }
           36 
           37 #ifdef X_HAVE_UTF8_STRING
           38 #define LOOKUP_STRING_FUNC Xutf8LookupString
           39 #else
           40 #define LOOKUP_STRING_FUNC XmbLookupString
           41 #endif
           42 
           43 void
           44 preprocess_key(
           45     ledit_window *window, XKeyEvent *event, KeySym *sym_ret,
           46     char **buf_ret, int *buf_len_ret) {
           47         /*
           48          * FIXME: I don't understand how key handling works with different keymaps.
           49          * If, for instance, you run "setxkbmap pk" and then type "Ctrl+c", the
           50          * keysym will be "0x1000686, Arabic_tcheh" and the appropriate string will
           51          * be returned by XmbLookupString (tested also using xev).
           52          * If, however, you run "setxkbmap -layout "us,pk" -option grp:shifts_toggle"
           53          * and type "Ctrl+c" after switching to the pk layout, the keysym will just
           54          * be "0x63, c" and XmbLookupString will return the control code sent by
           55          * Ctrl+c (ascii 03). This means the handling is different depending on how
           56          * the keymap is switched to, and I have no clue what the proper way to
           57          * handle this would be, since the shortcuts are explicitly supposed to work
           58          * properly in all language maps. My current solution is to just ignore the
           59          * control key in the state so the text found by Xutf8LookupString is correct
           60          * and the modifier mask can be checked separately. Please tell me if you
           61          * know the proper way to do this.
           62          */
           63         /*
           64          * Note on the above: I guess XKB tries to be smart and map the keys back to
           65          * the first language when control is pressed and multiple languages are
           66          * configured. This is completely useless for ledit, though, because most
           67          * keys don't use control in normal mode, and it just messes with all the
           68          * keys that do use control because ledit does its own mapping.
           69          */
           70         if (key_text_alloc == 0) {
           71                 key_text = ledit_malloc(KEY_TEXT_INITIAL_SIZE);
           72                 key_text_alloc = KEY_TEXT_INITIAL_SIZE;
           73         }
           74         event->state &= ~ControlMask;
           75 
           76         int len = 0;
           77         Status status;
           78         if (window->xic && event->type == KeyPress) {
           79                 len = LOOKUP_STRING_FUNC(window->xic, event, key_text, key_text_alloc - 1, sym_ret, &status);
           80                 if (status == XBufferOverflow) {
           81                         key_text_alloc = ideal_array_size(key_text_alloc, len + 1);
           82                         key_text = ledit_realloc(key_text, key_text_alloc);
           83                         len = LOOKUP_STRING_FUNC(window->xic, event, key_text, key_text_alloc - 1, sym_ret, &status);
           84                 }
           85         } else {
           86                 /* FIXME: anything equivalent to XBufferOverflow here? */
           87                 len = XLookupString(event, key_text, key_text_alloc - 1, sym_ret, NULL);
           88                 status = XLookupBoth;
           89         }
           90         *buf_len_ret = len >= (int)key_text_alloc ? (int)key_text_alloc - 1 : len;
           91         key_text[*buf_len_ret] = '\0';
           92         if (status != XLookupBoth && status != XLookupKeySym)
           93                 *sym_ret = NoSymbol;
           94         *buf_ret = key_text;
           95 }