#include <fcntl.h>
#include <limits.h>
#include <pwd.h>
+#include <signal.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <signal.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/types.h>
typedef struct {
Glyph attr; /* current char attributes */
- int x; /* terminal column */
- int y; /* terminal row */
+ int x;
+ int y;
char state;
} TCursor;
return utfbyte[i] | (u & ~utfmask[i]);
}
+// ./list-emojis <libgrapheme/data/emoji-data.txt >emojis.c.in
+#include "emojis.c.in"
+
+static int
+uint32comparator(const void *a, const void *b)
+{
+ return *(uint32_t *)a - *(uint32_t *)b;
+}
+
+int
+isEmoji(const Rune u)
+{
+ const uint32_t want = (uint32_t)u;
+ return bsearch(
+ &want,
+ emojis,
+ (sizeof emojis)/sizeof(uint32_t),
+ sizeof(uint32_t),
+ uint32comparator) != NULL;
+}
+
size_t
utf8validate(Rune *u, size_t i)
{
- if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
+ if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF) || isEmoji(*u))
*u = UTF_INVALID;
for (i = 1; *u > utfmax[i]; ++i)
;
{
char *p = csiescseq.buf, *np;
long int v;
+ int sep = ';'; /* colon or semi-colon, but not both */
csiescseq.narg = 0;
if (*p == '?') {
v = -1;
csiescseq.arg[csiescseq.narg++] = v;
p = np;
- if (*p != ';' || csiescseq.narg == ESC_ARG_SIZ)
+ if (sep == ';' && *p == ':')
+ sep = ':'; /* allow override to colon once */
+ if (*p != sep || csiescseq.narg == ESC_ARG_SIZ)
break;
p++;
}
}
break;
case 1: /* above */
- if (term.c.y > 1)
+ if (term.c.y > 0)
tclearregion(0, 0, term.col-1, term.c.y-1);
tclearregion(0, term.c.y, term.c.x, term.c.y);
break;
tcursor(CURSOR_SAVE);
break;
case 'u': /* DECRC -- Restore cursor position (ANSI.SYS) */
- tcursor(CURSOR_LOAD);
+ if (csiescseq.priv) {
+ goto unknown;
+ } else {
+ tcursor(CURSOR_LOAD);
+ }
break;
case ' ':
switch (csiescseq.mode[1]) {
void
tcontrolcode(uchar ascii)
{
- size_t i;
-
switch (ascii) {
case '\t': /* HT */
tputtab(1);
return;
case '\b': /* BS */
- for (i = 1; term.c.x && term.line[term.c.y][term.c.x - i].u == 0; ++i)
- ;
- tmoveto(term.c.x - i, term.c.y);
+ tmoveto(term.c.x-1, term.c.y);
return;
case '\r': /* CR */
tmoveto(0, term.c.y);