diff options
| author | trainytrain <trainytrain@rape.lol> | 2021-05-09 01:53:29 -0700 |
|---|---|---|
| committer | trainytrain <trainytrain@rape.lol> | 2021-05-09 01:53:29 -0700 |
| commit | 64ad31237da6d14f0193adb7f1210255d5d647dd (patch) | |
| tree | 3a6f8bcacd6a0211fd3dd0b8b7ae42df0539883d /x.c | |
| parent | 7e6e779130327e065fcf587afa80f13150d0de31 (diff) | |
init
Diffstat (limited to 'x.c')
| -rw-r--r-- | x.c | 417 |
1 files changed, 181 insertions, 236 deletions
@@ -16,7 +16,7 @@ #include <X11/XKBlib.h> #include <X11/Xresource.h> -char *argv0; +static char *argv0; #include "arg.h" #include "st.h" #include "win.h" @@ -31,11 +31,9 @@ typedef struct { } Shortcut; typedef struct { - uint mod; - uint button; - void (*func)(const Arg *); - const Arg arg; - uint release; + uint b; + uint mask; + char *s; } MouseShortcut; typedef struct { @@ -74,7 +72,6 @@ static void changealpha(const Arg *); static void zoom(const Arg *); static void zoomabs(const Arg *); static void zoomreset(const Arg *); -static void ttysend(const Arg *); /* config.h for applying patches and the configuration. */ #include "config.h" @@ -97,8 +94,10 @@ typedef XftGlyphFontSpec GlyphFontSpec; typedef struct { int tw, th; /* tty width and height */ int w, h; /* window width and height */ + int hborderpx, vborderpx; int ch; /* char height */ int cw; /* char width */ + int cyo; /* char y offset */ int mode; /* window state/mode flags */ int cursor; /* cursor style */ } TermWindow; @@ -109,13 +108,9 @@ typedef struct { Window win; Drawable buf; GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ - Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; - struct { - XIM xim; - XIC xic; - XPoint spot; - XVaNestedList spotlist; - } ime; + Atom xembed, wmdeletewin, netwmname, netwmpid; + XIM xim; + XIC xic; Draw draw; Visual *vis; XSetWindowAttributes attrs; @@ -159,14 +154,13 @@ typedef struct { static inline ushort sixd_to_16bit(int); static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int); -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int); +static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int, int); static void xdrawglyph(Glyph, int, int); static void xclear(int, int, int, int); static int xgeommasktogravity(int); -static int ximopen(Display *); +static void ximopen(Display *); static void ximinstantiate(Display *, XPointer, XPointer); static void ximdestroy(XIM, XPointer, XPointer); -static int xicdestroy(XIC, XPointer, XPointer); static void xinit(int, int); static void cresize(int, int); static void xresize(int, int); @@ -190,8 +184,6 @@ static void kpress(XEvent *); static void cmessage(XEvent *); static void resize(XEvent *); static void focus(XEvent *); -static uint buttonmask(uint); -static int mouseaction(XEvent *, uint); static void brelease(XEvent *); static void bpress(XEvent *); static void bmotion(XEvent *); @@ -357,16 +349,10 @@ zoomreset(const Arg *arg) } } -void -ttysend(const Arg *arg) -{ - ttywrite(arg->s, strlen(arg->s), 1); -} - int evcol(XEvent *e) { - int x = e->xbutton.x - borderpx; + int x = e->xbutton.x - win.hborderpx; LIMIT(x, 0, win.tw - 1); return x / win.cw; } @@ -374,7 +360,7 @@ evcol(XEvent *e) int evrow(XEvent *e) { - int y = e->xbutton.y - borderpx; + int y = e->xbutton.y - win.vborderpx; LIMIT(y, 0, win.th - 1); return y / win.ch; } @@ -383,7 +369,7 @@ void mousesel(XEvent *e, int done) { int type, seltype = SEL_REGULAR; - uint state = e->xbutton.state & ~(Button1Mask | forcemousemod); + uint state = e->xbutton.state & ~(Button1Mask | forceselmod); for (type = 1; type < LEN(selmasks); ++type) { if (match(selmasks[type], state)) { @@ -459,51 +445,36 @@ mousereport(XEvent *e) ttywrite(buf, len, 0); } -uint -buttonmask(uint button) -{ - return button == Button1 ? Button1Mask - : button == Button2 ? Button2Mask - : button == Button3 ? Button3Mask - : button == Button4 ? Button4Mask - : button == Button5 ? Button5Mask - : 0; -} - -int -mouseaction(XEvent *e, uint release) -{ - MouseShortcut *ms; - - /* ignore Button<N>mask for Button<N> - it's set on release */ - uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); - - for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { - if (ms->release == release && - ms->button == e->xbutton.button && - (match(ms->mod, state) || /* exact or forced */ - match(ms->mod, state & ~forcemousemod))) { - ms->func(&(ms->arg)); - return 1; - } - } - - return 0; -} - void bpress(XEvent *e) { struct timespec now; + MouseShortcut *ms; + MouseKey *mk; int snap; - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { mousereport(e); return; } - if (mouseaction(e, 0)) - return; + if (tisaltscr()) { + for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { + if (e->xbutton.button == ms->b + && match(ms->mask, e->xbutton.state)) { + ttywrite(ms->s, strlen(ms->s), 1); + return; + } + } + } + + for (mk = mkeys; mk < mkeys + LEN(mkeys); mk++) { + if (e->xbutton.button == mk->b + && match(mk->mask, e->xbutton.state)) { + mk->func(&mk->arg); + return; + } + } if (e->xbutton.button == Button1) { /* @@ -719,21 +690,21 @@ xsetsel(char *str) void brelease(XEvent *e) { - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { mousereport(e); return; } - if (mouseaction(e, 1)) - return; - if (e->xbutton.button == Button1) + if (e->xbutton.button == Button2) + selpaste(NULL); + else if (e->xbutton.button == Button1) mousesel(e, 1); } void bmotion(XEvent *e) { - if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { + if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) { mousereport(e); return; } @@ -756,6 +727,9 @@ cresize(int width, int height) col = MAX(1, col); row = MAX(1, row); + win.hborderpx = (win.w - col * win.cw) / 2; + win.vborderpx = (win.h - row * win.ch) / 2; + tresize(col, row); xresize(col, row); ttyresize(win.tw, win.th); @@ -834,6 +808,12 @@ xloadcols(void) if (opt_alpha) alpha = strtof(opt_alpha, NULL); dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); + dc.col[defaultbg].color.red = + ((unsigned short)(dc.col[defaultbg].color.red * alpha)) & 0xff00; + dc.col[defaultbg].color.green = + ((unsigned short)(dc.col[defaultbg].color.green * alpha)) & 0xff00; + dc.col[defaultbg].color.blue = + ((unsigned short)(dc.col[defaultbg].color.blue * alpha)) & 0xff00; dc.col[defaultbg].pixel &= 0x00FFFFFF; dc.col[defaultbg].pixel |= (unsigned char)(0xff * alpha) << 24; loaded = 1; @@ -852,6 +832,8 @@ xsetcolorname(int x, const char *name) XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]); dc.col[x] = ncolor; + if (x == defaultbg) + dc.col[defaultbg].color.alpha = (unsigned short)(0xffff * alpha); return 0; } @@ -868,6 +850,13 @@ xclear(int x1, int y1, int x2, int y2) } void +xclearwin(void) +{ + xclear(0, 0, win.w, win.h); +} + + +void xhints(void) { XClassHint class = {opt_name ? opt_name : "st", @@ -880,8 +869,8 @@ xhints(void) sizeh->flags = PSize | PResizeInc | PBaseSize | PMinSize; sizeh->height = win.h; sizeh->width = win.w; - sizeh->height_inc = win.ch; - sizeh->width_inc = win.cw; + sizeh->height_inc = 1; + sizeh->width_inc = 1; sizeh->base_height = 2 * borderpx; sizeh->base_width = 2 * borderpx; sizeh->min_height = win.ch + 2 * borderpx; @@ -1042,6 +1031,7 @@ xloadfonts(char *fontstr, double fontsize) /* Setting character width and height. */ win.cw = ceilf(dc.font.width * cwscale); win.ch = ceilf(dc.font.height * chscale); + win.cyo = ceilf(dc.font.height * (chscale - 1) / 2); FcPatternDel(pattern, FC_SLANT); FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); @@ -1181,58 +1171,41 @@ xunloadfonts(void) xunloadfont(&dc.ibfont); } -int +void ximopen(Display *dpy) { - XIMCallback imdestroy = { .client_data = NULL, .callback = ximdestroy }; - XICCallback icdestroy = { .client_data = NULL, .callback = xicdestroy }; - - xw.ime.xim = XOpenIM(xw.dpy, NULL, NULL, NULL); - if (xw.ime.xim == NULL) - return 0; - - if (XSetIMValues(xw.ime.xim, XNDestroyCallback, &imdestroy, NULL)) - fprintf(stderr, "XSetIMValues: " - "Could not set XNDestroyCallback.\n"); + XIMCallback destroy = { .client_data = NULL, .callback = ximdestroy }; - xw.ime.spotlist = XVaCreateNestedList(0, XNSpotLocation, &xw.ime.spot, - NULL); - - if (xw.ime.xic == NULL) { - xw.ime.xic = XCreateIC(xw.ime.xim, XNInputStyle, - XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, xw.win, - XNDestroyCallback, &icdestroy, - NULL); + 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 (xw.ime.xic == NULL) - fprintf(stderr, "XCreateIC: Could not create input context.\n"); - - return 1; + 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) { - if (ximopen(dpy)) - XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); + ximopen(dpy); + XUnregisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, + ximinstantiate, NULL); } void ximdestroy(XIM xim, XPointer client, XPointer call) { - xw.ime.xim = NULL; + xw.xim = NULL; XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - XFree(xw.ime.spotlist); -} - -int -xicdestroy(XIC xim, XPointer client, XPointer call) -{ - xw.ime.xic = NULL; - return 1; + ximinstantiate, NULL); } void @@ -1274,8 +1247,8 @@ xinit(int cols, int rows) xloadcols(); /* adjust fixed window geometry */ - win.w = 2 * borderpx + cols * win.cw; - win.h = 2 * borderpx + rows * win.ch; + win.w = 2 * win.hborderpx + cols * win.cw; + win.h = 2 * win.vborderpx + rows * win.ch; if (xw.gm & XNegative) xw.l += DisplayWidth(xw.dpy, xw.scr) - win.w - 2; if (xw.gm & YNegative) @@ -1309,10 +1282,7 @@ xinit(int cols, int rows) xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap); /* input methods */ - if (!ximopen(xw.dpy)) { - XRegisterIMInstantiateCallback(xw.dpy, NULL, NULL, NULL, - ximinstantiate, NULL); - } + ximopen(xw.dpy); /* white cursor, black outline */ cursor = XCreateFontCursor(xw.dpy, mouseshape); @@ -1335,7 +1305,6 @@ xinit(int cols, int rows) xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False); xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); - xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); @@ -1344,8 +1313,8 @@ xinit(int cols, int rows) win.mode = MODE_NUMLOCK; resettitle(); - xhints(); XMapWindow(xw.dpy, xw.win); + xhints(); XSync(xw.dpy, False); clock_gettime(CLOCK_MONOTONIC, &xsel.tclick1); @@ -1362,7 +1331,7 @@ xinit(int cols, int rows) int xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) { - float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; + float winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, xp, yp; ushort mode, prevmode = USHRT_MAX; Font *font = &dc.font; int frcflags = FRC_NORMAL; @@ -1375,7 +1344,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x FcCharSet *fccharset; int i, f, numspecs = 0; - for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { + for (i = 0, xp = winx, yp = winy + font->ascent + win.cyo; i < len; ++i) { /* Fetch rune and mode for current glyph. */ rune = glyphs[i].u; mode = glyphs[i].mode; @@ -1400,7 +1369,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x font = &dc.bfont; frcflags = FRC_BOLD; } - yp = winy + font->ascent; + yp = winy + font->ascent + win.cyo; } if (mode & ATTR_BOXDRAW) { @@ -1500,14 +1469,13 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x } void -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y) +xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y, int dmode) { int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1); - int winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, + int winx = win.hborderpx + x * win.cw, winy = win.vborderpx + y * win.ch, width = charlen * win.cw; Color *fg, *bg, *temp, revfg, revbg, truefg, truebg; XRenderColor colfg, colbg; - XRectangle r; /* Fallback on color display for attributes not supported by the font */ if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { @@ -1540,10 +1508,6 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i bg = &dc.col[base.bg]; } - /* Change basic system colors [0-7] to bright system colors [8-15] */ - if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7)) - fg = &dc.col[base.fg + 8]; - if (IS_SET(MODE_REVERSE)) { if (fg == &dc.col[defaultfg]) { fg = &dc.col[defaultbg]; @@ -1591,51 +1555,45 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i if (base.mode & ATTR_INVISIBLE) fg = bg; - /* Intelligent cleaning up of the borders. */ - if (x == 0) { - xclear(0, (y == 0)? 0 : winy, borderpx, - winy + win.ch + - ((winy + win.ch >= borderpx + win.th)? win.h : 0)); - } - if (winx + width >= borderpx + win.tw) { - xclear(winx + width, (y == 0)? 0 : winy, win.w, - ((winy + win.ch >= borderpx + win.th)? win.h : (winy + win.ch))); - } - if (y == 0) - xclear(winx, 0, winx + width, borderpx); - if (winy + win.ch >= borderpx + win.th) - xclear(winx, winy + win.ch, winx + width, win.h); - - /* Clean up the region we want to draw to. */ - XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); - - /* Set the clip region because Xft is sometimes dirty. */ - r.x = 0; - r.y = 0; - r.height = win.ch; - r.width = width; - XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1); - - if (base.mode & ATTR_BOXDRAW) { - drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len); - } else { - /* Render the glyphs. */ - XftDrawGlyphFontSpec(xw.draw, fg, specs, len); - } + if (dmode & DRAW_BG) { + /* Intelligent cleaning up of the borders. */ + if (x == 0) { + xclear(0, (y == 0)? 0 : winy, win.vborderpx, + winy + win.ch + + ((winy + win.ch >= win.vborderpx + win.th)? win.h : 0)); + } + if (winx + width >= win.hborderpx + win.tw) { + xclear(winx + width, (y == 0)? 0 : winy, win.w, + ((winy + win.ch >= win.vborderpx + win.th)? win.h : (winy + win.ch))); + } + if (y == 0) + xclear(winx, 0, winx + width, win.hborderpx); + if (winy + win.ch >= win.vborderpx + win.th) + xclear(winx, winy + win.ch, winx + width, win.h); - /* Render underline and strikethrough. */ - if (base.mode & ATTR_UNDERLINE) { - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1, - width, 1); + /* Fill the background */ + XftDrawRect(xw.draw, bg, winx, winy, width, win.ch); } - if (base.mode & ATTR_STRUCK) { - XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3, - width, 1); - } + if (dmode & DRAW_FG) { + if (base.mode & ATTR_BOXDRAW) { + drawboxes(winx, winy, width / len, win.ch, fg, bg, specs, len); + } else { + /* Render the glyphs. */ + XftDrawGlyphFontSpec(xw.draw, fg, specs, len); + } + + /* Render underline and strikethrough. */ + if (base.mode & ATTR_UNDERLINE) { + XftDrawRect(xw.draw, fg, winx, winy + win.cyo + dc.font.ascent + 1, + width, 1); + } - /* Reset clip to none. */ - XftDrawSetClip(xw.draw, 0); + if (base.mode & ATTR_STRUCK) { + XftDrawRect(xw.draw, fg, winx, winy + win.cyo + 2 * dc.font.ascent / 3, + width, 1); + } + } } void @@ -1645,7 +1603,7 @@ xdrawglyph(Glyph g, int x, int y) XftGlyphFontSpec spec; numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y); - xdrawglyphfontspecs(&spec, g, numspecs, x, y); + xdrawglyphfontspecs(&spec, g, numspecs, x, y, DRAW_BG | DRAW_FG); } void @@ -1693,9 +1651,8 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int le /* draw the new one */ if (IS_SET(MODE_FOCUSED)) { switch (win.cursor) { - case 7: /* st extension */ - g.u = 0x2603; /* snowman (U+2603) */ - /* FALLTHROUGH */ + case 7: /* st extension: snowman (U+2603) */ + g.u = 0x2603; case 0: /* Blinking Block */ case 1: /* Blinking Block (Default) */ case 2: /* Steady Block */ @@ -1704,35 +1661,35 @@ xdrawcursor(int cx, int cy, Glyph g, int ox, int oy, Glyph og, Line line, int le case 3: /* Blinking Underline */ case 4: /* Steady Underline */ XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + (cy + 1) * win.ch - \ + win.hborderpx + cx * win.cw, + win.vborderpx + (cy + 1) * win.ch - \ cursorthickness, win.cw, cursorthickness); break; case 5: /* Blinking bar */ case 6: /* Steady bar */ XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + cy * win.ch, + win.hborderpx + cx * win.cw, + win.vborderpx + cy * win.ch, cursorthickness, win.ch); break; } } else { XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + cy * win.ch, + win.hborderpx + cx * win.cw, + win.vborderpx + cy * win.ch, win.cw - 1, 1); XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + cy * win.ch, + win.hborderpx + cx * win.cw, + win.vborderpx + cy * win.ch, 1, win.ch - 1); XftDrawRect(xw.draw, &drawcol, - borderpx + (cx + 1) * win.cw - 1, - borderpx + cy * win.ch, + win.hborderpx + (cx + 1) * win.cw - 1, + win.vborderpx + cy * win.ch, 1, win.ch - 1); XftDrawRect(xw.draw, &drawcol, - borderpx + cx * win.cw, - borderpx + (cy + 1) * win.ch - 1, + win.hborderpx + cx * win.cw, + win.vborderpx + (cy + 1) * win.ch - 1, win.cw, 1); } } @@ -1747,19 +1704,6 @@ xsetenv(void) } void -xseticontitle(char *p) -{ - XTextProperty prop; - DEFAULT(p, opt_title); - - Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle, - &prop); - XSetWMIconName(xw.dpy, xw.win, &prop); - XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmiconname); - XFree(prop.value); -} - -void xsettitle(char *p) { XTextProperty prop; @@ -1781,32 +1725,39 @@ xstartdraw(void) void xdrawline(Line line, int x1, int y1, int x2) { - int i, x, ox, numspecs; + int i, x, ox, numspecs, numspecs_cached; Glyph base, new; - XftGlyphFontSpec *specs = xw.specbuf; - - numspecs = xmakeglyphfontspecs(specs, &line[x1], x2 - x1, x1, y1); - i = ox = 0; - for (x = x1; x < x2 && i < numspecs; x++) { - new = line[x]; - if (new.mode == ATTR_WDUMMY) - continue; - if (selected(x, y1)) - new.mode ^= ATTR_REVERSE; - if (i > 0 && ATTRCMP(base, new)) { - xdrawglyphfontspecs(specs, base, i, ox, y1); - specs += i; - numspecs -= i; - i = 0; - } - if (i == 0) { - ox = x; - base = new; + XftGlyphFontSpec *specs; + + numspecs_cached = xmakeglyphfontspecs(xw.specbuf, &line[x1], x2 - x1, x1, y1); + + /* Draw line in 2 passes: background and foreground. This way wide glyphs + won't get truncated (#223) */ + for (int dmode = DRAW_BG; dmode <= DRAW_FG; dmode <<= 1) { + specs = xw.specbuf; + numspecs = numspecs_cached; + i = ox = 0; + for (x = x1; x < x2 && i < numspecs; x++) { + new = line[x]; + if (new.mode == ATTR_WDUMMY) + continue; + if (selected(x, y1)) + new.mode ^= ATTR_REVERSE; + if (i > 0 && ATTRCMP(base, new)) { + xdrawglyphfontspecs(specs, base, i, ox, y1, dmode); + specs += i; + numspecs -= i; + i = 0; + } + if (i == 0) { + ox = x; + base = new; + } + i++; } - i++; + if (i > 0) + xdrawglyphfontspecs(specs, base, i, ox, y1, dmode); } - if (i > 0) - xdrawglyphfontspecs(specs, base, i, ox, y1); } void @@ -1822,13 +1773,11 @@ xfinishdraw(void) void xximspot(int x, int y) { - if (xw.ime.xic == NULL) - return; + XPoint spot = { borderpx + x * win.cw, borderpx + (y + 1) * win.ch }; + XVaNestedList attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); - xw.ime.spot.x = borderpx + x * win.cw; - xw.ime.spot.y = borderpx + (y + 1) * win.ch; - - XSetICValues(xw.ime.xic, XNPreeditAttributes, xw.ime.spotlist, NULL); + XSetICValues(xw.xic, XNPreeditAttributes, attr, NULL); + XFree(attr); } void @@ -1870,7 +1819,8 @@ xsetmode(int set, unsigned int flags) int xsetcursor(int cursor) { - if (!BETWEEN(cursor, 0, 7)) /* 7: st extension */ + DEFAULT(cursor, 1); + if (!BETWEEN(cursor, 0, 6)) return 1; win.cursor = cursor; return 0; @@ -1904,15 +1854,13 @@ focus(XEvent *ev) return; if (ev->type == FocusIn) { - if (xw.ime.xic) - XSetICFocus(xw.ime.xic); + XSetICFocus(xw.xic); win.mode |= MODE_FOCUSED; xseturgency(0); if (IS_SET(MODE_FOCUS)) ttywrite("\033[I", 3, 0); } else { - if (xw.ime.xic) - XUnsetICFocus(xw.ime.xic); + XUnsetICFocus(xw.xic); win.mode &= ~MODE_FOCUSED; if (IS_SET(MODE_FOCUS)) ttywrite("\033[O", 3, 0); @@ -1967,7 +1915,7 @@ kpress(XEvent *ev) { XKeyEvent *e = &ev->xkey; KeySym ksym; - char buf[64], *customkey; + char buf[32], *customkey; int len; Rune c; Status status; @@ -1976,10 +1924,7 @@ kpress(XEvent *ev) if (IS_SET(MODE_KBDLOCK)) return; - if (xw.ime.xic) - len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status); - else - len = XLookupString(e, buf, sizeof buf, &ksym, NULL); + len = XmbLookupString(xw.xic, e, buf, sizeof buf, &ksym, &status); /* 1. shortcuts */ for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) { if (ksym == bp->keysym && match(bp->mod, e->state)) { @@ -2107,7 +2052,7 @@ run(void) * triggers drawing, we first wait a bit to ensure we got * everything, and if nothing new arrives - we draw. * We start with trying to wait minlatency ms. If more content - * arrives sooner, we retry with shorter and shorter periods, + * arrives sooner, we retry with shorter and shorter preiods, * and eventually draw even without idle after maxlatency ms. * Typically this results in low latency while interacting, * maximum latency intervals during `cat huge.txt`, and perfect @@ -2215,7 +2160,7 @@ main(int argc, char *argv[]) { xw.l = xw.t = 0; xw.isfixed = False; - xsetcursor(cursorshape); + win.cursor = cursorshape; ARGBEGIN { case 'a': |
