1/****************************************************************************
2 * Copyright 2018,2020 Thomas E. Dickey                                     *
3 * Copyright 2012,2013 Free Software Foundation, Inc.                       *
4 *                                                                          *
5 * Permission is hereby granted, free of charge, to any person obtaining a  *
6 * copy of this software and associated documentation files (the            *
7 * "Software"), to deal in the Software without restriction, including      *
8 * without limitation the rights to use, copy, modify, merge, publish,      *
9 * distribute, distribute with modifications, sublicense, and/or sell       *
10 * copies of the Software, and to permit persons to whom the Software is    *
11 * furnished to do so, subject to the following conditions:                 *
12 *                                                                          *
13 * The above copyright notice and this permission notice shall be included  *
14 * in all copies or substantial portions of the Software.                   *
15 *                                                                          *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23 *                                                                          *
24 * Except as contained in this notice, the name(s) of the above copyright   *
25 * holders shall not be used in advertising or otherwise to promote the     *
26 * sale, use or other dealings in this Software without prior written       *
27 * authorization.                                                           *
28 ****************************************************************************/
29
30#include <curses.priv.h>
31
32#if USE_WIDEC_SUPPORT
33
34MODULE_ID("$Id: widechars.c,v 1.9 2020/08/29 16:22:03 juergen Exp $")
35
36#if (defined(_NC_WINDOWS)) && !defined(_NC_MSC)
37/*
38 * MinGW has wide-character functions, but they do not work correctly.
39 */
40
41int
42_nc_mbtowc(wchar_t *pwc, const char *s, size_t n)
43{
44    int result;
45    int count;
46    int try;
47
48    if (s != 0 && n != 0) {
49	/*
50	 * MultiByteToWideChar() can decide to return more than one
51	 * wide-character.  We want only one.  Ignore any trailing null, both
52	 * in the initial count and in the conversion.
53	 */
54	count = 0;
55	for (try = 1; try <= (int) n; ++try) {
56	    count = MultiByteToWideChar(CP_UTF8,
57					MB_ERR_INVALID_CHARS,
58					s,
59					try,
60					pwc,
61					0);
62	    TR(TRACE_BITS, ("...try %d:%d", try, count));
63	    if (count > 0) {
64		break;
65	    }
66	}
67	if (count < 1 || count > 2) {
68	    result = -1;
69	} else {
70	    wchar_t actual[2];
71	    memset(&actual, 0, sizeof(actual));
72	    count = MultiByteToWideChar(CP_UTF8,
73					MB_ERR_INVALID_CHARS,
74					s,
75					try,
76					actual,
77					2);
78	    TR(TRACE_BITS, ("\twin32 ->%#x, %#x", actual[0], actual[1]));
79	    *pwc = actual[0];
80	    if (actual[1] != 0)
81		result = -1;
82	    else
83		result = try;
84	}
85    } else {
86	result = 0;
87    }
88
89    return result;
90}
91
92int
93_nc_mblen(const char *s, size_t n)
94{
95    int result = -1;
96    int count;
97    wchar_t temp;
98
99    if (s != 0 && n != 0) {
100	count = _nc_mbtowc(&temp, s, n);
101	if (count == 1) {
102	    int check = WideCharToMultiByte(CP_UTF8,
103					    0,
104					    &temp,
105					    1,
106					    NULL,
107					    0,	/* compute length only */
108					    NULL,
109					    NULL);
110	    TR(TRACE_BITS, ("\tcheck ->%d\n", check));
111	    if (check > 0 && (size_t) check <= n) {
112		result = check;
113	    }
114	}
115    } else {
116	result = 0;
117    }
118
119    return result;
120}
121
122int __MINGW_NOTHROW
123_nc_wctomb(char *s, wchar_t wc)
124{
125    int result;
126    int check;
127
128    check = WideCharToMultiByte(CP_UTF8,
129				0,
130				&wc,
131				1,
132				NULL,
133				0,	/* compute length only */
134				NULL,
135				NULL);
136    if (check > 0) {
137	result = WideCharToMultiByte(CP_UTF8,
138				     0,
139				     &wc,
140				     1,
141				     s,
142				     check + 1,
143				     NULL,
144				     NULL);
145    } else {
146	result = -1;
147    }
148    return result;
149}
150
151#endif /* _NC_WINDOWS */
152
153#endif /* USE_WIDEC_SUPPORT */
154