diff --git a/src/console.h b/src/console.h index 5e06700..904b194 100644 --- a/src/console.h +++ b/src/console.h @@ -14,10 +14,22 @@ * of it. */ +#include #include +struct kmscon_char; struct kmscon_console; +/* single printable characters */ + +int kmscon_char_new(struct kmscon_char **out); +void kmscon_char_free(struct kmscon_char *ch); + +int kmscon_char_set_u8(struct kmscon_char *ch, const char *str, size_t len); +const char *kmscon_char_get_u8(const struct kmscon_char *ch); +size_t kmscon_char_get_len(const struct kmscon_char *ch); +int kmscon_char_append_u8(struct kmscon_char *ch, const char *str, size_t len); + /* console objects */ int kmscon_console_new(struct kmscon_console **out); diff --git a/src/console_char.c b/src/console_char.c new file mode 100644 index 0000000..0ccc452 --- /dev/null +++ b/src/console_char.c @@ -0,0 +1,132 @@ +/* + * kmscon - Console Characters + * Written 2011 by David Herrmann + */ + +/* + * Console Characters + * A console always has a fixed width and height measured in number of + * characters. This interfaces describes a single character. + * + * To be Unicode compatible, the most straightforward way would be using a UCS + * number for each character and printing them. However, Unicode allows + * combining marks, that is, a single printable character is constructed of + * multiple characters. We support this by allowing to append characters to an + * existing character. This should only be used with combining chars, though. + * Otherwise you end up with multiple printable characters in a cell and the + * output may get corrupted. + * + * We store each character (sequence) as UTF8 string because the pango library + * accepts only UTF8. Hence, we avoid conversion to UCS or wide-characters. + */ + +#include +#include +#include + +#include "console.h" + +/* maximum size of a single character */ +#define KMSCON_CHAR_SIZE 6 + +struct kmscon_char { + char *buf; + size_t size; + size_t len; +}; + +int kmscon_char_new(struct kmscon_char **out) +{ + struct kmscon_char *ch; + + if (!out) + return -EINVAL; + + ch = malloc(sizeof(*ch)); + if (!ch) + return -ENOMEM; + + memset(ch, 0, sizeof(*ch)); + + ch->size = KMSCON_CHAR_SIZE; + ch->buf = malloc(ch->size); + if (!ch->buf) { + free(ch); + return -ENOMEM; + } + + memset(ch->buf, 0, ch->size); + + *out = ch; + return 0; +} + +void kmscon_char_free(struct kmscon_char *ch) +{ + if (!ch) + return; + + free(ch->buf); + free(ch); +} + +int kmscon_char_set_u8(struct kmscon_char *ch, const char *str, size_t len) +{ + char *buf; + + if (!ch) + return -EINVAL; + + if (ch->size < len) { + buf = realloc(ch->buf, len); + if (!buf) + return -ENOMEM; + ch->buf = buf; + ch->size = len; + } + + memcpy(ch->buf, str, len); + ch->len = len; + + return 0; +} + +const char *kmscon_char_get_u8(const struct kmscon_char *ch) +{ + if (!ch || !ch->len) + return NULL; + + return ch->buf; +} + +size_t kmscon_char_get_len(const struct kmscon_char *ch) +{ + if (!ch) + return 0; + + return ch->len; +} + +int kmscon_char_append_u8(struct kmscon_char *ch, const char *str, size_t len) +{ + char *buf; + size_t nlen; + + if (!ch) + return -EINVAL; + + nlen = ch->len + len; + + if (ch->size < nlen) { + buf = realloc(ch->buf, nlen); + if (!buf) + return -EINVAL; + ch->buf = buf; + ch->size = nlen; + } + + memcpy(&ch->buf[ch->len], str, len); + ch->len += len; + + return 0; +}