summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWormHeamer2026-01-30 18:29:01 -0500
committerWormHeamer2026-01-30 18:29:01 -0500
commitdcf901d1d713943c033bac108f7cace5d7c1c0c1 (patch)
tree64d5da12c7594ede38cd0e3a0d011640552d9632
parent42ebdb5b5e30ee7fb4d8e0fadc4b1f8338637839 (diff)
use XFontSet instead of just XFontStruct
-rw-r--r--ui.c110
1 files changed, 79 insertions, 31 deletions
diff --git a/ui.c b/ui.c
index 35b6451..59df0f4 100644
--- a/ui.c
+++ b/ui.c
@@ -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;
}