|
1 /* Public Domain Curses */ |
|
2 |
|
3 #include <curspriv.h> |
|
4 |
|
5 RCSID("$Id: util.c,v 1.71 2008/07/13 16:08:18 wmcbrine Exp $") |
|
6 |
|
7 /*man-start************************************************************** |
|
8 |
|
9 Name: util |
|
10 |
|
11 Synopsis: |
|
12 char *unctrl(chtype c); |
|
13 void filter(void); |
|
14 void use_env(bool x); |
|
15 int delay_output(int ms); |
|
16 |
|
17 int getcchar(const cchar_t *wcval, wchar_t *wch, attr_t *attrs, |
|
18 short *color_pair, void *opts); |
|
19 int setcchar(cchar_t *wcval, const wchar_t *wch, const attr_t attrs, |
|
20 short color_pair, const void *opts); |
|
21 wchar_t *wunctrl(cchar_t *wc); |
|
22 |
|
23 int PDC_mbtowc(wchar_t *pwc, const char *s, size_t n); |
|
24 size_t PDC_mbstowcs(wchar_t *dest, const char *src, size_t n); |
|
25 size_t PDC_wcstombs(char *dest, const wchar_t *src, size_t n); |
|
26 |
|
27 Description: |
|
28 unctrl() expands the text portion of the chtype c into a |
|
29 printable string. Control characters are changed to the "^X" |
|
30 notation; others are passed through. wunctrl() is the wide- |
|
31 character version of the function. |
|
32 |
|
33 filter() and use_env() are no-ops in PDCurses. |
|
34 |
|
35 delay_output() inserts an ms millisecond pause in output. |
|
36 |
|
37 getcchar() works in two modes: When wch is not NULL, it reads |
|
38 the cchar_t pointed to by wcval and stores the attributes in |
|
39 attrs, the color pair in color_pair, and the text in the |
|
40 wide-character string wch. When wch is NULL, getcchar() merely |
|
41 returns the number of wide characters in wcval. In either mode, |
|
42 the opts argument is unused. |
|
43 |
|
44 setcchar constructs a cchar_t at wcval from the wide-character |
|
45 text at wch, the attributes in attr and the color pair in |
|
46 color_pair. The opts argument is unused. |
|
47 |
|
48 Currently, the length returned by getcchar() is always 1 or 0. |
|
49 Similarly, setcchar() will only take the first wide character |
|
50 from wch, and ignore any others that it "should" take (i.e., |
|
51 combining characters). Nor will it correctly handle any |
|
52 character outside the basic multilingual plane (UCS-2). |
|
53 |
|
54 Return Value: |
|
55 unctrl() and wunctrl() return NULL on failure. delay_output() |
|
56 always returns OK. |
|
57 |
|
58 getcchar() returns the number of wide characters wcval points to |
|
59 when wch is NULL; when it's not, getcchar() returns OK or ERR. |
|
60 |
|
61 setcchar() returns OK or ERR. |
|
62 |
|
63 Portability X/Open BSD SYS V |
|
64 unctrl Y Y Y |
|
65 filter Y - 3.0 |
|
66 use_env Y - 4.0 |
|
67 delay_output Y Y Y |
|
68 getcchar Y |
|
69 setcchar Y |
|
70 wunctrl Y |
|
71 PDC_mbtowc - - - |
|
72 PDC_mbstowcs - - - |
|
73 PDC_wcstombs - - - |
|
74 |
|
75 **man-end****************************************************************/ |
|
76 |
|
77 #ifdef PDC_WIDE |
|
78 # ifdef PDC_FORCE_UTF8 |
|
79 # include <string.h> |
|
80 # else |
|
81 # include <stdlib.h> |
|
82 # endif |
|
83 #endif |
|
84 |
|
85 char *unctrl(chtype c) |
|
86 { |
|
87 static char strbuf[3] = {0, 0, 0}; |
|
88 |
|
89 chtype ic; |
|
90 |
|
91 PDC_LOG(("unctrl() - called\n")); |
|
92 |
|
93 ic = c & A_CHARTEXT; |
|
94 |
|
95 if (ic >= 0x20 && ic != 0x7f) /* normal characters */ |
|
96 { |
|
97 strbuf[0] = (char)ic; |
|
98 strbuf[1] = '\0'; |
|
99 return strbuf; |
|
100 } |
|
101 |
|
102 strbuf[0] = '^'; /* '^' prefix */ |
|
103 |
|
104 if (ic == 0x7f) /* 0x7f == DEL */ |
|
105 strbuf[1] = '?'; |
|
106 else /* other control */ |
|
107 strbuf[1] = (char)(ic + '@'); |
|
108 |
|
109 return strbuf; |
|
110 } |
|
111 |
|
112 void filter(void) |
|
113 { |
|
114 PDC_LOG(("filter() - called\n")); |
|
115 } |
|
116 |
|
117 void use_env(bool x) |
|
118 { |
|
119 PDC_LOG(("use_env() - called: x %d\n", x)); |
|
120 } |
|
121 |
|
122 int delay_output(int ms) |
|
123 { |
|
124 PDC_LOG(("delay_output() - called: ms %d\n", ms)); |
|
125 |
|
126 return napms(ms); |
|
127 } |
|
128 |
|
129 #ifdef PDC_WIDE |
|
130 int getcchar(const cchar_t *wcval, wchar_t *wch, attr_t *attrs, |
|
131 short *color_pair, void *opts) |
|
132 { |
|
133 if (!wcval) |
|
134 return ERR; |
|
135 |
|
136 if (wch) |
|
137 { |
|
138 if (!attrs || !color_pair) |
|
139 return ERR; |
|
140 |
|
141 *wch = (*wcval & A_CHARTEXT); |
|
142 *attrs = (*wcval & (A_ATTRIBUTES & ~A_COLOR)); |
|
143 *color_pair = PAIR_NUMBER(*wcval & A_COLOR); |
|
144 |
|
145 if (*wch) |
|
146 *++wch = L'\0'; |
|
147 |
|
148 return OK; |
|
149 } |
|
150 else |
|
151 return ((*wcval & A_CHARTEXT) != L'\0'); |
|
152 } |
|
153 |
|
154 int setcchar(cchar_t *wcval, const wchar_t *wch, const attr_t attrs, |
|
155 short color_pair, const void *opts) |
|
156 { |
|
157 if (!wcval || !wch) |
|
158 return ERR; |
|
159 |
|
160 *wcval = *wch | attrs | COLOR_PAIR(color_pair); |
|
161 |
|
162 return OK; |
|
163 } |
|
164 |
|
165 wchar_t *wunctrl(cchar_t *wc) |
|
166 { |
|
167 static wchar_t strbuf[3] = {0, 0, 0}; |
|
168 |
|
169 cchar_t ic; |
|
170 |
|
171 PDC_LOG(("wunctrl() - called\n")); |
|
172 |
|
173 ic = *wc & A_CHARTEXT; |
|
174 |
|
175 if (ic >= 0x20 && ic != 0x7f) /* normal characters */ |
|
176 { |
|
177 strbuf[0] = (wchar_t)ic; |
|
178 strbuf[1] = L'\0'; |
|
179 return strbuf; |
|
180 } |
|
181 |
|
182 strbuf[0] = '^'; /* '^' prefix */ |
|
183 |
|
184 if (ic == 0x7f) /* 0x7f == DEL */ |
|
185 strbuf[1] = '?'; |
|
186 else /* other control */ |
|
187 strbuf[1] = (wchar_t)(ic + '@'); |
|
188 |
|
189 return strbuf; |
|
190 } |
|
191 |
|
192 int PDC_mbtowc(wchar_t *pwc, const char *s, size_t n) |
|
193 { |
|
194 # ifdef PDC_FORCE_UTF8 |
|
195 wchar_t key; |
|
196 int i = -1; |
|
197 const unsigned char *string; |
|
198 |
|
199 if (!s || (n < 1)) |
|
200 return -1; |
|
201 |
|
202 if (!*s) |
|
203 return 0; |
|
204 |
|
205 string = (const unsigned char *)s; |
|
206 |
|
207 key = string[0]; |
|
208 |
|
209 /* Simplistic UTF-8 decoder -- only does the BMP, minimal validation */ |
|
210 |
|
211 if (key & 0x80) |
|
212 { |
|
213 if ((key & 0xe0) == 0xc0) |
|
214 { |
|
215 if (1 < n) |
|
216 { |
|
217 key = ((key & 0x1f) << 6) | (string[1] & 0x3f); |
|
218 i = 2; |
|
219 } |
|
220 } |
|
221 else if ((key & 0xe0) == 0xe0) |
|
222 { |
|
223 if (2 < n) |
|
224 { |
|
225 key = ((key & 0x0f) << 12) | ((string[1] & 0x3f) << 6) | |
|
226 (string[2] & 0x3f); |
|
227 i = 3; |
|
228 } |
|
229 } |
|
230 } |
|
231 else |
|
232 i = 1; |
|
233 |
|
234 if (i) |
|
235 *pwc = key; |
|
236 |
|
237 return i; |
|
238 # else |
|
239 return mbtowc(pwc, s, n); |
|
240 # endif |
|
241 } |
|
242 |
|
243 size_t PDC_mbstowcs(wchar_t *dest, const char *src, size_t n) |
|
244 { |
|
245 # ifdef PDC_FORCE_UTF8 |
|
246 size_t i = 0, len; |
|
247 |
|
248 if (!src || !dest) |
|
249 return 0; |
|
250 |
|
251 len = strlen(src); |
|
252 |
|
253 while (*src && i < n) |
|
254 { |
|
255 int retval = PDC_mbtowc(dest + i, src, len); |
|
256 |
|
257 if (retval < 1) |
|
258 return -1; |
|
259 |
|
260 src += retval; |
|
261 len -= retval; |
|
262 i++; |
|
263 } |
|
264 # else |
|
265 size_t i = mbstowcs(dest, src, n); |
|
266 # endif |
|
267 dest[i] = 0; |
|
268 return i; |
|
269 } |
|
270 |
|
271 size_t PDC_wcstombs(char *dest, const wchar_t *src, size_t n) |
|
272 { |
|
273 # ifdef PDC_FORCE_UTF8 |
|
274 size_t i = 0; |
|
275 |
|
276 if (!src || !dest) |
|
277 return 0; |
|
278 |
|
279 while (*src && i < n) |
|
280 { |
|
281 chtype code = *src++; |
|
282 |
|
283 if (code < 0x80) |
|
284 { |
|
285 dest[i] = code; |
|
286 i++; |
|
287 } |
|
288 else |
|
289 if (code < 0x800) |
|
290 { |
|
291 dest[i] = ((code & 0x07c0) >> 6) | 0xc0; |
|
292 dest[i + 1] = (code & 0x003f) | 0x80; |
|
293 i += 2; |
|
294 } |
|
295 else |
|
296 { |
|
297 dest[i] = ((code & 0xf000) >> 12) | 0xe0; |
|
298 dest[i + 1] = ((code & 0x0fc0) >> 6) | 0x80; |
|
299 dest[i + 2] = (code & 0x003f) | 0x80; |
|
300 i += 3; |
|
301 } |
|
302 } |
|
303 # else |
|
304 size_t i = wcstombs(dest, src, n); |
|
305 # endif |
|
306 dest[i] = '\0'; |
|
307 return i; |
|
308 } |
|
309 #endif |