mirror of
https://github.com/mintycube/dmenu.git
synced 2024-10-22 12:05:48 +00:00
Compare commits
No commits in common. "cde29093ca07b2753ebe2fa6a79db24ab60ccb8c" and "a5f48fb1d7bcc044734009ddd8e70ea1efcce4fa" have entirely different histories.
cde29093ca
...
a5f48fb1d7
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1 +0,0 @@
|
|||||||
README.md merge=ours
|
|
46
dmenu.c
46
dmenu.c
@ -178,6 +178,15 @@ static Clr *scheme[SchemeLast];
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#if CASEINSENSITIVE_PATCH
|
||||||
|
static char * cistrstr(const char *s, const char *sub);
|
||||||
|
static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp;
|
||||||
|
static char *(*fstrstr)(const char *, const char *) = cistrstr;
|
||||||
|
#else
|
||||||
|
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
|
||||||
|
static char *(*fstrstr)(const char *, const char *) = strstr;
|
||||||
|
#endif // CASEINSENSITIVE_PATCH
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
textw_clamp(const char *str, unsigned int n)
|
textw_clamp(const char *str, unsigned int n)
|
||||||
{
|
{
|
||||||
@ -207,14 +216,6 @@ static void run(void);
|
|||||||
static void setup(void);
|
static void setup(void);
|
||||||
static void usage(void);
|
static void usage(void);
|
||||||
|
|
||||||
#if CASEINSENSITIVE_PATCH
|
|
||||||
static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp;
|
|
||||||
static char *(*fstrstr)(const char *, const char *) = cistrstr;
|
|
||||||
#else
|
|
||||||
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
|
|
||||||
static char *(*fstrstr)(const char *, const char *) = strstr;
|
|
||||||
#endif // CASEINSENSITIVE_PATCH
|
|
||||||
|
|
||||||
#include "patch/include.c"
|
#include "patch/include.c"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -269,9 +270,6 @@ cleanup(void)
|
|||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
||||||
#if INPUTMETHOD_PATCH
|
|
||||||
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
|
|
||||||
#endif // INPUTMETHOD_PATCH
|
|
||||||
for (i = 0; i < SchemeLast; i++)
|
for (i = 0; i < SchemeLast; i++)
|
||||||
free(scheme[i]);
|
free(scheme[i]);
|
||||||
for (i = 0; items && items[i].text; ++i)
|
for (i = 0; items && items[i].text; ++i)
|
||||||
@ -1508,6 +1506,7 @@ run(void)
|
|||||||
#if PRESELECT_PATCH
|
#if PRESELECT_PATCH
|
||||||
int i;
|
int i;
|
||||||
#endif // PRESELECT_PATCH
|
#endif // PRESELECT_PATCH
|
||||||
|
|
||||||
while (!XNextEvent(dpy, &ev)) {
|
while (!XNextEvent(dpy, &ev)) {
|
||||||
#if PRESELECT_PATCH
|
#if PRESELECT_PATCH
|
||||||
if (preselected) {
|
if (preselected) {
|
||||||
@ -1521,15 +1520,8 @@ run(void)
|
|||||||
preselected = 0;
|
preselected = 0;
|
||||||
}
|
}
|
||||||
#endif // PRESELECT_PATCH
|
#endif // PRESELECT_PATCH
|
||||||
#if INPUTMETHOD_PATCH
|
|
||||||
if (XFilterEvent(&ev, None))
|
|
||||||
continue;
|
|
||||||
if (composing)
|
|
||||||
continue;
|
|
||||||
#else
|
|
||||||
if (XFilterEvent(&ev, win))
|
if (XFilterEvent(&ev, win))
|
||||||
continue;
|
continue;
|
||||||
#endif // INPUTMETHOD_PATCH
|
|
||||||
switch(ev.type) {
|
switch(ev.type) {
|
||||||
#if MOUSE_SUPPORT_PATCH
|
#if MOUSE_SUPPORT_PATCH
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
@ -1796,16 +1788,13 @@ setup(void)
|
|||||||
(unsigned char *) &dock, 1);
|
(unsigned char *) &dock, 1);
|
||||||
#endif // WMTYPE_PATCH
|
#endif // WMTYPE_PATCH
|
||||||
|
|
||||||
|
|
||||||
/* input methods */
|
/* input methods */
|
||||||
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL)
|
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL)
|
||||||
die("XOpenIM failed: could not open input device");
|
die("XOpenIM failed: could not open input device");
|
||||||
|
|
||||||
#if INPUTMETHOD_PATCH
|
|
||||||
init_input_method(xim);
|
|
||||||
#else
|
|
||||||
xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
||||||
XNClientWindow, win, XNFocusWindow, win, NULL);
|
XNClientWindow, win, XNFocusWindow, win, NULL);
|
||||||
#endif // INPUTMETHOD_PATCH
|
|
||||||
|
|
||||||
#if MANAGED_PATCH
|
#if MANAGED_PATCH
|
||||||
if (managed) {
|
if (managed) {
|
||||||
@ -1827,13 +1816,8 @@ setup(void)
|
|||||||
XSelectInput(dpy, dws[i], FocusChangeMask);
|
XSelectInput(dpy, dws[i], FocusChangeMask);
|
||||||
XFree(dws);
|
XFree(dws);
|
||||||
}
|
}
|
||||||
#if !INPUTMETHOD_PATCH
|
|
||||||
grabfocus();
|
grabfocus();
|
||||||
#endif // INPUTMETHOD_PATCH
|
|
||||||
}
|
}
|
||||||
#if INPUTMETHOD_PATCH
|
|
||||||
grabfocus();
|
|
||||||
#endif // INPUTMETHOD_PATCH
|
|
||||||
drw_resize(drw, mw, mh);
|
drw_resize(drw, mw, mh);
|
||||||
drawmenu();
|
drawmenu();
|
||||||
}
|
}
|
||||||
@ -1949,10 +1933,6 @@ main(int argc, char *argv[])
|
|||||||
#if XRESOURCES_PATCH
|
#if XRESOURCES_PATCH
|
||||||
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
|
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
|
||||||
fputs("warning: no locale support\n", stderr);
|
fputs("warning: no locale support\n", stderr);
|
||||||
#if INPUTMETHOD_PATCH
|
|
||||||
if (!XSetLocaleModifiers(""))
|
|
||||||
fputs("warning: could not set locale modifiers", stderr);
|
|
||||||
#endif // INPUTMETHOD_PATCH
|
|
||||||
if (!(dpy = XOpenDisplay(NULL)))
|
if (!(dpy = XOpenDisplay(NULL)))
|
||||||
die("cannot open display");
|
die("cannot open display");
|
||||||
|
|
||||||
@ -2185,10 +2165,6 @@ main(int argc, char *argv[])
|
|||||||
#else // !XRESOURCES_PATCH
|
#else // !XRESOURCES_PATCH
|
||||||
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
|
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
|
||||||
fputs("warning: no locale support\n", stderr);
|
fputs("warning: no locale support\n", stderr);
|
||||||
#if INPUTMETHOD_PATCH
|
|
||||||
if (!XSetLocaleModifiers(""))
|
|
||||||
fputs("warning: could not set locale modifiers", stderr);
|
|
||||||
#endif // INPUTMETHOD_PATCH
|
|
||||||
if (!(dpy = XOpenDisplay(NULL)))
|
if (!(dpy = XOpenDisplay(NULL)))
|
||||||
die("cannot open display");
|
die("cannot open display");
|
||||||
screen = DefaultScreen(dpy);
|
screen = DefaultScreen(dpy);
|
||||||
|
98
drw.c
98
drw.c
@ -11,50 +11,63 @@
|
|||||||
|
|
||||||
#if !PANGO_PATCH || HIGHLIGHT_PATCH
|
#if !PANGO_PATCH || HIGHLIGHT_PATCH
|
||||||
#define UTF_INVALID 0xFFFD
|
#define UTF_INVALID 0xFFFD
|
||||||
|
#define UTF_SIZ 4
|
||||||
|
|
||||||
static int
|
static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
|
||||||
utf8decode(const char *s_in, long *u, int *err)
|
static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
|
||||||
|
static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
|
||||||
|
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
|
||||||
|
|
||||||
|
static long
|
||||||
|
utf8decodebyte(const char c, size_t *i)
|
||||||
{
|
{
|
||||||
static const unsigned char lens[] = {
|
for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
|
||||||
/* 0XXXX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
|
||||||
/* 10XXX */ 0, 0, 0, 0, 0, 0, 0, 0, /* invalid */
|
return (unsigned char)c & ~utfmask[*i];
|
||||||
/* 110XX */ 2, 2, 2, 2,
|
return 0;
|
||||||
/* 1110X */ 3, 3,
|
}
|
||||||
/* 11110 */ 4,
|
|
||||||
/* 11111 */ 0, /* invalid */
|
|
||||||
};
|
|
||||||
static const unsigned char leading_mask[] = { 0x7F, 0x1F, 0x0F, 0x07 };
|
|
||||||
static const unsigned int overlong[] = { 0x0, 0x80, 0x0800, 0x10000 };
|
|
||||||
|
|
||||||
const unsigned char *s = (const unsigned char *)s_in;
|
static size_t
|
||||||
int len = lens[*s >> 3];
|
utf8validate(long *u, size_t i)
|
||||||
|
{
|
||||||
|
if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
|
||||||
*u = UTF_INVALID;
|
*u = UTF_INVALID;
|
||||||
*err = 1;
|
for (i = 1; *u > utfmax[i]; ++i)
|
||||||
if (len == 0)
|
;
|
||||||
return 1;
|
|
||||||
|
|
||||||
long cp = s[0] & leading_mask[len - 1];
|
|
||||||
for (int i = 1; i < len; ++i) {
|
|
||||||
if (s[i] == '\0' || (s[i] & 0xC0) != 0x80)
|
|
||||||
return i;
|
return i;
|
||||||
cp = (cp << 6) | (s[i] & 0x3F);
|
}
|
||||||
}
|
|
||||||
/* out of range, surrogate, overlong encoding */
|
static size_t
|
||||||
if (cp > 0x10FFFF || (cp >> 11) == 0x1B || cp < overlong[len - 1])
|
utf8decode(const char *c, long *u, size_t clen)
|
||||||
return len;
|
{
|
||||||
|
size_t i, j, len, type;
|
||||||
|
long udecoded;
|
||||||
|
|
||||||
|
*u = UTF_INVALID;
|
||||||
|
if (!clen)
|
||||||
|
return 0;
|
||||||
|
udecoded = utf8decodebyte(c[0], &len);
|
||||||
|
if (!BETWEEN(len, 1, UTF_SIZ))
|
||||||
|
return 1;
|
||||||
|
for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
|
||||||
|
udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
|
||||||
|
if (type)
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
if (j < len)
|
||||||
|
return 0;
|
||||||
|
*u = udecoded;
|
||||||
|
utf8validate(u, len);
|
||||||
|
|
||||||
*err = 0;
|
|
||||||
*u = cp;
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HIGHLIGHT_PATCH
|
#if HIGHLIGHT_PATCH
|
||||||
int
|
size_t
|
||||||
utf8len(const char *c)
|
utf8len(const char *c)
|
||||||
{
|
{
|
||||||
long utf8codepoint = 0;
|
long utf8codepoint = 0;
|
||||||
int utf8err = 0;
|
return utf8decode(c, &utf8codepoint, UTF_SIZ);
|
||||||
return utf8decode(c, &utf8codepoint, &utf8err);
|
|
||||||
}
|
}
|
||||||
#endif // HIGHLIGHT_PATCH
|
#endif // HIGHLIGHT_PATCH
|
||||||
#endif // PANGO_PATCH
|
#endif // PANGO_PATCH
|
||||||
@ -434,7 +447,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
|||||||
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1;
|
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1;
|
||||||
XftDraw *d = NULL;
|
XftDraw *d = NULL;
|
||||||
Fnt *usedfont, *curfont, *nextfont;
|
Fnt *usedfont, *curfont, *nextfont;
|
||||||
int utf8strlen, utf8charlen, utf8err, render = x || y || w || h;
|
int utf8strlen, utf8charlen, render = x || y || w || h;
|
||||||
long utf8codepoint = 0;
|
long utf8codepoint = 0;
|
||||||
const char *utf8str;
|
const char *utf8str;
|
||||||
FcCharSet *fccharset;
|
FcCharSet *fccharset;
|
||||||
@ -443,8 +456,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
|||||||
XftResult result;
|
XftResult result;
|
||||||
int charexists = 0, overflow = 0;
|
int charexists = 0, overflow = 0;
|
||||||
/* keep track of a couple codepoints for which we have no match. */
|
/* keep track of a couple codepoints for which we have no match. */
|
||||||
static unsigned int nomatches[128], ellipsis_width, invalid_width;
|
static unsigned int nomatches[128], ellipsis_width;
|
||||||
static const char invalid[] = "<EFBFBD>";
|
|
||||||
const char *ellipsis = "...";
|
const char *ellipsis = "...";
|
||||||
|
|
||||||
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
|
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
|
||||||
@ -469,14 +481,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
|||||||
usedfont = drw->fonts;
|
usedfont = drw->fonts;
|
||||||
if (!ellipsis_width && render)
|
if (!ellipsis_width && render)
|
||||||
ellipsis_width = drw_fontset_getwidth(drw, ellipsis);
|
ellipsis_width = drw_fontset_getwidth(drw, ellipsis);
|
||||||
if (!invalid_width && render)
|
|
||||||
invalid_width = drw_fontset_getwidth(drw, invalid);
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ew = ellipsis_len = utf8err = utf8strlen = 0;
|
ew = ellipsis_len = utf8strlen = 0;
|
||||||
utf8str = text;
|
utf8str = text;
|
||||||
nextfont = NULL;
|
nextfont = NULL;
|
||||||
while (*text) {
|
while (*text) {
|
||||||
utf8charlen = utf8decode(text, &utf8codepoint, &utf8err);
|
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
|
||||||
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
||||||
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
||||||
if (charexists) {
|
if (charexists) {
|
||||||
@ -498,9 +508,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
|||||||
else
|
else
|
||||||
utf8strlen = ellipsis_len;
|
utf8strlen = ellipsis_len;
|
||||||
} else if (curfont == usedfont) {
|
} else if (curfont == usedfont) {
|
||||||
|
utf8strlen += utf8charlen;
|
||||||
text += utf8charlen;
|
text += utf8charlen;
|
||||||
utf8strlen += utf8err ? 0 : utf8charlen;
|
ew += tmpw;
|
||||||
ew += utf8err ? 0 : tmpw;
|
|
||||||
} else {
|
} else {
|
||||||
nextfont = curfont;
|
nextfont = curfont;
|
||||||
}
|
}
|
||||||
@ -508,7 +518,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overflow || !charexists || nextfont || utf8err)
|
if (overflow || !charexists || nextfont)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
charexists = 0;
|
charexists = 0;
|
||||||
@ -523,12 +533,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
|||||||
x += ew;
|
x += ew;
|
||||||
w -= ew;
|
w -= ew;
|
||||||
}
|
}
|
||||||
if (utf8err && (!render || invalid_width < w)) {
|
|
||||||
if (render)
|
|
||||||
drw_text(drw, x, y, w, h, 0, invalid, invert);
|
|
||||||
x += invalid_width;
|
|
||||||
w -= invalid_width;
|
|
||||||
}
|
|
||||||
if (render && overflow && ellipsis_w)
|
if (render && overflow && ellipsis_w)
|
||||||
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, ellipsis, invert);
|
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, ellipsis, invert);
|
||||||
|
|
||||||
|
2
drw.h
2
drw.h
@ -69,7 +69,7 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in
|
|||||||
#endif // PANGO_PATCH
|
#endif // PANGO_PATCH
|
||||||
|
|
||||||
#if HIGHLIGHT_PATCH
|
#if HIGHLIGHT_PATCH
|
||||||
int utf8len(const char *c);
|
size_t utf8len(const char *c);
|
||||||
#endif // HIGHLIGHT_PATCH
|
#endif // HIGHLIGHT_PATCH
|
||||||
|
|
||||||
/* Colorscheme abstraction */
|
/* Colorscheme abstraction */
|
||||||
|
@ -13,9 +13,6 @@
|
|||||||
#if HIGHPRIORITY_PATCH
|
#if HIGHPRIORITY_PATCH
|
||||||
#include "highpriority.c"
|
#include "highpriority.c"
|
||||||
#endif
|
#endif
|
||||||
#if INPUTMETHOD_PATCH
|
|
||||||
#include "inputmethod.c"
|
|
||||||
#endif
|
|
||||||
#if DYNAMIC_OPTIONS_PATCH
|
#if DYNAMIC_OPTIONS_PATCH
|
||||||
#include "dynamicoptions.c"
|
#include "dynamicoptions.c"
|
||||||
#endif
|
#endif
|
||||||
|
@ -4,9 +4,6 @@
|
|||||||
#if FZFEXPECT_PATCH
|
#if FZFEXPECT_PATCH
|
||||||
#include "fzfexpect.h"
|
#include "fzfexpect.h"
|
||||||
#endif
|
#endif
|
||||||
#if INPUTMETHOD_PATCH
|
|
||||||
#include "inputmethod.h"
|
|
||||||
#endif
|
|
||||||
#if MULTI_SELECTION_PATCH
|
#if MULTI_SELECTION_PATCH
|
||||||
#include "multiselect.h"
|
#include "multiselect.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,196 +0,0 @@
|
|||||||
static size_t nextrunetext(const char *text, size_t position, int inc)
|
|
||||||
{
|
|
||||||
ssize_t n;
|
|
||||||
|
|
||||||
/* return location of next utf8 rune in the given direction (+1 or -1) */
|
|
||||||
for (n = position + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc)
|
|
||||||
;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return bytes from beginning of text to nth utf8 rune to the right */
|
|
||||||
static size_t runebytes(const char *text, size_t n)
|
|
||||||
{
|
|
||||||
size_t ret;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
while (n-- > 0)
|
|
||||||
ret += nextrunetext(text + ret, 0, 1);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return number of characters from beginning of text to nth byte to the right
|
|
||||||
*/
|
|
||||||
static size_t runechars(const char *text, size_t n)
|
|
||||||
{
|
|
||||||
size_t ret, i;
|
|
||||||
|
|
||||||
ret = i = 0;
|
|
||||||
while (i < n) {
|
|
||||||
i += nextrunetext(text + i, 0, 1);
|
|
||||||
ret++;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* move caret on pre-edit text */
|
|
||||||
static void preeditcaret(XIC xic, XPointer clientdata, XPointer calldata)
|
|
||||||
{
|
|
||||||
XIMPreeditCaretCallbackStruct *pcaret;
|
|
||||||
|
|
||||||
(void)xic;
|
|
||||||
pcaret = (XIMPreeditCaretCallbackStruct *)calldata;
|
|
||||||
if (!pcaret)
|
|
||||||
return;
|
|
||||||
switch (pcaret->direction) {
|
|
||||||
case XIMForwardChar:
|
|
||||||
cursor = nextrune(+1);
|
|
||||||
break;
|
|
||||||
case XIMBackwardChar:
|
|
||||||
cursor = nextrune(-1);
|
|
||||||
break;
|
|
||||||
case XIMForwardWord:
|
|
||||||
movewordedge(+1);
|
|
||||||
break;
|
|
||||||
case XIMBackwardWord:
|
|
||||||
movewordedge(-1);
|
|
||||||
break;
|
|
||||||
case XIMLineStart:
|
|
||||||
cursor = 0;
|
|
||||||
break;
|
|
||||||
case XIMLineEnd:
|
|
||||||
if (preview[cursor] != '\0')
|
|
||||||
cursor = strlen(preview);
|
|
||||||
break;
|
|
||||||
case XIMAbsolutePosition:
|
|
||||||
cursor = runebytes(text, pcaret->position);
|
|
||||||
break;
|
|
||||||
case XIMDontChange:
|
|
||||||
/* do nothing */
|
|
||||||
break;
|
|
||||||
case XIMCaretUp:
|
|
||||||
case XIMCaretDown:
|
|
||||||
case XIMNextLine:
|
|
||||||
case XIMPreviousLine:
|
|
||||||
/* not implemented */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pcaret->position = runechars(preview, cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* start input method pre-editing */
|
|
||||||
static int preeditstart(XIC xic, XPointer clientdata, XPointer calldata)
|
|
||||||
{
|
|
||||||
(void)xic;
|
|
||||||
(void)calldata;
|
|
||||||
(void)clientdata;
|
|
||||||
composing = 1;
|
|
||||||
printf("PREEDIT\n");
|
|
||||||
return BUFSIZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* end input method pre-editing */
|
|
||||||
static void preeditdone(XIC xic, XPointer clientdata, XPointer calldata)
|
|
||||||
{
|
|
||||||
(void)xic;
|
|
||||||
(void)clientdata;
|
|
||||||
(void)calldata;
|
|
||||||
printf("DONE\n");
|
|
||||||
|
|
||||||
composing = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* draw input method pre-edit text */
|
|
||||||
static void preeditdraw(XIC xic, XPointer clientdata, XPointer calldata)
|
|
||||||
{
|
|
||||||
XIMPreeditDrawCallbackStruct *pdraw;
|
|
||||||
size_t beg, dellen, inslen, endlen;
|
|
||||||
|
|
||||||
printf("DRAW\n");
|
|
||||||
|
|
||||||
(void)xic;
|
|
||||||
pdraw = (XIMPreeditDrawCallbackStruct *)calldata;
|
|
||||||
if (!pdraw)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* we do not support wide characters */
|
|
||||||
if (pdraw->text && pdraw->text->encoding_is_wchar == True) {
|
|
||||||
fputs("warning: wchar is not supportecd; use utf8", stderr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
beg = runebytes(text, pdraw->chg_first);
|
|
||||||
dellen = runebytes(preview + beg, pdraw->chg_length);
|
|
||||||
inslen = pdraw->text ? runebytes(pdraw->text->string.multi_byte, pdraw->text->length) : 0;
|
|
||||||
endlen = 0;
|
|
||||||
if (beg + dellen < strlen(preview))
|
|
||||||
endlen = strlen(preview + beg + dellen);
|
|
||||||
|
|
||||||
/* we cannot change text past the end of our pre-edit string */
|
|
||||||
|
|
||||||
if (beg + dellen >= BUFSIZ || beg + inslen >= BUFSIZ)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* get space for text to be copied, and copy it */
|
|
||||||
memmove(preview + beg + inslen, preview + beg + dellen, endlen + 1);
|
|
||||||
if (pdraw->text && pdraw->text->length)
|
|
||||||
memcpy(preview + beg, pdraw->text->string.multi_byte, inslen);
|
|
||||||
(preview + beg + inslen + endlen)[0] = '\0';
|
|
||||||
|
|
||||||
/* get caret position */
|
|
||||||
cursor = runebytes(text, pdraw->caret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void init_input_method(XIM xim)
|
|
||||||
{
|
|
||||||
XVaNestedList preedit = NULL;
|
|
||||||
XICCallback start, done, draw, caret;
|
|
||||||
XIMStyle preeditstyle;
|
|
||||||
XIMStyle statusstyle;
|
|
||||||
XIMStyles *imstyles;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* get styles supported by input method */
|
|
||||||
if (XGetIMValues(xim, XNQueryInputStyle, &imstyles, NULL) != NULL)
|
|
||||||
fputs("XGetIMValues: could not obtain input method values", stderr);
|
|
||||||
|
|
||||||
/* check whether input method support on-the-spot pre-editing */
|
|
||||||
preeditstyle = XIMPreeditNothing;
|
|
||||||
statusstyle = XIMStatusNothing;
|
|
||||||
for (i = 0; i < imstyles->count_styles; i++) {
|
|
||||||
if (imstyles->supported_styles[i] & XIMPreeditCallbacks) {
|
|
||||||
preeditstyle = XIMPreeditCallbacks;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create callbacks for the input context */
|
|
||||||
start.client_data = NULL;
|
|
||||||
done.client_data = NULL;
|
|
||||||
draw.client_data = (XPointer)text;
|
|
||||||
caret.client_data = (XPointer)text;
|
|
||||||
start.callback = (XICProc)preeditstart;
|
|
||||||
done.callback = (XICProc)preeditdone;
|
|
||||||
draw.callback = (XICProc)preeditdraw;
|
|
||||||
caret.callback = (XICProc)preeditcaret;
|
|
||||||
|
|
||||||
/* create list of values for input context */
|
|
||||||
preedit = XVaCreateNestedList(0, XNPreeditStartCallback, &start, XNPreeditDoneCallback,
|
|
||||||
&done, XNPreeditDrawCallback, &draw, XNPreeditCaretCallback,
|
|
||||||
&caret, NULL);
|
|
||||||
if (preedit == NULL)
|
|
||||||
fputs("XVaCreateNestedList: could not create nested list", stderr);
|
|
||||||
|
|
||||||
xic = XCreateIC(xim, XNInputStyle, preeditstyle | statusstyle, XNPreeditAttributes, preedit,
|
|
||||||
XNClientWindow, win, XNFocusWindow, win, NULL);
|
|
||||||
XFree(preedit);
|
|
||||||
|
|
||||||
long eventmask;
|
|
||||||
/* get events the input method is interested in */
|
|
||||||
if (XGetICValues(xic, XNFilterEvents, &eventmask, NULL))
|
|
||||||
fputs("XGetICValues: could not obtain input context values", stderr);
|
|
||||||
|
|
||||||
XSelectInput(dpy, win,
|
|
||||||
ExposureMask | KeyPressMask | VisibilityChangeMask | ButtonPressMask |
|
|
||||||
PointerMotionMask | eventmask);
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
static int composing;
|
|
||||||
static char preview[512] = "";
|
|
||||||
|
|
||||||
static size_t nextrunetext(const char *text, size_t position, int inc);
|
|
||||||
static size_t runebytes(const char *text, size_t n);
|
|
||||||
static size_t runechars(const char *text, size_t n);
|
|
||||||
static void preeditcaret(XIC xic, XPointer clientdata, XPointer calldata);
|
|
||||||
static int preeditstart(XIC xic, XPointer clientdata, XPointer calldata);
|
|
||||||
static void preeditdone(XIC xic, XPointer clientdata, XPointer calldata);
|
|
||||||
static void preeditdraw(XIC xic, XPointer clientdata, XPointer calldata);
|
|
||||||
static void init_input_method(XIM xim);
|
|
@ -108,12 +108,6 @@
|
|||||||
*/
|
*/
|
||||||
#define INITIALTEXT_PATCH 0
|
#define INITIALTEXT_PATCH 0
|
||||||
|
|
||||||
/* Adds support for input methods (fctix, ibus, etc.) allowing the user to change the
|
|
||||||
* keyboard layout while dmenu is open.
|
|
||||||
* https://github.com/bakkeby/dmenu-flexipatch/pull/22
|
|
||||||
*/
|
|
||||||
#define INPUTMETHOD_PATCH 0
|
|
||||||
|
|
||||||
/* This patch adds a flag which will cause dmenu to select an item immediately if there
|
/* This patch adds a flag which will cause dmenu to select an item immediately if there
|
||||||
* is only one matching option left.
|
* is only one matching option left.
|
||||||
* https://tools.suckless.org/dmenu/patches/instant/
|
* https://tools.suckless.org/dmenu/patches/instant/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user