improved the util functions files - iomenu - interactive terminal-based selection menu
 (HTM) git clone git://bitreich.org/iomenu git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/iomenu
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Tags
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit dfe94b799cc9591d604f4130f38a840b2fd37eac
 (DIR) parent bdefd3e959d83d05d65b5df6ce45e6d30b771984
 (HTM) Author: Josuah Demangeon <mail@josuah.net>
       Date:   Sun, 18 Mar 2018 18:55:04 +0100
       
       improved the util functions files
       
       Diffstat:
         M Makefile                            |      20 ++++++++++++--------
         M iomenu.c                            |      49 ++++++++++++++-----------------
         D str.h                               |       1 -
         M strcasestr.c                        |       6 +++---
         A strsep.c                            |      21 +++++++++++++++++++++
         M utf8.c                              |     419 ++++++++++++++++++-------------
         M utf8.h                              |      19 +++++++++++--------
         A util.h                              |      31 +++++++++++++++++++++++++++++++
       
       8 files changed, 350 insertions(+), 216 deletions(-)
       ---
 (DIR) diff --git a/Makefile b/Makefile
       @@ -1,31 +1,35 @@
        CFLAGS = -std=c89 -pedantic -Wall -Wextra -g -D_POSIX_C_SOURCE=200809L
        
       -SRC = iomenu.c utf8.c strcasestr.c
       -OBJ = ${SRC:.o=.c}
       +SRC = iomenu.c strcasestr.c strsep.c utf8.c
       +OBJ = ${SRC:.c=.o}
        
       +.PHONY: all
        all: iomenu
        
        .c.o:
                ${CC} -c -o $@ ${CFLAGS} $<
        
       -iomenu: ${OBJ} utf8.h str.h
       +iomenu: ${OBJ}
                ${CC} -o $@ ${LDFLAGS} ${OBJ}
        
       -utf8.c: utf8.h
       -
       -strcasestr.c: str.h
       +iomenu.o: iomenu.c util.h
       +strcasestr.o: strcasestr.c util.h
       +strsep.o: strsep.c util.h
       +test.o: test.c util.h
       +utf8.o: utf8.c utf8.h
        
       +.PHONY: test
        test: test.c
                ${CC} -o $@ ${LDFLAGS} test.c utf8.c
                ./$@
        
       +.PHONY: clean
        clean:
                rm -f *.o *.core iomenu test
        
       +.PHONY: install
        install: iomenu
                mkdir -p  ${PREFIX}/share/man/man1
                cp *.1    ${PREFIX}/share/man/man1
                mkdir -p  ${PREFIX}/bin
                cp iomenu ${PREFIX}/bin
       -
       -.PHONY: all test clean install
 (DIR) diff --git a/iomenu.c b/iomenu.c
       @@ -12,18 +12,13 @@
        #include <unistd.h>
        
        #include "utf8.h"
       -#include "str.h"
       +#include "util.h"
        #include "arg.h"
        
        #ifndef SIGWINCH
        #define SIGWINCH        28
        #endif
        
       -#define MIN(X, Y)        (((X) < (Y)) ? (X) : (Y))
       -#define CTL(char)        ((char) & ~0x40)
       -#define ALT(char)        ((char) + 0x80)
       -#define CSI(char)        ((char) + 0x80 + 0x80)
       -
        static struct termios        termios;
        struct winsize                ws;
        static int                ttyfd;
       @@ -52,7 +47,7 @@ match_line(char *line, char **tokv)
        ** Free the structures, reset the terminal state and exit with an error message.
        */
        static void
       -err(const char *s)
       +die(const char *s)
        {
                tcsetattr(ttyfd, TCSANOW, &termios);
                close(ttyfd);
       @@ -62,7 +57,7 @@ err(const char *s)
        
        /*
        ** Split a buffer into an array of lines, without allocating memory for every
       -** line, but using the input buffer and replacing characters.
       +** line, but using the input buffer and replacing '\n' by '\0'.
        */
        static void
        split_lines(char *buf)
       @@ -76,9 +71,9 @@ split_lines(char *buf)
                for (b = buf; (b = strchr(b, '\n')) != NULL && b[1] != '\0'; b++)
                        linec++;
                if ((lv = linev = calloc(linec + 1, sizeof(char **))) == NULL)
       -                err("calloc");
       +                die("calloc");
                if ((mv = matchv = calloc(linec + 1, sizeof(char **))) == NULL)
       -                err("calloc");
       +                die("calloc");
                *mv = *lv = b = buf;
                while ((b = strchr(b, '\n')) != NULL) {
                        *b = '\0';
       @@ -99,13 +94,13 @@ read_stdin(void)
                size = BUFSIZ;
                off = 0;
                if ((buf = malloc(size)) == NULL)
       -                err("malloc");
       +                die("malloc");
                while ((len = read(STDIN_FILENO, buf + off, size - off)) > 0) {
                        off += len;
                        if (off == size) {
                                size *= 2;
                                if ((buf = realloc(buf, size + 1)) == NULL)
       -                                err("realloc");
       +                                die("realloc");
                        }
                }
                buf[off] = '\0';
       @@ -237,14 +232,14 @@ print_selection(void)
        }
        
        /*
       -** Big case table, that calls itself back for with ALT (aka ESC), CSI
       -** (aka ESC + [).  These last two have values above the range of ASCII.
       +** Big case table, that calls itself back for with ALT (aka Esc), CSI
       +** (aka Esc + [).  These last two have values above the range of ASCII.
        */
        int
        key(int k)
        {
                extern        char        **matchv, input[LINE_MAX];
       -        extern        int          linec;
       +        extern        int        linec;
        
        top:
                switch (k) {
       @@ -258,47 +253,47 @@ top:
                        remove_word();
                        break;
                case 127:
       -        case CTL('H'):  /* backspace */
       +        case CTL('H'):        /* backspace */
                        input[strlen(input) - 1] = '\0';
                        filter(linec, linev);
                        break;
       -        case CSI('A'):  /* up */
       +        case CSI('A'):        /* up */
                case CTL('P'):
                        move(-1);
                        break;
       -        case CSI('B'):  /* down */
       +        case CSI('B'):        /* down */
                case CTL('N'):
                        move(+1);
                        break;
       -        case CSI('5'):  /* page up */
       +        case CSI('5'):        /* page up */
                        if (fgetc(stdin) != '~')
                                break;
                        /* FALLTHROUGH */
                case ALT('v'):
                        move_page(-1);
                        break;
       -        case CSI('6'):  /* page down */
       +        case CSI('6'):        /* page down */
                        if (fgetc(stdin) != '~')
                                break;
                        /* FALLTHROUGH */
                case CTL('V'):
                        move_page(+1);
                        break;
       -        case CTL('I'):  /* tab */
       +        case CTL('I'):        /* tab */
                        if (linec > 0) {
                                strncpy(input, matchv[cur], sizeof(input));
                                input[sizeof(input) - 1] = '\0';
                        }
                        filter(matchc, matchv);
                        break;
       -        case CTL('J'):  /* enter */
       +        case CTL('J'):        /* enter */
                case CTL('M'):
                        print_selection();
                        return 0;
                case ALT('['):
                        k = CSI(fgetc(stdin));
                        goto top;
       -        case 0x1b: /* escape / alt */
       +        case ESC:
                        k = ALT(fgetc(stdin));
                        goto top;
                default:
       @@ -384,7 +379,7 @@ sighandle(int sig)
                switch (sig) {
                case SIGWINCH:
                        if (ioctl(ttyfd, TIOCGWINSZ, &ws) < 0)
       -                        err("ioctl");
       +                        die("ioctl");
                        print_screen();
                        break;
                }
       @@ -408,11 +403,11 @@ init(void)
                filter(linec, linev);
        
                if (freopen("/dev/tty", "r", stdin) == NULL)
       -                err("freopen /dev/tty");
       +                die("freopen /dev/tty");
                if (freopen("/dev/tty", "w", stderr) == NULL)
       -                err("freopen /dev/tty");
       +                die("freopen /dev/tty");
                if ((ttyfd = open("/dev/tty", O_RDWR)) < 0)
       -                err("open /dev/tty");
       +                die("open /dev/tty");
        
                set_terminal();
                sighandle(SIGWINCH);
 (DIR) diff --git a/str.h b/str.h
       @@ -1 +0,0 @@
       -char        *strcasestr(const char *, const char *);
 (DIR) diff --git a/strcasestr.c b/strcasestr.c
       @@ -1,13 +1,13 @@
        #include <ctype.h>
        #include <stddef.h>
        
       -#include "str.h"
       +#include "util.h"
        
        char *
        strcasesstr(const char *str1, const char *str2)
        {
       -        const char        *s1;
       -        const char        *s2;
       +        const char *s1;
       +        const char *s2;
        
                for (;;) {
                        s1 = str1;
 (DIR) diff --git a/strsep.c b/strsep.c
       @@ -0,0 +1,21 @@
       +#include <string.h>
       +
       +char *
       +strsep(char **strp, const char *delim)
       +{
       +        char        *s, *oldp;
       +
       +        if (*strp == NULL)
       +                return NULL;
       +        for (s = oldp = *strp; ; s++) {
       +                if (*s == '\0') {
       +                        *strp = NULL;
       +                        return oldp;
       +                } else if (strchr(delim, *s) != NULL) {
       +                        break;
       +                }
       +        }
       +        *s = '\0';
       +        *strp = s + 1;
       +        return oldp;
       +}
 (DIR) diff --git a/utf8.c b/utf8.c
       @@ -1,160 +1,186 @@
        /*
       - * ASCII all have a leading '0' byte:
       - *
       - *   0xxxxxxx
       - *
       - * UTF-8(7) have one leading '1' and as many following '1' as there are
       - * continuation bytes (with leading '1' and '0').
       - *
       - *   0xxxxxxx
       - *   110xxxxx 10xxxxxx
       - *   1110xxxx 10xxxxxx 10xxxxxx
       - *   11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
       - *   111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
       - *   1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
       - *
       - * There is up to 3 continuation bytes -- up to 4 bytes per runes.
       - *
       - * The whole character value is retreived into an 'x' and stored into a
       - * (long)[].
       - *
       - * Thanks to Connor Lane Smith for the idea of combining switches and
       - * binary masks.
       - */
       +** ASCII all have a leading '0' byte:
       +**
       +**   0xxxxxxx
       +**
       +** UTF-8 have one leading '1' and as many following '1' as there are
       +** continuation bytes (with leading '1' and '0').
       +**
       +**   0xxxxxxx
       +**   110xxxxx 10xxxxxx
       +**   1110xxxx 10xxxxxx 10xxxxxx
       +**   11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
       +**   111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
       +**   1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
       +**
       +** There is up to 3 continuation bytes -- up to 4 bytes per runes.
       +*/
        
        #include <ctype.h>
        #include <stddef.h>
        #include <stdlib.h>
        #include <string.h>
       +#include <stdio.h>
        
        #include "utf8.h"
        
       -/*
       - * Return the number of bytes in rune for the `n` next char in `s`,
       - * or 0 if is misencoded or if it is '\0'.
       - */
       -size_t
       -utf8_len(char *s)
       +static int
       +utflen(char const *str)
        {
       -        unsigned char *sp = (unsigned char *) s;
                int i, len;
       +        unsigned char const *s;
        
       -        len =        (*sp == 0x0) ? 0 :  /* 00000000 */
       -                (*sp < 0x80) ? 1 :  /* 0xxxxxxx < 10000000 */
       -                (*sp < 0xc0) ? 0 :  /* 10xxxxxx < 11000000 */
       -                (*sp < 0xe0) ? 2 :  /* 110xxxxx < 11100000 */
       -                (*sp < 0xf0) ? 3 :  /* 1110xxxx < 11110000 */
       -                (*sp < 0xf8) ? 4 :  /* 11110xxx < 11111000 */
       -                (*sp < 0xfc) ? 5 :  /* 111110xx < 11111100 */
       -                (*sp < 0xfe) ? 6 :  /* 1111110x < 11111110 */
       -                (*sp < 0xff) ? 7 :  /* 11111110 < 11111111 */
       -                             0;
       +        s = (unsigned char const *)str;
       +        len =        (*s < 0x80) ? 1 :  /* 0xxxxxxx < *s < 10000000 */
       +                (*s < 0xc0) ? 0 :  /* 10xxxxxx < *s < 11000000 */
       +                (*s < 0xe0) ? 2 :  /* 110xxxxx < *s < 11100000 */
       +                (*s < 0xf0) ? 3 :  /* 1110xxxx < *s < 11110000 */
       +                (*s < 0xf8) ? 4 :  /* 11110xxx < *s < 11111000 */
       +                (*s < 0xfc) ? 5 :  /* 111110xx < *s < 11111100 */
       +                (*s < 0xfe) ? 6 :  /* 1111110x < *s < 11111110 */
       +                (*s < 0xff) ? 7 :  /* 11111110 < *s < 11111111 */
       +                0;
        
                /* check continuation bytes and '\0' */
       -        for (sp++, i = 1; i < len; i++, sp++) {
       -                if ((*sp & 0xc0) != 0x80)  /* 10xxxxxx & 11000000 */
       +        for (s++, i = 1; i < len; i++, s++) {
       +                if ((*s & 0xc0) != 0x80)        /* 10xxxxxx & 11000000 */
                                return 0;
                }
        
                return len;
        }
        
       +static long
       +torune(char const **str, size_t len)
       +{
       +        long rune;
       +        int n;
       +        char mask[] = { 0x00, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
       +
       +        if (len == 0 || len > 6)
       +                return 0;
       +
       +        /* first byte */
       +        rune = *(*str)++ & mask[len];
       +
       +        /* continuation bytes */
       +        for (n = len - 1; n > 0; n--, (*str)++)
       +                rune = (rune << 6) | (**str & 0x3f);        /* 10xxxxxx */
       +
       +        return rune;
       +}
       +
        /*
       - * Return the number of bytes required to encode `rune` into UTF-8, or
       - * 0 if rune is too long.
       - */
       -size_t
       +** Return the number of bytes required to encode <rune> into UTF-8, or
       +** 0 if rune is too long.
       +*/
       +int
        utf8_runelen(long rune)
        {
       -        return        (rune <= 0x0000007f) ? 1 : (rune <= 0x000007ff) ? 2 :
       -                (rune <= 0x0000ffff) ? 3 : (rune <= 0x001fffff) ? 4 :
       -                (rune <= 0x03ffffff) ? 5 : (rune <= 0x7fffffff) ? 6 : 0;
       +        return        (rune <= 0x0000007f) ? 1 :
       +                (rune <= 0x000007ff) ? 2 :
       +                (rune <= 0x0000ffff) ? 3 :
       +                (rune <= 0x001fffff) ? 4 :
       +                (rune <= 0x03ffffff) ? 5 :
       +                (rune <= 0x7fffffff) ? 6 :
       +                0;
        }
        
        /*
       - * Sets `rune' to a rune corresponding to the firsts `n' bytes of `s'.
       - *
       - * Return the number of bytes read or 0 if the string is misencoded.
       - */
       -size_t
       -utf8_torune(long *rune, char *s)
       +** Return the number of bytes in rune for the next char in <s>, or 0 if
       +** is misencoded or if it is '\0'.
       +*/
       +int
       +utf8_utflen(char const *str)
        {
       -        char mask[] = { 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
       -        size_t i, len = utf8_len(s);
       +        long rune;
       +        int len;
        
       -        if (len == 0 || len > 6 || (size_t) len > strlen(s))
       +        len = utflen(str);
       +        rune = torune(&str, len);
       +        if (len != utf8_runelen(rune))
                        return 0;
        
       -        /* first byte */
       -        *rune = *s++ & mask[len - 1];
       +        return len;
       +}
        
       -        /* continuation bytes */
       -        for (i = 1; i < len; i++)
       -                *rune = (*rune << 6) | (*s++ & 0x3f);  /* 10xxxxxx */
       +/*
       +** Return a rune corresponding to the firsts bytes of <str> or -1 if
       +** the rune is invalid, and set <str> to the beginning of the next rune.
       +*/
       +long
       +utf8_torune(char const **str)
       +{
       +        long rune;
       +        int len;
        
       -        /* overlong sequences */
       -        if (utf8_runelen(*rune) != len)
       -                return 0;
       +        len = utflen(*str);
       +        rune = torune(str, len);
       +        if (len != utf8_runelen(rune))
       +                return -1;
        
       -        return len;
       +        return rune;
        }
        
        /*
       - * Encode the rune `rune' in utf-8 in `s', null-terminated, then return the
       - * number of bytes written, 0 if `rune' is invalid.
       - */
       +** Encode the rune <rune> in UTF-8 in <str>, null-terminated, then return the
       +** number of bytes written, 0 if <rune> is invalid.
       +**
       +** Thanks to Connor Lane Smith for the idea of combining switches and
       +** binary masks.
       +*/
        int
       -utf8_tostr(char *s, long rune)
       +utf8_tostr(char *str, long rune)
        {
                switch (utf8_runelen(rune)) {
                case 1:
       -                s[0] = rune;                                /* 0xxxxxxx */
       -                s[1] = '\0';
       +                str[0] = rune;                                /* 0xxxxxxx */
       +                str[1] = '\0';
                        return 1;
                case 2:
       -                s[0] = 0xc0 | (0x1f & (rune >> 6));        /* 110xxxxx */
       -                s[1] = 0x80 | (0x3f & (rune));                /* 10xxxxxx */
       -                s[2] = '\0';
       +                str[0] = 0xc0 | (0x1f & (rune >> 6));        /* 110xxxxx */
       +                str[1] = 0x80 | (0x3f & (rune));        /* 10xxxxxx */
       +                str[2] = '\0';
                        return 2;
                case 3:
       -                s[0] = 0xe0 | (0x0f & (rune >> 12));        /* 1110xxxx */
       -                s[1] = 0x80 | (0x3f & (rune >> 6));        /* 10xxxxxx */
       -                s[2] = 0x80 | (0x3f & (rune));                /* 10xxxxxx */
       -                s[3] = '\0';
       +                str[0] = 0xe0 | (0x0f & (rune >> 12));        /* 1110xxxx */
       +                str[1] = 0x80 | (0x3f & (rune >> 6));        /* 10xxxxxx */
       +                str[2] = 0x80 | (0x3f & (rune));        /* 10xxxxxx */
       +                str[3] = '\0';
                        return 3;
                case 4:
       -                s[0] = 0xf0 | (0x07 & (rune >> 18));        /* 11110xxx */
       -                s[1] = 0x80 | (0x3f & (rune >> 12));        /* 10xxxxxx */
       -                s[2] = 0x80 | (0x3f & (rune >> 6));        /* 10xxxxxx */
       -                s[3] = 0x80 | (0x3f & (rune));                /* 10xxxxxx */
       -                s[4] = '\0';
       +                str[0] = 0xf0 | (0x07 & (rune >> 18));        /* 11110xxx */
       +                str[1] = 0x80 | (0x3f & (rune >> 12));        /* 10xxxxxx */
       +                str[2] = 0x80 | (0x3f & (rune >> 6));        /* 10xxxxxx */
       +                str[3] = 0x80 | (0x3f & (rune));        /* 10xxxxxx */
       +                str[4] = '\0';
                        return 4;
                case 5:
       -                s[0] = 0xf8 | (0x03 & (rune >> 24));        /* 111110xx */
       -                s[1] = 0x80 | (0x3f & (rune >> 18));        /* 10xxxxxx */
       -                s[2] = 0x80 | (0x3f & (rune >> 12));        /* 10xxxxxx */
       -                s[3] = 0x80 | (0x3f & (rune >> 6));        /* 10xxxxxx */
       -                s[4] = 0x80 | (0x3f & (rune));                /* 10xxxxxx */
       -                s[5] = '\0';
       +                str[0] = 0xf8 | (0x03 & (rune >> 24));        /* 111110xx */
       +                str[1] = 0x80 | (0x3f & (rune >> 18));        /* 10xxxxxx */
       +                str[2] = 0x80 | (0x3f & (rune >> 12));        /* 10xxxxxx */
       +                str[3] = 0x80 | (0x3f & (rune >> 6));        /* 10xxxxxx */
       +                str[4] = 0x80 | (0x3f & (rune));        /* 10xxxxxx */
       +                str[5] = '\0';
                        return 5;
                case 6:
       -                s[0] = 0xfc | (0x01 & (rune >> 30));        /* 1111110x */
       -                s[1] = 0x80 | (0x3f & (rune >> 24));        /* 10xxxxxx */
       -                s[2] = 0x80 | (0x3f & (rune >> 18));        /* 10xxxxxx */
       -                s[3] = 0x80 | (0x3f & (rune >> 12));        /* 10xxxxxx */
       -                s[4] = 0x80 | (0x3f & (rune >> 6));        /* 10xxxxxx */
       -                s[5] = 0x80 | (0x3f & (rune));                /* 10xxxxxx */
       -                s[6] = '\0';
       +                str[0] = 0xfc | (0x01 & (rune >> 30));        /* 1111110x */
       +                str[1] = 0x80 | (0x3f & (rune >> 24));        /* 10xxxxxx */
       +                str[2] = 0x80 | (0x3f & (rune >> 18));        /* 10xxxxxx */
       +                str[3] = 0x80 | (0x3f & (rune >> 12));        /* 10xxxxxx */
       +                str[4] = 0x80 | (0x3f & (rune >> 6));        /* 10xxxxxx */
       +                str[5] = 0x80 | (0x3f & (rune));        /* 10xxxxxx */
       +                str[6] = '\0';
                        return 6;
                default:
       -                s[0] = '\0';
       +                str[0] = '\0';
                        return 0;
                }
        }
        
        /*
       - * Return 1 if the rune is a printable character, and 0 otherwise.
       - */
       +** Return 1 if the rune is a printable character, and 0 otherwise.
       +*/
        int
        utf8_isprint(long rune)
        {
       @@ -162,41 +188,14 @@ utf8_isprint(long rune)
        }
        
        /*
       - * Return a index of the first byte of a character of `s' that would be rendered
       - * at the `col'-th column in a terminal, or NULL if the whole string fit.  In
       - * order to format tabs properly, the string must start with an offset of `off'
       - * columns.
       - */
       -int
       -utf8_col(char *str, int col, int off)
       -{
       -        long rune;
       -        char *pos, *s;
       -
       -        for (s = str; off <= col;) {
       -                pos = s;
       -                if (*s == '\0')
       -                        break;
       -
       -                s += utf8_torune(&rune, s);
       -                if (rune == '\t')
       -                        off += 8 - (off % 8);
       -                else
       -                        off += utf8_wcwidth(rune);
       -        }
       -
       -        return pos - str;
       -}
       -
       -/*
       - * Markus Kuhn -- 2007-05-26 (Unicode 5.0)
       - *
       - * Permission to use, copy, modify, and distribute this software
       - * for any purpose and without fee is hereby granted. The author
       - * disclaims all warranties with regard to this software.
       - *
       - * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
       - */
       +** Markus Kuhn -- 2007-05-26 (Unicode 5.0)
       +**
       +** Permission to use, copy, modify, and distribute this software
       +** for any purpose and without fee is hereby granted. The author
       +** disclaims all warranties with regard to this software.
       +**
       +** Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
       +*/
        
        struct interval {
                int first;
       @@ -204,10 +203,10 @@ struct interval {
        };
        
        /*
       - * auxiliary function for binary search in interval table
       - */
       +** Auxiliary function for binary search in interval table.
       +*/
        static int
       -bisearch(long ucs, const struct interval *table, int max)
       +bisearch(long ucs, struct interval const *table, int max)
        {
                int min = 0;
                int mid;
       @@ -228,42 +227,42 @@ bisearch(long ucs, const struct interval *table, int max)
        }
        
        /* The following two functions define the column width of an ISO 10646
       - * character as follows:
       - *
       - *    - The null character (U+0000) has a column width of 0.
       - *
       - *    - Other C0/C1 control characters and DEL will lead to a return
       - *      value of -1.
       - *
       - *    - Non-spacing and enclosing combining characters (general
       - *      category code Mn or Me in the Unicode database) have a
       - *      column width of 0.
       - *
       - *    - SOFT HYPHEN (U+00AD) has a column width of 1.
       - *
       - *    - Other format characters (general category code Cf in the Unicode
       - *      database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
       - *
       - *    - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
       - *      have a column width of 0.
       - *
       - *    - Spacing characters in the East Asian Wide (W) or East Asian
       - *      Full-width (F) category as defined in Unicode Technical
       - *      Report #11 have a column width of 2.
       - *
       - *    - All remaining characters (including all printable
       - *      ISO 8859-1 and WGL4 characters, Unicode control characters,
       - *      etc.) have a column width of 1.
       - *
       - * This implementation was assuming that wchar_t characters are encoded
       - * in ISO 10646, but wchar_t have been replaced by long.
       - */
       +** character as follows:
       +**
       +**    - The null character (U+0000) has a column width of 0.
       +**
       +**    - Other C0/C1 control characters and DEL will lead to a return
       +**      value of -1.
       +**
       +**    - Non-spacing and enclosing combining characters (general
       +**      category code Mn or Me in the Unicode database) have a
       +**      column width of 0.
       +**
       +**    - SOFT HYPHEN (U+00AD) has a column width of 1.
       +**
       +**    - Other format characters (general category code Cf in the Unicode
       +**      database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
       +**
       +**    - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
       +**      have a column width of 0.
       +**
       +**    - Spacing characters in the East Asian Wide (W) or East Asian
       +**      Full-width (F) category as defined in Unicode Technical
       +**      Report #11 have a column width of 2.
       +**
       +**    - All remaining characters (including all printable
       +**      ISO 8859-1 and WGL4 characters, Unicode control characters,
       +**      etc.) have a column width of 1.
       +**
       +** This implementation was assuming that long characters are encoded
       +** in ISO 10646.
       +*/
        int
        utf8_wcwidth(long ucs)
        {
                /* sorted list of non-overlapping intervals of non-spacing characters */
                /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
       -        static const struct interval combining[] = {
       +        static struct interval const combining[] = {
                        { 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 },
                        { 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
                        { 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 },
       @@ -341,3 +340,85 @@ utf8_wcwidth(long ucs)
                    (ucs >= 0x20000 && ucs <= 0x2fffd) ||
                    (ucs >= 0x30000 && ucs <= 0x3fffd)));
        }
       +
       +/*
       +** Return the width of <rune> with tabs as displayed from position <off>.
       +*/
       +int
       +utf8_runewidth(long rune, size_t off)
       +{
       +        return (rune == '\t') ?  (int)(8 - (off % 8)) : utf8_wcwidth(rune);
       +}
       +
       +/*
       +** Return a index of the first byte of a character of <s> that would be rendered
       +** at the <col>-th column in a terminal, or NULL if the whole string fit.  In
       +** order to format tabs properly, the string must start with an offset of <off>
       +** columns.
       +*/
       +int
       +utf8_col(char const *str, size_t col, size_t off)
       +{
       +        long rune;
       +        char const *pos, *s;
       +
       +        for (s = str; off <= col;) {
       +                pos = s;
       +                if (*s == '\0')
       +                        break;
       +
       +                rune = utf8_torune(&s);
       +                off += utf8_runewidth(rune, off);
       +        }
       +
       +        return pos - str;
       +}
       +
       +/*
       +** Print <rune> to <fp> if it is less wide than <maxwidth> and return
       +** the number of columns of the rune printed or a negative value if
       +** nothing was printed: -1 if the rune is invalid, and -2 if no width
       +** is left.  If the rune is tab, the width is calculated usin <off>
       +** as column offset.
       +*/
       +int
       +utf8_putrune(long rune, int maxwidth, int off, FILE *fp)
       +{
       +        int width;
       +        char str[8];
       +
       +        if ((width = utf8_runewidth(rune, off)) > maxwidth)
       +                return -2;
       +        if (utf8_tostr(str, rune) == 0)
       +                return -1;
       +        fputs(str, fp);
       +
       +        return width;
       +}
       +
       +/*
       +** Return a pointer to the next rune in <str> or next byte if the rune
       +** is invalid.
       +*/
       +char const *
       +utf8_nextrune(char const *str)
       +{
       +        int len;
       +
       +        len = utf8_utflen(str);
       +        return (len == 0) ? str + 1 : str + len;
       +}
       +
       +/*
       +** Return a pointer to the prev rune in <str> or prev byte if the rune
       +** is invalid.
       +*/
       +char const *
       +utf8_prevrune(char const *str)
       +{
       +        char const *s;
       +
       +        for (s = str; (*s & 0x80) != 0; s--)
       +                ;
       +        return (utf8_utflen(s) != 0) ? s : str - 1;
       +}
 (DIR) diff --git a/utf8.h b/utf8.h
       @@ -1,8 +1,11 @@
       -size_t        utf8_len(char *);
       -size_t        rune_len(long);
       -size_t        utf8_torune(long *, char *);
       -int        utf8_isunicode(long);
       -int        utf8_check(char *);
       -int        utf8_isprint(long);
       -int        utf8_col(char *, int, int);
       -int        utf8_wcwidth(long);
       +int                 utf8_runelen        (long);
       +int                 utf8_utflen        (char const *);
       +long                 utf8_torune        (char const **);
       +int                 utf8_tostr        (char *, long);
       +int                 utf8_isprint        (long);
       +int                 utf8_wcwidth        (long);
       +int                 utf8_runewidth        (long, size_t);
       +int                 utf8_col        (char const *, size_t, size_t);
       +int                 utf8_putrune        (long, int, int, FILE *);
       +char const        *utf8_nextrune        (char const *);
       +char const        *utf8_prevrune        (char const *);
 (DIR) diff --git a/util.h b/util.h
       @@ -0,0 +1,31 @@
       +/*
       +** EPITECH PROJECT, 2017
       +** util
       +** File description:
       +** util
       +*/
       +
       +#ifndef UTIL_H
       +#define UTIL_H
       +
       +#include <stdarg.h>
       +
       +#define ESC                0x1b                        /* Esc key */
       +#define CTL(c)                ((c) & ~0x40)                /* Ctr + (c) key */
       +#define ALT(c)                ((c) + 0x80)                /* Alt + (c) key */
       +#define CSI(c)                ((c) + 0x80 + 0x80)        /* Escape + '[' + (c) code */
       +#define MIN(x, y)        (((x) < (y)) ? (x) : (y))
       +#define MAX(x, y)        (((x) > (y)) ? (x) : (y))
       +#define LEN(x)                (sizeof(x) / sizeof(*(x)))
       +
       +/* string */
       +char        *strcasestr(const char *, const char *);
       +size_t        strlcpy(char *, const char *, size_t);
       +char        *strsep(char **, const char *);
       +
       +/* error */
       +void        err(int, const char *, ...);
       +void        vwarn(const char *, va_list);
       +void        warn(const char *, ...);
       +
       +#endif