aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--main.c4
-rw-r--r--sxiv.h3
-rw-r--r--util.c29
-rw-r--r--window.c47
5 files changed, 75 insertions, 10 deletions
diff --git a/Makefile b/Makefile
index 6c26d3c..304f2a9 100644
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,7 @@ LIB_EXIF_0 =
LIB_EXIF_1 = -lexif
LIB_GIF_0 =
LIB_GIF_1 = -lgif
-LDLIBS = -lImlib2 -lX11 -lXft \
+LDLIBS = -lImlib2 -lX11 -lXft -lfontconfig \
$(LIB_EXIF_$(HAVE_LIBEXIF)) $(LIB_GIF_$(HAVE_GIFLIB))
OBJS = autoreload_$(AUTORELOAD).o commands.o image.o main.o options.o \
diff --git a/main.c b/main.c
index ebe14c9..0bafac5 100644
--- a/main.c
+++ b/main.c
@@ -390,8 +390,8 @@ void update_info(void)
if (ow_info) {
fn = strlen(files[fileidx].name);
if (fn < l->size &&
- win_textwidth(&win.env, files[fileidx].name, fn, true) +
- win_textwidth(&win.env, r->buf, r->p - r->buf, true) < win.w)
+ win_textwidth(&win.env, files[fileidx].name, fn, true, NULL) +
+ win_textwidth(&win.env, r->buf, r->p - r->buf, true, NULL) < win.w)
{
strncpy(l->buf, files[fileidx].name, l->size);
} else {
diff --git a/sxiv.h b/sxiv.h
index 25443ea..2d026b1 100644
--- a/sxiv.h
+++ b/sxiv.h
@@ -362,6 +362,7 @@ int r_opendir(r_dir_t*, const char*, bool);
int r_closedir(r_dir_t*);
char* r_readdir(r_dir_t*);
int r_mkdir(char*);
+void* utf8codepoint(const void * __restrict__ str, long * __restrict__ out_codepoint);
/* window.c */
@@ -442,7 +443,7 @@ void win_toggle_bar(win_t*);
void win_clear(win_t*);
void win_draw(win_t*);
void win_draw_rect(win_t*, int, int, int, int, bool, int, unsigned long);
-int win_textwidth(const win_env_t*, const char*, unsigned int, bool);
+int win_textwidth(const win_env_t*, const char*, unsigned int, bool, XftFont*);
void win_set_title(win_t*, const char*);
void win_set_cursor(win_t*, cursor_t);
void win_cursor_pos(win_t*, int*, int*);
diff --git a/util.c b/util.c
index 6a236c6..973bc80 100644
--- a/util.c
+++ b/util.c
@@ -204,3 +204,32 @@ int r_mkdir(char *path)
}
return 0;
}
+
+/* copied from sheredom's utf8.h (public domain) https://github.com/sheredom/utf8.h */
+
+void* utf8codepoint(const void* __restrict__ str, long* __restrict__ out_codepoint)
+{
+ const char *s = (const char *)str;
+
+ if (0xf0 == (0xf8 & s[0])) {
+ // 4 byte utf8 codepoint
+ *out_codepoint = ((0x07 & s[0]) << 18) | ((0x3f & s[1]) << 12) |
+ ((0x3f & s[2]) << 6) | (0x3f & s[3]);
+ s += 4;
+ } else if (0xe0 == (0xf0 & s[0])) {
+ // 3 byte utf8 codepoint
+ *out_codepoint = ((0x0f & s[0]) << 12) | ((0x3f & s[1]) << 6) | (0x3f & s[2]);
+ s += 3;
+ } else if (0xc0 == (0xe0 & s[0])) {
+ // 2 byte utf8 codepoint
+ *out_codepoint = ((0x1f & s[0]) << 6) | (0x3f & s[1]);
+ s += 2;
+ } else {
+ // 1 byte utf8 codepoint otherwise
+ *out_codepoint = s[0];
+ s += 1;
+ }
+
+ return (void *)s;
+}
+
diff --git a/window.c b/window.c
index 71d439f..46c3c6d 100644
--- a/window.c
+++ b/window.c
@@ -360,9 +360,40 @@ void win_clear(win_t *win)
XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h);
}
+void win_draw_bar_text(win_t *win, XftDraw *d, XftColor *color, XftFont *font, int x, int y, char *text, int maxlen, int maximum_x)
+{
+ size_t len = 0;
+ int xshift = 0, newshift;
+ long codep;
+ char *p, *nextp;
+ FcCharSet* fccharset;
+ XftFont* fallback = NULL;
+
+ for (p = text; *p && (len < maxlen); p = nextp, len++) {
+ nextp = utf8codepoint(p, &codep);
+ if (!XftCharExists(win->env.dpy, font, codep)) {
+ fccharset = FcCharSetCreate();
+ FcCharSetAddChar(fccharset, codep);
+ fallback = XftFontOpen(win->env.dpy, win->env.scr,
+ FC_CHARSET, FcTypeCharSet, fccharset,
+ FC_SCALABLE, FcTypeBool, FcTrue,
+ NULL);
+ FcCharSetDestroy(fccharset);
+ }
+ newshift = win_textwidth(&win->env, p, (int) (nextp-p), false, (fallback ? fallback : font));
+ if (xshift + newshift <= maximum_x)
+ XftDrawStringUtf8(d, color, (fallback ? fallback : font), x + xshift, y, (XftChar8*)p, (int) (nextp-p));
+ xshift += newshift;
+ if (fallback) {
+ XftFontClose(win->env.dpy, fallback);
+ fallback = NULL;
+ }
+ }
+}
+
void win_draw_bar(win_t *win)
{
- int len, olen, x, y, w, tw;
+ int len, olen, x, y, w, tw, maximum_x;
char rest[3];
const char *dots = "...";
win_env_t *e;
@@ -385,7 +416,7 @@ void win_draw_bar(win_t *win)
XSetBackground(e->dpy, gc, win->bar.bgcol.pixel);
if ((len = strlen(r->buf)) > 0) {
- if ((tw = win_textwidth(e, r->buf, len, true)) > w)
+ if ((tw = win_textwidth(e, r->buf, len, true, font)) > w)
return;
x = win->w - tw + H_TEXT_PAD;
w -= tw;
@@ -393,9 +424,10 @@ void win_draw_bar(win_t *win)
}
if ((len = strlen(l->buf)) > 0) {
olen = len;
- while (len > 0 && (tw = win_textwidth(e, l->buf, len, true)) > w)
+ while (len > 0 && (tw = win_textwidth(e, l->buf, len, true, font)) > w)
len--;
if (len > 0) {
+ maximum_x = w;
if (len != olen) {
w = strlen(dots);
if (len <= w)
@@ -404,7 +436,7 @@ void win_draw_bar(win_t *win)
memcpy(l->buf + len - w, dots, w);
}
x = H_TEXT_PAD;
- XftDrawStringUtf8(d, &win->bar.fgcol, font, x, y, (XftChar8*)l->buf, len);
+ win_draw_bar_text(win, d, &win->bar.fgcol, font, x, y, l->buf, len, maximum_x);
if (len != olen)
memcpy(l->buf + len - w, rest, w);
}
@@ -437,11 +469,14 @@ void win_draw_rect(win_t *win, int x, int y, int w, int h, bool fill, int lw,
XDrawRectangle(win->env.dpy, win->buf.pm, gc, x, y, w, h);
}
-int win_textwidth(const win_env_t *e, const char *text, unsigned int len, bool with_padding)
+int win_textwidth(const win_env_t *e, const char *text, unsigned int len, bool with_padding, XftFont *fnt)
{
XGlyphInfo ext;
- XftTextExtentsUtf8(e->dpy, font, (XftChar8*)text, len, &ext);
+ if(!fnt)
+ fnt = font;
+
+ XftTextExtentsUtf8(e->dpy, fnt, (XftChar8*)text, len, &ext);
return ext.xOff + (with_padding ? 2 * H_TEXT_PAD : 0);
}