1*0a6a1f1dSLionel Sambuc /* $NetBSD: chartype.c,v 1.12 2015/02/22 02:16:19 christos Exp $ */
23e1db26aSLionel Sambuc
33e1db26aSLionel Sambuc /*-
43e1db26aSLionel Sambuc * Copyright (c) 2009 The NetBSD Foundation, Inc.
53e1db26aSLionel Sambuc * All rights reserved.
63e1db26aSLionel Sambuc *
73e1db26aSLionel Sambuc * Redistribution and use in source and binary forms, with or without
83e1db26aSLionel Sambuc * modification, are permitted provided that the following conditions
93e1db26aSLionel Sambuc * are met:
103e1db26aSLionel Sambuc * 1. Redistributions of source code must retain the above copyright
113e1db26aSLionel Sambuc * notice, this list of conditions and the following disclaimer.
123e1db26aSLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
133e1db26aSLionel Sambuc * notice, this list of conditions and the following disclaimer in the
143e1db26aSLionel Sambuc * documentation and/or other materials provided with the distribution.
153e1db26aSLionel Sambuc * 3. All advertising materials mentioning features or use of this software
163e1db26aSLionel Sambuc * must display the following acknowledgement:
173e1db26aSLionel Sambuc * This product includes software developed by the NetBSD
183e1db26aSLionel Sambuc * Foundation, Inc. and its contributors.
193e1db26aSLionel Sambuc * 4. Neither the name of The NetBSD Foundation nor the names of its
203e1db26aSLionel Sambuc * contributors may be used to endorse or promote products derived
213e1db26aSLionel Sambuc * from this software without specific prior written permission.
223e1db26aSLionel Sambuc *
233e1db26aSLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
243e1db26aSLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
253e1db26aSLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
263e1db26aSLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
273e1db26aSLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
283e1db26aSLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
293e1db26aSLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
303e1db26aSLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
313e1db26aSLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
323e1db26aSLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
333e1db26aSLionel Sambuc * POSSIBILITY OF SUCH DAMAGE.
343e1db26aSLionel Sambuc */
353e1db26aSLionel Sambuc
363e1db26aSLionel Sambuc /*
373e1db26aSLionel Sambuc * chartype.c: character classification and meta information
383e1db26aSLionel Sambuc */
393e1db26aSLionel Sambuc #include "config.h"
403e1db26aSLionel Sambuc #if !defined(lint) && !defined(SCCSID)
41*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: chartype.c,v 1.12 2015/02/22 02:16:19 christos Exp $");
423e1db26aSLionel Sambuc #endif /* not lint && not SCCSID */
433e1db26aSLionel Sambuc #include "el.h"
443e1db26aSLionel Sambuc #include <stdlib.h>
453e1db26aSLionel Sambuc
463e1db26aSLionel Sambuc #define CT_BUFSIZ ((size_t)1024)
473e1db26aSLionel Sambuc
483e1db26aSLionel Sambuc #ifdef WIDECHAR
49*0a6a1f1dSLionel Sambuc protected int
ct_conv_cbuff_resize(ct_buffer_t * conv,size_t csize)50*0a6a1f1dSLionel Sambuc ct_conv_cbuff_resize(ct_buffer_t *conv, size_t csize)
513e1db26aSLionel Sambuc {
523e1db26aSLionel Sambuc void *p;
53*0a6a1f1dSLionel Sambuc
54*0a6a1f1dSLionel Sambuc if (csize <= conv->csize)
55*0a6a1f1dSLionel Sambuc return 0;
56*0a6a1f1dSLionel Sambuc
57*0a6a1f1dSLionel Sambuc conv->csize = csize;
58*0a6a1f1dSLionel Sambuc
593e1db26aSLionel Sambuc p = el_realloc(conv->cbuff, conv->csize * sizeof(*conv->cbuff));
603e1db26aSLionel Sambuc if (p == NULL) {
613e1db26aSLionel Sambuc conv->csize = 0;
623e1db26aSLionel Sambuc el_free(conv->cbuff);
633e1db26aSLionel Sambuc conv->cbuff = NULL;
64*0a6a1f1dSLionel Sambuc return -1;
65*0a6a1f1dSLionel Sambuc }
663e1db26aSLionel Sambuc conv->cbuff = p;
67*0a6a1f1dSLionel Sambuc return 0;
683e1db26aSLionel Sambuc }
693e1db26aSLionel Sambuc
70*0a6a1f1dSLionel Sambuc protected int
ct_conv_wbuff_resize(ct_buffer_t * conv,size_t wsize)71*0a6a1f1dSLionel Sambuc ct_conv_wbuff_resize(ct_buffer_t *conv, size_t wsize)
72*0a6a1f1dSLionel Sambuc {
73*0a6a1f1dSLionel Sambuc void *p;
74*0a6a1f1dSLionel Sambuc
75*0a6a1f1dSLionel Sambuc if (wsize <= conv->wsize)
76*0a6a1f1dSLionel Sambuc return 0;
77*0a6a1f1dSLionel Sambuc
78*0a6a1f1dSLionel Sambuc conv->wsize = wsize;
79*0a6a1f1dSLionel Sambuc
803e1db26aSLionel Sambuc p = el_realloc(conv->wbuff, conv->wsize * sizeof(*conv->wbuff));
813e1db26aSLionel Sambuc if (p == NULL) {
823e1db26aSLionel Sambuc conv->wsize = 0;
833e1db26aSLionel Sambuc el_free(conv->wbuff);
843e1db26aSLionel Sambuc conv->wbuff = NULL;
85*0a6a1f1dSLionel Sambuc return -1;
863e1db26aSLionel Sambuc }
87*0a6a1f1dSLionel Sambuc conv->wbuff = p;
88*0a6a1f1dSLionel Sambuc return 0;
893e1db26aSLionel Sambuc }
903e1db26aSLionel Sambuc
913e1db26aSLionel Sambuc
923e1db26aSLionel Sambuc public char *
ct_encode_string(const Char * s,ct_buffer_t * conv)933e1db26aSLionel Sambuc ct_encode_string(const Char *s, ct_buffer_t *conv)
943e1db26aSLionel Sambuc {
953e1db26aSLionel Sambuc char *dst;
96*0a6a1f1dSLionel Sambuc ssize_t used;
973e1db26aSLionel Sambuc
983e1db26aSLionel Sambuc if (!s)
993e1db26aSLionel Sambuc return NULL;
1003e1db26aSLionel Sambuc
1013e1db26aSLionel Sambuc dst = conv->cbuff;
102*0a6a1f1dSLionel Sambuc for (;;) {
103*0a6a1f1dSLionel Sambuc used = (ssize_t)(dst - conv->cbuff);
104*0a6a1f1dSLionel Sambuc if ((conv->csize - (size_t)used) < 5) {
105*0a6a1f1dSLionel Sambuc if (ct_conv_cbuff_resize(conv,
106*0a6a1f1dSLionel Sambuc conv->csize + CT_BUFSIZ) == -1)
1073e1db26aSLionel Sambuc return NULL;
1083e1db26aSLionel Sambuc dst = conv->cbuff + used;
1093e1db26aSLionel Sambuc }
110*0a6a1f1dSLionel Sambuc if (!*s)
111*0a6a1f1dSLionel Sambuc break;
1123e1db26aSLionel Sambuc used = ct_encode_char(dst, (size_t)5, *s);
1133e1db26aSLionel Sambuc if (used == -1) /* failed to encode, need more buffer space */
1143e1db26aSLionel Sambuc abort();
1153e1db26aSLionel Sambuc ++s;
1163e1db26aSLionel Sambuc dst += used;
1173e1db26aSLionel Sambuc }
1183e1db26aSLionel Sambuc *dst = '\0';
1193e1db26aSLionel Sambuc return conv->cbuff;
1203e1db26aSLionel Sambuc }
1213e1db26aSLionel Sambuc
1223e1db26aSLionel Sambuc public Char *
ct_decode_string(const char * s,ct_buffer_t * conv)1233e1db26aSLionel Sambuc ct_decode_string(const char *s, ct_buffer_t *conv)
1243e1db26aSLionel Sambuc {
125*0a6a1f1dSLionel Sambuc size_t len;
1263e1db26aSLionel Sambuc
1273e1db26aSLionel Sambuc if (!s)
1283e1db26aSLionel Sambuc return NULL;
1293e1db26aSLionel Sambuc
1303e1db26aSLionel Sambuc len = ct_mbstowcs(NULL, s, (size_t)0);
1313e1db26aSLionel Sambuc if (len == (size_t)-1)
1323e1db26aSLionel Sambuc return NULL;
133*0a6a1f1dSLionel Sambuc
134*0a6a1f1dSLionel Sambuc if (conv->wsize < ++len)
135*0a6a1f1dSLionel Sambuc if (ct_conv_wbuff_resize(conv, len + CT_BUFSIZ) == -1)
1363e1db26aSLionel Sambuc return NULL;
137*0a6a1f1dSLionel Sambuc
1383e1db26aSLionel Sambuc ct_mbstowcs(conv->wbuff, s, conv->wsize);
1393e1db26aSLionel Sambuc return conv->wbuff;
1403e1db26aSLionel Sambuc }
1413e1db26aSLionel Sambuc
1423e1db26aSLionel Sambuc
1433e1db26aSLionel Sambuc protected Char **
ct_decode_argv(int argc,const char * argv[],ct_buffer_t * conv)1443e1db26aSLionel Sambuc ct_decode_argv(int argc, const char *argv[], ct_buffer_t *conv)
1453e1db26aSLionel Sambuc {
1463e1db26aSLionel Sambuc size_t bufspace;
1473e1db26aSLionel Sambuc int i;
1483e1db26aSLionel Sambuc Char *p;
1493e1db26aSLionel Sambuc Char **wargv;
1503e1db26aSLionel Sambuc ssize_t bytes;
1513e1db26aSLionel Sambuc
1523e1db26aSLionel Sambuc /* Make sure we have enough space in the conversion buffer to store all
1533e1db26aSLionel Sambuc * the argv strings. */
1543e1db26aSLionel Sambuc for (i = 0, bufspace = 0; i < argc; ++i)
1553e1db26aSLionel Sambuc bufspace += argv[i] ? strlen(argv[i]) + 1 : 0;
156*0a6a1f1dSLionel Sambuc if (conv->wsize < ++bufspace)
157*0a6a1f1dSLionel Sambuc if (ct_conv_wbuff_resize(conv, bufspace + CT_BUFSIZ) == -1)
1583e1db26aSLionel Sambuc return NULL;
1593e1db26aSLionel Sambuc
1603e1db26aSLionel Sambuc wargv = el_malloc((size_t)argc * sizeof(*wargv));
1613e1db26aSLionel Sambuc
1623e1db26aSLionel Sambuc for (i = 0, p = conv->wbuff; i < argc; ++i) {
1633e1db26aSLionel Sambuc if (!argv[i]) { /* don't pass null pointers to mbstowcs */
1643e1db26aSLionel Sambuc wargv[i] = NULL;
1653e1db26aSLionel Sambuc continue;
1663e1db26aSLionel Sambuc } else {
1673e1db26aSLionel Sambuc wargv[i] = p;
1683e1db26aSLionel Sambuc bytes = (ssize_t)mbstowcs(p, argv[i], bufspace);
1693e1db26aSLionel Sambuc }
1703e1db26aSLionel Sambuc if (bytes == -1) {
1713e1db26aSLionel Sambuc el_free(wargv);
1723e1db26aSLionel Sambuc return NULL;
1733e1db26aSLionel Sambuc } else
1743e1db26aSLionel Sambuc bytes++; /* include '\0' in the count */
1753e1db26aSLionel Sambuc bufspace -= (size_t)bytes;
1763e1db26aSLionel Sambuc p += bytes;
1773e1db26aSLionel Sambuc }
1783e1db26aSLionel Sambuc
1793e1db26aSLionel Sambuc return wargv;
1803e1db26aSLionel Sambuc }
1813e1db26aSLionel Sambuc
1823e1db26aSLionel Sambuc
1833e1db26aSLionel Sambuc protected size_t
ct_enc_width(Char c)1843e1db26aSLionel Sambuc ct_enc_width(Char c)
1853e1db26aSLionel Sambuc {
1863e1db26aSLionel Sambuc /* UTF-8 encoding specific values */
1873e1db26aSLionel Sambuc if (c < 0x80)
1883e1db26aSLionel Sambuc return 1;
1893e1db26aSLionel Sambuc else if (c < 0x0800)
1903e1db26aSLionel Sambuc return 2;
1913e1db26aSLionel Sambuc else if (c < 0x10000)
1923e1db26aSLionel Sambuc return 3;
1933e1db26aSLionel Sambuc else if (c < 0x110000)
1943e1db26aSLionel Sambuc return 4;
1953e1db26aSLionel Sambuc else
1963e1db26aSLionel Sambuc return 0; /* not a valid codepoint */
1973e1db26aSLionel Sambuc }
1983e1db26aSLionel Sambuc
1993e1db26aSLionel Sambuc protected ssize_t
ct_encode_char(char * dst,size_t len,Char c)2003e1db26aSLionel Sambuc ct_encode_char(char *dst, size_t len, Char c)
2013e1db26aSLionel Sambuc {
2023e1db26aSLionel Sambuc ssize_t l = 0;
2033e1db26aSLionel Sambuc if (len < ct_enc_width(c))
2043e1db26aSLionel Sambuc return -1;
2053e1db26aSLionel Sambuc l = ct_wctomb(dst, c);
2063e1db26aSLionel Sambuc
2073e1db26aSLionel Sambuc if (l < 0) {
2083e1db26aSLionel Sambuc ct_wctomb_reset;
2093e1db26aSLionel Sambuc l = 0;
2103e1db26aSLionel Sambuc }
2113e1db26aSLionel Sambuc return l;
2123e1db26aSLionel Sambuc }
2133e1db26aSLionel Sambuc #endif
2143e1db26aSLionel Sambuc
2153e1db26aSLionel Sambuc protected const Char *
ct_visual_string(const Char * s)2163e1db26aSLionel Sambuc ct_visual_string(const Char *s)
2173e1db26aSLionel Sambuc {
2183e1db26aSLionel Sambuc static Char *buff = NULL;
2193e1db26aSLionel Sambuc static size_t buffsize = 0;
2203e1db26aSLionel Sambuc void *p;
2213e1db26aSLionel Sambuc Char *dst;
2223e1db26aSLionel Sambuc ssize_t used = 0;
2233e1db26aSLionel Sambuc
2243e1db26aSLionel Sambuc if (!s)
2253e1db26aSLionel Sambuc return NULL;
2263e1db26aSLionel Sambuc if (!buff) {
2273e1db26aSLionel Sambuc buffsize = CT_BUFSIZ;
2283e1db26aSLionel Sambuc buff = el_malloc(buffsize * sizeof(*buff));
2293e1db26aSLionel Sambuc }
2303e1db26aSLionel Sambuc dst = buff;
2313e1db26aSLionel Sambuc while (*s) {
2323e1db26aSLionel Sambuc used = ct_visual_char(dst, buffsize - (size_t)(dst - buff), *s);
2333e1db26aSLionel Sambuc if (used == -1) { /* failed to encode, need more buffer space */
2343e1db26aSLionel Sambuc used = dst - buff;
2353e1db26aSLionel Sambuc buffsize += CT_BUFSIZ;
2363e1db26aSLionel Sambuc p = el_realloc(buff, buffsize * sizeof(*buff));
2373e1db26aSLionel Sambuc if (p == NULL)
2383e1db26aSLionel Sambuc goto out;
2393e1db26aSLionel Sambuc buff = p;
2403e1db26aSLionel Sambuc dst = buff + used;
2413e1db26aSLionel Sambuc /* don't increment s here - we want to retry it! */
2423e1db26aSLionel Sambuc }
2433e1db26aSLionel Sambuc else
2443e1db26aSLionel Sambuc ++s;
2453e1db26aSLionel Sambuc dst += used;
2463e1db26aSLionel Sambuc }
2473e1db26aSLionel Sambuc if (dst >= (buff + buffsize)) { /* sigh */
2483e1db26aSLionel Sambuc buffsize += 1;
2493e1db26aSLionel Sambuc p = el_realloc(buff, buffsize * sizeof(*buff));
2503e1db26aSLionel Sambuc if (p == NULL)
2513e1db26aSLionel Sambuc goto out;
2523e1db26aSLionel Sambuc buff = p;
2533e1db26aSLionel Sambuc dst = buff + buffsize - 1;
2543e1db26aSLionel Sambuc }
2553e1db26aSLionel Sambuc *dst = 0;
2563e1db26aSLionel Sambuc return buff;
2573e1db26aSLionel Sambuc out:
2583e1db26aSLionel Sambuc el_free(buff);
2593e1db26aSLionel Sambuc buffsize = 0;
2603e1db26aSLionel Sambuc return NULL;
2613e1db26aSLionel Sambuc }
2623e1db26aSLionel Sambuc
2633e1db26aSLionel Sambuc
2643e1db26aSLionel Sambuc
2653e1db26aSLionel Sambuc protected int
ct_visual_width(Char c)2663e1db26aSLionel Sambuc ct_visual_width(Char c)
2673e1db26aSLionel Sambuc {
2683e1db26aSLionel Sambuc int t = ct_chr_class(c);
2693e1db26aSLionel Sambuc switch (t) {
2703e1db26aSLionel Sambuc case CHTYPE_ASCIICTL:
2713e1db26aSLionel Sambuc return 2; /* ^@ ^? etc. */
2723e1db26aSLionel Sambuc case CHTYPE_TAB:
2733e1db26aSLionel Sambuc return 1; /* Hmm, this really need to be handled outside! */
2743e1db26aSLionel Sambuc case CHTYPE_NL:
2753e1db26aSLionel Sambuc return 0; /* Should this be 1 instead? */
2763e1db26aSLionel Sambuc #ifdef WIDECHAR
2773e1db26aSLionel Sambuc case CHTYPE_PRINT:
2783e1db26aSLionel Sambuc return wcwidth(c);
2793e1db26aSLionel Sambuc case CHTYPE_NONPRINT:
2803e1db26aSLionel Sambuc if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */
2813e1db26aSLionel Sambuc return 8; /* \U+12345 */
2823e1db26aSLionel Sambuc else
2833e1db26aSLionel Sambuc return 7; /* \U+1234 */
2843e1db26aSLionel Sambuc #else
2853e1db26aSLionel Sambuc case CHTYPE_PRINT:
2863e1db26aSLionel Sambuc return 1;
2873e1db26aSLionel Sambuc case CHTYPE_NONPRINT:
2883e1db26aSLionel Sambuc return 4; /* \123 */
2893e1db26aSLionel Sambuc #endif
2903e1db26aSLionel Sambuc default:
2913e1db26aSLionel Sambuc return 0; /* should not happen */
2923e1db26aSLionel Sambuc }
2933e1db26aSLionel Sambuc }
2943e1db26aSLionel Sambuc
2953e1db26aSLionel Sambuc
2963e1db26aSLionel Sambuc protected ssize_t
ct_visual_char(Char * dst,size_t len,Char c)2973e1db26aSLionel Sambuc ct_visual_char(Char *dst, size_t len, Char c)
2983e1db26aSLionel Sambuc {
2993e1db26aSLionel Sambuc int t = ct_chr_class(c);
3003e1db26aSLionel Sambuc switch (t) {
3013e1db26aSLionel Sambuc case CHTYPE_TAB:
3023e1db26aSLionel Sambuc case CHTYPE_NL:
3033e1db26aSLionel Sambuc case CHTYPE_ASCIICTL:
3043e1db26aSLionel Sambuc if (len < 2)
3053e1db26aSLionel Sambuc return -1; /* insufficient space */
3063e1db26aSLionel Sambuc *dst++ = '^';
3073e1db26aSLionel Sambuc if (c == '\177')
3083e1db26aSLionel Sambuc *dst = '?'; /* DEL -> ^? */
3093e1db26aSLionel Sambuc else
3103e1db26aSLionel Sambuc *dst = c | 0100; /* uncontrolify it */
3113e1db26aSLionel Sambuc return 2;
3123e1db26aSLionel Sambuc case CHTYPE_PRINT:
3133e1db26aSLionel Sambuc if (len < 1)
3143e1db26aSLionel Sambuc return -1; /* insufficient space */
3153e1db26aSLionel Sambuc *dst = c;
3163e1db26aSLionel Sambuc return 1;
3173e1db26aSLionel Sambuc case CHTYPE_NONPRINT:
3183e1db26aSLionel Sambuc /* we only use single-width glyphs for display,
3193e1db26aSLionel Sambuc * so this is right */
3203e1db26aSLionel Sambuc if ((ssize_t)len < ct_visual_width(c))
3213e1db26aSLionel Sambuc return -1; /* insufficient space */
3223e1db26aSLionel Sambuc #ifdef WIDECHAR
3233e1db26aSLionel Sambuc *dst++ = '\\';
3243e1db26aSLionel Sambuc *dst++ = 'U';
3253e1db26aSLionel Sambuc *dst++ = '+';
3263e1db26aSLionel Sambuc #define tohexdigit(v) "0123456789ABCDEF"[v]
3273e1db26aSLionel Sambuc if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */
3283e1db26aSLionel Sambuc *dst++ = tohexdigit(((unsigned int) c >> 16) & 0xf);
3293e1db26aSLionel Sambuc *dst++ = tohexdigit(((unsigned int) c >> 12) & 0xf);
3303e1db26aSLionel Sambuc *dst++ = tohexdigit(((unsigned int) c >> 8) & 0xf);
3313e1db26aSLionel Sambuc *dst++ = tohexdigit(((unsigned int) c >> 4) & 0xf);
3323e1db26aSLionel Sambuc *dst = tohexdigit(((unsigned int) c ) & 0xf);
3333e1db26aSLionel Sambuc return c > 0xffff ? 8 : 7;
3343e1db26aSLionel Sambuc #else
3353e1db26aSLionel Sambuc *dst++ = '\\';
3363e1db26aSLionel Sambuc #define tooctaldigit(v) ((v) + '0')
3373e1db26aSLionel Sambuc *dst++ = tooctaldigit(((unsigned int) c >> 6) & 0x7);
3383e1db26aSLionel Sambuc *dst++ = tooctaldigit(((unsigned int) c >> 3) & 0x7);
3393e1db26aSLionel Sambuc *dst++ = tooctaldigit(((unsigned int) c ) & 0x7);
3403e1db26aSLionel Sambuc #endif
3413e1db26aSLionel Sambuc /*FALLTHROUGH*/
3423e1db26aSLionel Sambuc /* these two should be handled outside this function */
3433e1db26aSLionel Sambuc default: /* we should never hit the default */
3443e1db26aSLionel Sambuc return 0;
3453e1db26aSLionel Sambuc }
3463e1db26aSLionel Sambuc }
3473e1db26aSLionel Sambuc
3483e1db26aSLionel Sambuc
3493e1db26aSLionel Sambuc
3503e1db26aSLionel Sambuc
3513e1db26aSLionel Sambuc protected int
ct_chr_class(Char c)3523e1db26aSLionel Sambuc ct_chr_class(Char c)
3533e1db26aSLionel Sambuc {
3543e1db26aSLionel Sambuc if (c == '\t')
3553e1db26aSLionel Sambuc return CHTYPE_TAB;
3563e1db26aSLionel Sambuc else if (c == '\n')
3573e1db26aSLionel Sambuc return CHTYPE_NL;
3583e1db26aSLionel Sambuc else if (IsASCII(c) && Iscntrl(c))
3593e1db26aSLionel Sambuc return CHTYPE_ASCIICTL;
3603e1db26aSLionel Sambuc else if (Isprint(c))
3613e1db26aSLionel Sambuc return CHTYPE_PRINT;
3623e1db26aSLionel Sambuc else
3633e1db26aSLionel Sambuc return CHTYPE_NONPRINT;
3643e1db26aSLionel Sambuc }
365