# st

Unnamed repository; edit this file 'description' to name the repository.

| Log | Files | Refs | README | LICENSE

    commit e85b6b64660214121164ea97fb098eaa4935f7db
    parent 75f92eb3489275bfcad901e5ca424134eda6e2f4
    Author: Ivan Tham <pickfire@riseup.net>
    Date:   Tue, 12 Feb 2019 18:41:41 +0100

    better Input Method Editor (IME) support

    Features:

    - Allow input methods swap with hotkey (E.g. left ctrl + left shift).
    - Over-the-spot pre-editing style, pre-edit data placed over insertion point.
    - Restart IME without segmentation fault.

    TODO:

    - Automatically pickup IME if st started before IME

    Diffstat:
    Mst.c | 1+
    Mwin.h | 1+
    Mx.c | 69++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------

    3 files changed, 54 insertions(+), 17 deletions(-)
    diff --git a/st.c b/st.c
    @@ -2594,6 +2594,7 @@ draw(void)
     			term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
     	term.ocx = cx, term.ocy = term.c.y;
     	xfinishdraw();
    +	xximspot(term.ocx, term.ocy);
     }

     void
    diff --git a/win.h b/win.h
    @@ -36,3 +36,4 @@ void xsetmode(int, unsigned int);
     void xsetpointermotion(int);
     void xsetsel(char *);
     int xstartdraw(void);
    +void xximspot(int, int);
    diff --git a/x.c b/x.c
    @@ -139,6 +139,9 @@ static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
     static void xdrawglyph(Glyph, int, int);
     static void xclear(int, int, int, int);
     static int xgeommasktogravity(int);
    +static void ximopen(Display *);
    +static void ximinstantiate(Display *, XPointer, XPointer);
    +static void ximdestroy(XIM, XPointer, XPointer);
     static void xinit(int, int);
     static void cresize(int, int);
     static void xresize(int, int);
    @@ -997,6 +1000,43 @@ xunloadfonts(void)
     }

     void
    +ximopen(Display *dpy)
    +{
    +	XIMCallback destroy = { .client_data = NULL, .callback = ximdestroy };
    +
    +	if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) {
    +		XSetLocaleModifiers("@im=local");
    +		if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) {
    +			XSetLocaleModifiers("@im=");
    +			if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL)
    +				die("XOpenIM failed. Could not open input device.\n");
    +		}
    +	}
    +	if (XSetIMValues(xw.xim, XNDestroyCallback, &destroy, NULL) != NULL)
    +		die("XSetIMValues failed. Could not set input method value.\n");
    +	xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
    +				XNClientWindow, xw.win, XNFocusWindow, xw.win, NULL);
    +	if (xw.xic == NULL)
    +		die("XCreateIC failed. Could not obtain input method.\n");
    +}
    +
    +void
    +ximinstantiate(Display *dpy, XPointer client, XPointer call)
    +{
    +	ximopen(dpy);
    +	XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
    +					ximinstantiate, NULL);
    +}
    +
    +void
    +ximdestroy(XIM xim, XPointer client, XPointer call)
    +{
    +	xw.xim = NULL;
    +	XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL,
    +					ximinstantiate, NULL);
    +}
    +
    +void
     xinit(int cols, int rows)
     {
     	XGCValues gcvalues;
    @@ -1033,7 +1073,7 @@ xinit(int cols, int rows)
     	xw.attrs.background_pixel = dc.col[defaultbg].pixel;
     	xw.attrs.border_pixel = dc.col[defaultbg].pixel;
     	xw.attrs.bit_gravity = NorthWestGravity;
    -	xw.attrs.event_mask = FocusChangeMask | KeyPressMask
    +	xw.attrs.event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask
     		| ExposureMask | VisibilityChangeMask | StructureNotifyMask
     		| ButtonMotionMask | ButtonPressMask | ButtonReleaseMask;
     	xw.attrs.colormap = xw.cmap;
    @@ -1061,22 +1101,7 @@ xinit(int cols, int rows)
     	xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap);

     	/* input methods */
    -	if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) {
    -		XSetLocaleModifiers("@im=local");
    -		if ((xw.xim =  XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) {
    -			XSetLocaleModifiers("@im=");
    -			if ((xw.xim = XOpenIM(xw.dpy,
    -					NULL, NULL, NULL)) == NULL) {
    -				die("XOpenIM failed. Could not open input"
    -					" device.\n");
    -			}
    -		}
    -	}
    -	xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing
    -					   | XIMStatusNothing, XNClientWindow, xw.win,
    -					   XNFocusWindow, xw.win, NULL);
    -	if (xw.xic == NULL)
    -		die("XCreateIC failed. Could not obtain input method.\n");
    +	ximopen(xw.dpy);

     	/* white cursor, black outline */
     	cursor = XCreateFontCursor(xw.dpy, mouseshape);
    @@ -1555,6 +1580,16 @@ xfinishdraw(void)
     }

     void
    +xximspot(int x, int y)
    +{
    +	XPoint spot = { borderpx + x * win.cw, borderpx + (y + 1) * win.ch };
    +	XVaNestedList attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);
    +
    +	XSetICValues(xw.xic, XNPreeditAttributes, attr, NULL);
    +	XFree(attr);
    +}
    +
    +void
     expose(XEvent *ev)
     {
     	redraw();