sob

Simple output bar
git clone https://git.sinitax.com/codemadness/sob
Log | Files | Refs | README | LICENSE | Upstream | sfeed.txt

commit 953439a2efe7bf8be200be0d384377d1d96f4d48
parent 4f2bc0ed04d5afc5dfd11651fe84747eb3ec55bb
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Fri, 10 Oct 2014 18:47:55 +0000

add support for characters that are bigger than 1 column

Diffstat:
MREADME | 4+++-
Msob.c | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
2 files changed, 67 insertions(+), 15 deletions(-)

diff --git a/README b/README @@ -10,6 +10,8 @@ Dependencies Features -------- - Small (in size and memory), not much dependencies. +- UTF-8 input and output support. + - Support for characters that are bigger than 1 column. - Custom prompt (including color support). - Easy to write custom completion scripts or special actions. - Custom action on SIGWINCH (window resize). @@ -23,7 +25,7 @@ Features Known issues ------------ -line yank doesn't work with xclip, but does work with xsel. +- Line yank doesn't work with xclip, but does work with xsel. Author diff --git a/sob.c b/sob.c @@ -12,6 +12,9 @@ #include <unistd.h> #include <termios.h> +#define __XOPEN_SOURCE +#include <wchar.h> + #include "arg.h" char *argv0; @@ -27,6 +30,8 @@ struct line { size_t utflen; /* length in characters */ size_t bytepos; /* index position (in bytes) */ size_t utfpos; /* pos in characters */ + size_t colpos; /* cursor position (in columns) */ + size_t collen; /* total length (in columns) */ }; static void line_clear(void); @@ -69,10 +74,11 @@ static void setup(void); static void sighandler(int); static void usage(void); +static size_t colw(const char *, size_t); static int nonspace(int c); static size_t utf8len(const char *); -static size_t utfprevn(const char *, size_t , size_t); -static size_t utfnextn(const char *, size_t , size_t); +static size_t utfprevn(const char *, size_t, size_t); +static size_t utfnextn(const char *, size_t, size_t); static void utfuntilchar(size_t *, size_t *, int (*)(int), int); static struct termios ttystate, ttysave; @@ -92,6 +98,25 @@ nonspace(int c) } static size_t +colw(const char *s, size_t max) +{ + size_t len = 0, i; + wchar_t w = 0; + int r; + + for(i = 0; *s; s++, i++) { + if((*s & 0xc0) != 0x80) { + if((r = mbtowc(&w, s, i + 4 > max ? max - i : 4)) == -1) + break; + if((r = wcwidth(w)) == -1) + break; + len += r; + } + } + return len; +} + +static size_t utf8len(const char *s) { size_t i; @@ -133,7 +158,7 @@ utfnextn(const char *s, size_t p, size_t n) return 0; } -/* b is byte start pos, u is utf pos, f is filter function, +/* b is byte start pos, u is utf pos, c is column pos, f is filter function, * dir is -1 or +1 for prev or next */ static void utfuntilchar(size_t *b, size_t *u, int (*f)(int), int dir) @@ -165,12 +190,13 @@ utfuntilchar(size_t *b, size_t *u, int (*f)(int), int dir) static void line_inserttext(const char *s) { - size_t siz, len; + size_t siz, ulen, clen; siz = strlen(s); if(line.bytepos + siz + 1 > sizeof(line.line)) return; - len = utf8len(s); + clen = colw(s, siz); + ulen = utf8len(s); /* append */ if(line.bytepos == line.bytesiz) { memmove(&line.line[line.bytepos], s, siz); @@ -184,7 +210,9 @@ line_inserttext(const char *s) line.bytesiz += siz; line.line[line.bytesiz + 1] = '\0'; line.utflen = utf8len(line.line); - line.utfpos += len; + line.utfpos += ulen; + line.colpos += clen; + line.collen = colw(line.line, line.bytesiz); line_draw(); } @@ -202,6 +230,8 @@ line_set(const char *s) line.bytepos = line.bytesiz; line.utflen = utf8len(line.line); line.utfpos = line.utflen; + line.collen = colw(line.line, line.bytesiz); + line.colpos = line.collen; } /* like mksh, toggle counting of escape codes in prompt with "\x01" */ @@ -237,7 +267,7 @@ line_draw(void) fprintf(outfp, "\x1b[2J\x1b[H"); /* clear */ line_prompt(); fwrite(line.line, 1, line.bytesiz, outfp); - line_cursor_move(line.utfpos); + line_cursor_move(line.colpos); } static void @@ -268,14 +298,16 @@ static void line_cursor_wordprev(void) { line_getwordposprev(line.bytepos, line.utfpos, &line.bytepos, &line.utfpos); - line_cursor_move(line.utfpos); + line.colpos = colw(line.line, line.bytepos); + line_cursor_move(line.colpos); } static void line_cursor_wordnext(void) { line_getwordposnext(line.bytepos, line.utfpos, &line.bytepos, &line.utfpos); - line_cursor_move(line.utfpos); + line.colpos = colw(line.line, line.bytepos); + line_cursor_move(line.colpos); } static void @@ -283,7 +315,8 @@ line_cursor_begin(void) { line.bytepos = 0; line.utfpos = 0; - line_cursor_move(line.utfpos); + line.colpos = 0; + line_cursor_move(line.colpos); } static void @@ -298,7 +331,8 @@ line_cursor_prev(void) line.bytepos -= n; line.utfpos--; - line_cursor_move(line.utfpos); + line.colpos -= colw(&line.line[line.bytepos], n); + line_cursor_move(line.colpos); } static void @@ -311,9 +345,10 @@ line_cursor_next(void) if((n = utfnextn(line.line, line.bytepos, 1)) == 0) return; + line.colpos += colw(&line.line[line.bytepos], n); line.bytepos += n; line.utfpos++; - line_cursor_move(line.utfpos); + line_cursor_move(line.colpos); } static void @@ -321,7 +356,8 @@ line_cursor_end(void) { line.bytepos = line.bytesiz; line.utfpos = line.utflen; - line_cursor_move(line.utfpos); + line.colpos = line.collen; + line_cursor_move(line.colpos); } static void @@ -342,6 +378,9 @@ line_delcharnext(void) if((siz = utfnextn(line.line, line.bytepos, 1)) == 0) return; + + line.collen -= colw(&line.line[line.bytepos], siz); + memmove(&line.line[line.bytepos], &line.line[line.bytepos + siz], line.bytesiz - line.bytepos - siz); @@ -354,20 +393,25 @@ line_delcharnext(void) static void line_delcharprev(void) { - size_t siz; + size_t siz, col; if(line.utfpos <= 0 || line.utflen <= 0) return; if((siz = utfprevn(line.line, line.bytepos, 1)) == 0) return; + col = colw(&line.line[line.bytepos - siz], siz); + memmove(&line.line[line.bytepos - siz], &line.line[line.bytepos], line.bytesiz - line.bytepos); + line.bytepos -= siz; line.bytesiz -= siz; line.line[line.bytesiz] = '\0'; line.utflen--; line.utfpos--; + line.colpos -= col; + line.collen -= col; line_draw(); } @@ -379,6 +423,8 @@ line_deltoend(void) line.bytesiz = line.bytepos; line.utflen = utf8len(line.line); line.utfpos = line.utflen; + line.collen = colw(line.line, line.bytesiz); + line.colpos = line.collen; line_draw(); } @@ -400,6 +446,8 @@ line_delwordcursor(void) line.line[line.bytesiz] = '\0'; line.utfpos -= len; line.utflen -= len; + line.collen = colw(line.line, line.bytesiz); + line.colpos = colw(line.line, bs); line_draw(); } @@ -415,6 +463,7 @@ line_delwordprev(void) line_getwordposprev(line.bytepos, line.utfpos, &bs, &us); siz = line.bytepos - bs; + line.colpos -= colw(&line.line[bs], siz); memmove(&line.line[bs], &line.line[line.bytepos], line.bytesiz - line.bytepos); @@ -425,6 +474,7 @@ line_delwordprev(void) line.line[line.bytesiz] = '\0'; line.utfpos -= len; line.utflen -= len; + line.collen = colw(line.line, line.bytesiz); line_draw(); }