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