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 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