+ exit(EXIT_FAILURE);
+}
+
+static int
+ch_len(chtype * src)
+{
+ int result = 0;
+ while (*src++)
+ result++;
+ return result;
+}
+
+/*
+ * Allocate a string into an array of chtype's. If UTF-8 mode is
+ * active, translate the string accordingly.
+ */
+static chtype *
+ch_dup(char *src)
+{
+ unsigned len = strlen(src);
+ chtype *dst = typeMalloc(chtype, len + 1);
+ unsigned j, k;
+ unsigned utf_count = 0;
+ unsigned utf_char = 0;
+
+#define UCS_REPL 0xfffd
+
+ for (j = k = 0; j < len; j++) {
+ if (utf8_mode) {
+ unsigned c = src[j] & 0xff;
+ /* Combine UTF-8 into Unicode */
+ if (c < 0x80) {
+ /* We received an ASCII character */
+ if (utf_count > 0)
+ dst[k++] = UCS_REPL; /* prev. sequence incomplete */
+ dst[k++] = c;
+ utf_count = 0;
+ } else if (c < 0xc0) {
+ /* We received a continuation byte */
+ if (utf_count < 1) {
+ dst[k++] = UCS_REPL; /* ... unexpectedly */
+ } else {
+ if (!utf_char && !((c & 0x7f) >> (7 - utf_count))) {
+ utf_char = UCS_REPL;
+ }
+ /* characters outside UCS-2 become UCS_REPL */
+ if (utf_char > 0x03ff) {
+ /* value would be >0xffff */
+ utf_char = UCS_REPL;
+ } else {
+ utf_char <<= 6;
+ utf_char |= (c & 0x3f);
+ }
+ utf_count--;
+ if (utf_count == 0)
+ dst[k++] = utf_char;
+ }
+ } else {
+ /* We received a sequence start byte */
+ if (utf_count > 0)
+ dst[k++] = UCS_REPL; /* prev. sequence incomplete */
+ if (c < 0xe0) {
+ utf_count = 1;
+ utf_char = (c & 0x1f);
+ if (!(c & 0x1e))
+ utf_char = UCS_REPL; /* overlong sequence */
+ } else if (c < 0xf0) {
+ utf_count = 2;
+ utf_char = (c & 0x0f);
+ } else if (c < 0xf8) {
+ utf_count = 3;
+ utf_char = (c & 0x07);
+ } else if (c < 0xfc) {
+ utf_count = 4;
+ utf_char = (c & 0x03);
+ } else if (c < 0xfe) {
+ utf_count = 5;
+ utf_char = (c & 0x01);
+ } else {
+ dst[k++] = UCS_REPL;
+ utf_count = 0;
+ }
+ }
+ } else {
+ dst[k++] = src[j];
+ }
+ }
+ dst[k] = 0;
+ return dst;