diff options
| -rw-r--r-- | ui.c | 110 |
1 files changed, 79 insertions, 31 deletions
@@ -6,6 +6,7 @@ #include <X11/Xutil.h> #include <X11/XKBlib.h> #include <X11/Xresource.h> +#include <locale.h> #include <stdio.h> #include "ui.h" @@ -29,7 +30,7 @@ static XSizeHints szhint; static GC gc; static Atom wm_delete_window; -static XFontStruct *ft_opt, *ft_inp; +static XFontSet ft_opt, ft_inp; static inline unsigned long color(const char *name) @@ -49,19 +50,59 @@ color(const char *name) return px; } +static inline XFontSet +ft_load(const char *name) +{ + char **missing_charset_list; + int missing_charset_count; + char *def_str; + return XCreateFontSet(dsp, name, &missing_charset_list, &missing_charset_count, &def_str); +} + +static void +ft_free(XFontSet fs) +{ + XFreeFontSet(dsp, fs); +} + +static inline void +ft_ascent_descent(XFontSet fs, int *asc, int *desc) +{ + XFontStruct **font; + char **name; + int n = XFontsOfFontSet(fs, &font, &name); + int ascent = 0, descent = 0; + for (int i = 0; i < n; i++) { + if (font[i]->ascent > ascent) ascent = font[i]->ascent; + if (font[i]->descent > descent) descent = font[i]->descent; + } + *asc = ascent; + *desc = descent; +} + +static inline int +ft_width(XFontSet f, const char *s, int n) +{ + XRectangle ink, log; + Xutf8TextExtents(f, s, n, &ink, &log); + return log.width; +} + static inline void set_ic_pos(const char *s, int i) { - int w = XTextWidth(ft_inp, s, i); + int w = ft_width(ft_inp, s, i); ic_pos.x = 16 + w; ic_pos.y = 24; - XSetICValues(ic, /* XNFocusWindow, win, */ XNPreeditAttributes, ic_pos_list, NULL); - XSetICFocus(ic); + XSetICValues(ic, XNPreeditAttributes, ic_pos_list, NULL); } void ui_init(int argc, char **argv, UiOpts opt) { + if (!setlocale(LC_ALL, "")) + err(1, "failed to set locale"); + dsp = XOpenDisplay(NULL); scr = DefaultScreen(dsp); db = XrmGetDatabase(dsp); @@ -95,11 +136,11 @@ ui_init(int argc, char **argv, UiOpts opt) .background_pixel = bg, .border_pixel = fg, .bit_gravity = NorthWestGravity, - .event_mask = KeyPressMask | KeyReleaseMask | ExposureMask + .event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask + | ExposureMask | VisibilityChangeMask | StructureNotifyMask + | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask, }); - /* TODO: replace with modern XSetWMProperties */ - /* does setting the urgency hint auto-focus in ctwm? */ XSetWMProperties(dsp, win, NULL, NULL, argv, argc, &szhint, &(XWMHints) { .flags = InputHint | XUrgencyHint, .input = 1 }, @@ -115,15 +156,15 @@ ui_init(int argc, char **argv, UiOpts opt) XSetWMProtocols(dsp, win, &wm_delete_window, 1); /* TODO: error checking */ - ft_opt = XLoadQueryFont(dsp, "-*-new century schoolbook-medium-r-*-*-24-*-*-*-*-*-*-*"); - ft_inp = XLoadQueryFont(dsp, "-*-new century schoolbook-medium-i-*-*-24-*-*-*-*-*-*-*"); + ft_opt = ft_load("-*-new century schoolbook-medium-r-*-*-24-*-*-*-*-*-*-*"); + ft_inp = ft_load("-*-new century schoolbook-medium-i-*-*-24-*-*-*-*-*-*-*"); - if (!ft_opt) ft_opt = XLoadQueryFont(dsp, "fixed"); - if (!ft_inp) ft_inp = XLoadQueryFont(dsp, "fixed"); + if (!ft_opt) ft_opt = ft_load("fixed"); + if (!ft_inp) ft_inp = ft_load("fixed"); int w = 0; for (int i = 0; i < opt.n; i++) { - int ow = XTextWidth(ft_opt, opt.v[i].s, opt.v[i].n); + int ow = ft_width(ft_opt, opt.v[i].s, opt.v[i].n); if (ow > w) w = ow; } @@ -156,8 +197,8 @@ ui_fini(void) XFree(ic_pos_list); XDestroyIC(ic); XCloseIM(im); - XFreeFont(dsp, ft_opt); - XFreeFont(dsp, ft_inp); + XFreeFontSet(dsp, ft_opt); + XFreeFontSet(dsp, ft_inp); XFreeGC(dsp, gc); XDestroyWindow(dsp, win); XCloseDisplay(dsp); @@ -209,6 +250,7 @@ loop: case KeyPress: e->type = UI_KEY_DOWN; e->key.strn = Xutf8LookupString(ic, &ev.xkey, e->key.str, sizeof(e->key.str), &sym, &status); + printf("%lu %.*s\n", sym, e->key.strn, e->key.str); e->key.key = xksym_to_uik(sym); e->key.mod = xkstate_to_uim(ev.xkey.state); return 1; @@ -226,6 +268,12 @@ loop: return 1; } break; + case FocusIn: + XSetICFocus(ic); + break; + case FocusOut: + XUnsetICFocus(ic); + break; } fprintf(stderr, "[Unknown event %d]\n", ev.type); goto loop; @@ -242,30 +290,31 @@ ui_draw(Str input, int inpi, int seli, UiOpts o) /* draw input */ - int w = XTextWidth(ft_inp, input.s, inpi); + int w = ft_width(ft_inp, input.s, inpi); int y = 32; + int ft_opt_asc, ft_opt_dsc, ft_inp_asc, ft_inp_dsc; + ft_ascent_descent(ft_opt, &ft_opt_asc, &ft_opt_dsc); + ft_ascent_descent(ft_inp, &ft_inp_asc, &ft_inp_dsc); + XSetForeground(dsp, gc, inpbg); XFillRectangle(dsp, win, gc, - 12, y - ft_opt->ascent, - w + 8, ft_opt->descent + ft_opt->ascent); + 12, y - ft_opt_asc, + w + 8, ft_opt_asc + ft_opt_dsc); XSetForeground(dsp, gc, inpfg); - XSetFont(dsp, gc, ft_inp->fid); XDrawLine(dsp, win, gc, - 16 + w, y - ft_inp->ascent, - 16 + w, y + ft_inp->descent); + 16 + w, y - ft_inp_asc, + 16 + w, y + ft_inp_dsc); - XDrawString(dsp, win, gc, 16, y, input.s, input.n); + Xutf8DrawString(dsp, win, ft_inp, gc, 16, y, input.s, input.n); XSetForeground(dsp, gc, fg); y += 24; /* draw options */ - XSetFont(dsp, gc, ft_opt->fid); - int lines = (attr.height - 32) / 24; int tline = lines / 2; int bline = lines - tline; @@ -279,19 +328,18 @@ ui_draw(Str input, int inpi, int seli, UiOpts o) for (int i = top; i < bot; i++) { if (i == seli) { - int w = XTextWidth(ft_opt, o.v[i].s, o.v[i].n); + int w = ft_width(ft_opt, o.v[i].s, o.v[i].n); XSetForeground(dsp, gc, selbg); XFillRectangle(dsp, win, gc, - 12, y - ft_opt->ascent, - w + 8, ft_opt->descent + ft_opt->ascent); + 12, y - ft_opt_asc, + w + 8, ft_opt_asc + ft_opt_dsc); XSetForeground(dsp, gc, selfg); - XDrawString(dsp, win, gc, 16, y, - o.v[i].s, o.v[i].n); + Xutf8DrawString(dsp, win, ft_opt, gc, + 16, y, o.v[i].s, o.v[i].n); XSetForeground(dsp, gc, fg); } else { - XDrawString(dsp, win, gc, - 16, y, - o.v[i].s, o.v[i].n); + Xutf8DrawString(dsp, win, ft_opt, gc, + 16, y, o.v[i].s, o.v[i].n); } y += 24; } |
