Introduction
Introduction Statistics Contact Development Disclaimer Help
add uft-8 support - lchat - A line oriented chat front end for ii.
git clone git://git.suckless.org/lchat
Log
Files
Refs
README
---
commit 0f8af7612e393d40705e953306bc0555f026c2f7
parent 569292df0c821cf2c977d224345ec009e344cb1c
Author: Jan Klemkow <[email protected]>
Date: Sat, 9 Jul 2016 20:30:21 +0200
add uft-8 support
Diffstat:
M Makefile | 26 +++++++++++++++++++++-----
M lchat.c | 44 +++++++++++++++++++++--------…
M slackline.c | 151 ++++++++++++++++++++++++-----…
M slackline.h | 18 ++++++++++++++++--
4 files changed, 183 insertions(+), 56 deletions(-)
---
diff --git a/Makefile b/Makefile
@@ -1,18 +1,34 @@
-CC=cc
-CFLAGS=-std=c99 -pedantic -Wall -Wextra
+CC ?= cc
+CFLAGS = -std=c99 -pedantic -Wall -Wextra -g
-.PHONY: all clean
+# utf.h
+CFLAGS += -I/usr/local/include
+LIBS = -L/usr/local/lib -lutf
+
+.PHONY: all clean test debug
all: lchat
clean:
- rm -f lchat *.o
+ rm -f lchat *.o *.core
+
+test: sl_test
+ ./sl_test
+
+debug:
+ gdb lchat lchat.core
lchat: lchat.o slackline.o
- $(CC) -o $@ lchat.o slackline.o
+ $(CC) -o $@ lchat.o slackline.o $(LIBS)
lchat.o: lchat.c
$(CC) -c $(CFLAGS) -D_BSD_SOURCE -D_XOPEN_SOURCE -D_GNU_SOURCE \
-o $@ lchat.c
+sl_test.o: sl_test.c slackline.h
+ $(CC) $(CFLAGS) -c -o $@ sl_test.c
+
+sl_test: sl_test.o slackline.o slackline.h
+ $(CC) $(CFLAGS) -o $@ sl_test.o slackline.o $(LIBS)
+
slackline.o: slackline.c slackline.h
$(CC) -c $(CFLAGS) -o $@ slackline.c
diff --git a/lchat.c b/lchat.c
@@ -112,9 +112,9 @@ line_output(struct slackline *sl, char *file)
err(EXIT_FAILURE, "open: %s", file);
/* replace NUL-terminator with newline as line separator for file */
- sl->buf[sl->len] = '\n';
+ sl->buf[sl->blen] = '\n';
- if (write(fd, sl->buf, sl->len + 1) == -1)
+ if (write(fd, sl->buf, sl->blen + 1) == -1)
err(EXIT_FAILURE, "write");
if (close(fd) == -1)
@@ -137,7 +137,7 @@ main(int argc, char *argv[])
struct termios term;
struct slackline *sl = sl_init();
int fd = STDIN_FILENO;
- int c;
+ char c;
int ch;
bool empty_line = false;
bool bell_flag = true;
@@ -285,15 +285,28 @@ main(int argc, char *argv[])
/* handle keyboard intput */
if (pfd[0].revents & POLLIN) {
- c = getchar();
- if (c == 13) { /* return */
- if (sl->len == 0 && empty_line == false)
+ ssize_t ret = read(fd, &c, sizeof c);
+
+ if (ret == -1)
+ err(EXIT_FAILURE, "read");
+
+ if (ret == 0)
+ return EXIT_SUCCESS;
+
+ switch (c) {
+ case 4: /* eot */
+ return EXIT_SUCCESS;
+ break;
+ case 13: /* return */
+ if (sl->rlen == 0 && empty_line == false)
goto out;
line_output(sl, in_file);
sl_reset(sl);
+ break;
+ default:
+ if (sl_keystroke(sl, c) == -1)
+ errx(EXIT_FAILURE, "sl_keystroke");
}
- if (sl_keystroke(sl, c) == -1)
- errx(EXIT_FAILURE, "sl_keystroke");
}
/* handle tail command error and its broken pipe */
@@ -324,19 +337,22 @@ main(int argc, char *argv[])
fputs(sl->buf, stdout);
/* save amount of overhanging lines */
- loverhang = (prompt_len + sl->len) / winsize.ws_col;
+ loverhang = (prompt_len + sl->rlen) / winsize.ws_col;
/* correct line wrap handling */
- if ((prompt_len + sl->len) > 0 &&
- (prompt_len + sl->len) % winsize.ws_col == 0)
+ if ((prompt_len + sl->rlen) > 0 &&
+ (prompt_len + sl->rlen) % winsize.ws_col == 0)
fputs("\n", stdout);
- if (sl->cur < sl->len) { /* move the cursor */
+ if (sl->rcur < sl->rlen) { /* move the cursor */
putchar('\r');
/* HACK: because \033[0C does the same as \033[1C */
- if (sl->cur + prompt_len > 0)
- printf("\033[%zuC", sl->cur + prompt_len);
+ if (sl->rcur + prompt_len > 0)
+ printf("\033[%zuC", sl->rcur + prompt_len);
}
+
+ if (fflush(stdout) == EOF)
+ err(EXIT_FAILURE, "fflush");
}
return EXIT_SUCCESS;
}
diff --git a/slackline.c b/slackline.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 Jan Klemkow <[email protected]>
+ * Copyright (c) 2015-2016 Jan Klemkow <[email protected]>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,10 +14,12 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdbool.h>
+
+#include <utf.h>
#include "slackline.h"
@@ -35,6 +37,9 @@ sl_init(void)
return NULL;
}
+ memset(sl->ubuf, 0, sizeof(sl->ubuf));
+ sl->ubuf_len = 0;
+
sl_reset(sl);
return sl;
@@ -51,15 +56,58 @@ void
sl_reset(struct slackline *sl)
{
sl->buf[0] = '\0';
- sl->len = 0;
- sl->cur = 0;
+ sl->ptr = sl->buf;
+ sl->last = sl->buf;
+
+ sl->bcur = 0;
+ sl->blen = 0;
+ sl->rcur = 0;
+ sl->rlen = 0;
+
sl->esc = ESC_NONE;
+ sl->ubuf_len = 0;
+}
+
+static size_t
+sl_postobyte(struct slackline *sl, size_t pos)
+{
+ char *ptr = &sl->buf[0];
+ size_t byte = 0;
+
+ for (;pos > 0; pos--) {
+ for (size_t i = 0;; i++) {
+ if (fullrune(ptr, i) == 1) {
+ ptr += i;
+ byte += i;
+ break;
+ }
+ }
+ }
+
+ return byte;
+}
+
+static char *
+sl_postoptr(struct slackline *sl, size_t pos)
+{
+ char *ptr = &sl->buf[0];
+
+ for (;pos > 0; pos--) {
+ for (size_t i = 0;; i++) {
+ if (fullrune(ptr, i) == 1) {
+ ptr += i;
+ break;
+ }
+ }
+ }
+
+ return ptr;
}
int
sl_keystroke(struct slackline *sl, int key)
{
- if (sl == NULL || sl->len < sl->cur)
+ if (sl == NULL || sl->rlen < sl->rcur)
return -1;
/* handle escape sequences */
@@ -75,55 +123,88 @@ sl_keystroke(struct slackline *sl, int key)
case 'B': /* down */
break;
case 'C': /* right */
- if (sl->cur < sl->len)
- sl->cur++;
+ if (sl->rcur < sl->rlen)
+ sl->rcur++;
+ sl->bcur = sl_postobyte(sl, sl->rcur);
break;
case 'D': /* left */
- if (sl->cur > 0)
- sl->cur--;
+ if (sl->rcur > 0)
+ sl->rcur--;
+ sl->bcur = sl_postobyte(sl, sl->rcur);
break;
case 'H': /* Home */
- sl->cur = 0;
+ sl->bcur = sl->rcur = 0;
break;
case 'F': /* End */
- sl->cur = sl->len;
+ sl->rcur = sl->rlen;
+ sl->bcur = sl_postobyte(sl, sl->rcur);
break;
}
sl->esc = ESC_NONE;
return 0;
}
- /* add character to buffer */
- if (key >= 32 && key < 127) {
- if (sl->cur < sl->len) {
- memmove(sl->buf + sl->cur + 1, sl->buf + sl->cur,
- sl->len - sl->cur);
- sl->buf[sl->cur++] = key;
- } else {
- sl->buf[sl->cur++] = key;
- sl->buf[sl->cur] = '\0';
- }
- sl->len++;
- return 0;
- }
-
/* handle ctl keys */
switch (key) {
case 27: /* Escape */
sl->esc = ESC;
- break;
+ return 0;
case 127: /* backspace */
case 8: /* backspace */
- if (sl->cur == 0)
- break;
- if (sl->cur < sl->len)
- memmove(sl->buf + sl->cur - 1, sl->buf + sl->cur,
- sl->len - sl->cur);
- sl->cur--;
- sl->len--;
- sl->buf[sl->len] = '\0';
- break;
+ if (sl->rcur == 0)
+ return 0;
+
+ char *ncur = sl_postoptr(sl, sl->rcur - 1);
+
+ if (sl->rcur < sl->rlen)
+ memmove(ncur, sl->ptr, sl->last - sl->ptr);
+
+ sl->rcur--;
+ sl->rlen--;
+ sl->last -= sl->ptr - ncur;
+ sl->ptr = ncur;
+ sl->bcur = sl_postobyte(sl, sl->rcur);
+ sl->blen = sl_postobyte(sl, sl->rlen);
+ *sl->last = '\0';
+ return 0;
}
+ /* byte-wise composing of UTF-8 runes */
+ sl->ubuf[sl->ubuf_len++] = key;
+ if (fullrune(sl->ubuf, sl->ubuf_len) == 0)
+ return 0;
+
+ if (sl->blen + sl->ubuf_len >= sl->bufsize) {
+ char *nbuf;
+
+ if ((nbuf = realloc(sl->buf, sl->bufsize * 2)) == NULL)
+ return -1;
+
+ sl->buf = nbuf;
+ sl->bufsize *= 2;
+ }
+
+ /* add character to buffer */
+ if (sl->rcur < sl->rlen) { /* insert into buffer */
+ char *ncur = sl_postoptr(sl, sl->rcur + 1);
+ char *cur = sl_postoptr(sl, sl->rcur);
+ char *end = sl_postoptr(sl, sl->rlen);
+
+ memmove(ncur, cur, end - cur);
+ }
+
+ memcpy(sl->last, sl->ubuf, sl->ubuf_len);
+
+ sl->ptr += sl->ubuf_len;
+ sl->last += sl->ubuf_len;
+ sl->bcur += sl->ubuf_len;
+ sl->blen += sl->ubuf_len;
+ sl->ubuf_len = 0;
+
+ sl->rcur++;
+ sl->rlen++;
+
+ *sl->last = '\0';
+
return 0;
}
diff --git a/slackline.h b/slackline.h
@@ -6,11 +6,25 @@
enum esc_seq {ESC_NONE, ESC, ESC_BRACKET};
struct slackline {
+ /* buffer */
char *buf;
+ char *ptr; /* ptr of cursor */
+ char *last; /* ptr of last byte of string */
size_t bufsize;
- size_t len;
- size_t cur;
+
+ /* byte positions */
+ size_t bcur; /* first byte of the rune of the cursor */
+ size_t blen; /* amount of bytes of current string */
+
+ /* rune positions */
+ size_t rcur; /* cursor */
+ size_t rlen; /* amount of runes */
+
enum esc_seq esc;
+
+ /* UTF-8 handling */
+ char ubuf[6]; /* UTF-8 buffer */
+ size_t ubuf_len;
};
struct slackline *sl_init(void);
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.