ledit

Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/ledit.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ledit.git (over tor)
Log | Files | Refs | README | 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 }