1 /* $OpenBSD: utf8.c,v 1.1 2016/01/10 14:04:16 schwarze Exp $ */
2
3 /*
4 * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * witH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <ctype.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <vis.h>
24 #include <wchar.h>
25
26 int
mbswprint(const char * mbs,int maxwidth,int trail)27 mbswprint(const char *mbs, int maxwidth, int trail)
28 {
29 char buf[5];
30 wchar_t wc;
31 int len; /* length in bytes of UTF-8 encoded string */
32 int width; /* display width of a single Unicode char */
33 int total_width; /* display width of what is printed */
34
35 total_width = 0;
36 while (*mbs != '\0' && total_width < maxwidth) {
37 len = mbtowc(&wc, mbs, MB_CUR_MAX);
38 if (len == -1) {
39 (void)mbtowc(NULL, NULL, MB_CUR_MAX);
40 len = 1;
41 }
42 if (len == 1)
43 width = vis(buf, mbs[0],
44 VIS_TAB | VIS_NL | VIS_CSTYLE, mbs[1]) - buf;
45 else if ((width = wcwidth(wc)) == -1) {
46 /* U+FFFD replacement character */
47 memcpy(buf, "\357\277\275\0", 4);
48 width = 1;
49 } else {
50 memcpy(buf, mbs, len);
51 buf[len] = '\0';
52 }
53 if (total_width + width > maxwidth)
54 break;
55 fputs(buf, stdout);
56 total_width += width;
57 mbs += len;
58 }
59 if (trail)
60 while (total_width++ < maxwidth)
61 putchar(' ');
62 return total_width;
63 }
64