ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/misc.C
Revision: 1.60
Committed: Thu May 13 19:40:19 2021 UTC (3 years ago) by sf-exg
Content type: text/plain
Branch: MAIN
CVS Tags: rxvt-unicode-rel-9_29, rxvt-unicode-rel-9_26, rxvt-unicode-rel-9_25, rxvt-unicode-rel-9_30, HEAD
Changes since 1.59: +9 -17 lines
Log Message:
Require C++11

File Contents

# Content
1 /*----------------------------------------------------------------------*
2 * File: misc.C
3 *----------------------------------------------------------------------*
4 *
5 * All portions of code are copyright by their respective author/s.
6 * Copyright (c) 1996 mj olesen <olesen@me.QueensU.CA> Queen's Univ at Kingston
7 * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
8 * Copyright (c) 1998-2000 Geoff Wing <gcw@pobox.com>
9 * Copyright (c) 2003-2006 Marc Lehmann <schmorp@schmorp.de>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *----------------------------------------------------------------------*/
25
26 #include "../config.h" /* NECESSARY */
27 #include "rxvt.h" /* NECESSARY */
28
29 #include <new>
30
31 // alas new/delete cannot be specified as inline in C++11 (see 17.6.4.6)
32 void *
33 operator new (size_t s)
34 {
35 return rxvt_malloc (s);
36 }
37
38 void
39 operator delete (void *p) noexcept
40 {
41 free (p);
42 }
43
44 char *
45 rxvt_wcstombs (const wchar_t *str, int len)
46 {
47 if (len < 0) len = wcslen (str);
48
49 mbstate mbs;
50 char *r = (char *)rxvt_malloc (len * MB_CUR_MAX + 1);
51
52 char *dst = r;
53 while (len--)
54 {
55 ssize_t l = wcrtomb (dst, *str++, mbs);
56
57 if (l < 0)
58 {
59 *dst++ = '?';
60 wcrtomb (0, 0, mbs); // reset undefined state
61 }
62 else
63 dst += l;
64 }
65
66 *dst++ = 0;
67
68 return (char *)rxvt_realloc (r, dst - r);
69 }
70
71 wchar_t *
72 rxvt_mbstowcs (const char *str, int len)
73 {
74 if (len < 0) len = strlen (str);
75
76 wchar_t *r = (wchar_t *)rxvt_malloc ((len + 1) * sizeof (wchar_t));
77
78 if ((ssize_t)mbstowcs (r, str, len + 1) < 0)
79 *r = 0;
80
81 return r;
82 }
83
84 char *
85 rxvt_wcstoutf8 (const wchar_t *str, int len)
86 {
87 if (len < 0) len = wcslen (str);
88
89 char *r = (char *)rxvt_malloc (len * 4 + 1);
90 char *p = r;
91
92 while (len--)
93 {
94 unicode_t w = *str++ & UNICODE_MASK;
95
96 if (w < 0x000080)
97 *p++ = w;
98 else if (w < 0x000800)
99 *p++ = 0xc0 | ( w >> 6),
100 *p++ = 0x80 | ( w & 0x3f);
101 else if (w < 0x010000)
102 *p++ = 0xe0 | ( w >> 12),
103 *p++ = 0x80 | ((w >> 6) & 0x3f),
104 *p++ = 0x80 | ( w & 0x3f);
105 else if (w < 0x110000)
106 *p++ = 0xf0 | ( w >> 18),
107 *p++ = 0x80 | ((w >> 12) & 0x3f),
108 *p++ = 0x80 | ((w >> 6) & 0x3f),
109 *p++ = 0x80 | ( w & 0x3f);
110 else
111 *p++ = '?';
112 }
113
114 *p++ = 0;
115
116 return (char *)rxvt_realloc (r, p - r);
117 }
118
119 wchar_t *
120 rxvt_utf8towcs (const char *str, int len)
121 {
122 if (len < 0) len = strlen (str);
123
124 wchar_t *r = (wchar_t *)rxvt_malloc ((len + 1) * sizeof (wchar_t)),
125 *p = r;
126
127 unsigned char *s = (unsigned char *)str,
128 *e = s + len;
129
130 for (;;)
131 {
132 len = e - s;
133
134 if (len == 0)
135 break;
136 else if (s[0] < 0x80)
137 *p++ = *s++;
138 else if (len >= 2
139 && s[0] >= 0xc2 && s[0] <= 0xdf
140 && (s[1] & 0xc0) == 0x80)
141 {
142 *p++ = ((s[0] & 0x1f) << 6)
143 | (s[1] & 0x3f);
144 s += 2;
145 }
146 else if (len >= 3
147 && ( (s[0] == 0xe0 && s[1] >= 0xa0 && s[1] <= 0xbf)
148 || (s[0] >= 0xe1 && s[0] <= 0xec && s[1] >= 0x80 && s[1] <= 0xbf)
149 || (s[0] == 0xed && s[1] >= 0x80 && s[1] <= 0x9f)
150 || (s[0] >= 0xee && s[0] <= 0xef && s[1] >= 0x80 && s[1] <= 0xbf)
151 )
152 && (s[2] & 0xc0) == 0x80)
153 {
154 *p++ = ((s[0] & 0x0f) << 12)
155 | ((s[1] & 0x3f) << 6)
156 | (s[2] & 0x3f);
157 s += 3;
158 }
159 else if (len >= 4
160 && ( (s[0] == 0xf0 && s[1] >= 0x90 && s[1] <= 0xbf)
161 || (s[0] >= 0xf1 && s[0] <= 0xf3 && s[1] >= 0x80 && s[1] <= 0xbf)
162 || (s[0] == 0xf4 && s[1] >= 0x80 && s[1] <= 0x8f)
163 )
164 && (s[2] & 0xc0) == 0x80
165 && (s[3] & 0xc0) == 0x80)
166 {
167 *p++ = ((s[0] & 0x07) << 18)
168 | ((s[1] & 0x3f) << 12)
169 | ((s[2] & 0x3f) << 6)
170 | (s[3] & 0x3f);
171 s += 4;
172 }
173 else
174 {
175 *p++ = 0xfffd;
176 s++;
177 }
178 }
179
180 *p = 0;
181
182 return r;
183 }
184
185 const char *
186 rxvt_basename (const char *str) noexcept
187 {
188 const char *base = strrchr (str, '/');
189
190 return base ? base + 1 : str;
191 }
192
193 /*
194 * Print an error message
195 */
196 void
197 rxvt_vlog (const char *fmt, va_list arg_ptr) noexcept
198 {
199 char msg[1024];
200
201 vsnprintf (msg, sizeof msg, fmt, arg_ptr);
202
203 if (GET_R && GET_R->log_hook)
204 (*GET_R->log_hook) (msg);
205 else
206 write (STDOUT_FILENO, msg, strlen (msg));
207 }
208
209 void
210 rxvt_log (const char *fmt,...) noexcept
211 {
212 va_list arg_ptr;
213
214 va_start (arg_ptr, fmt);
215 rxvt_vlog (fmt, arg_ptr);
216 va_end (arg_ptr);
217 }
218
219 /*
220 * Print an error message
221 */
222 void
223 rxvt_warn (const char *fmt,...) noexcept
224 {
225 va_list arg_ptr;
226
227 rxvt_log ("%s: ", RESNAME);
228
229 va_start (arg_ptr, fmt);
230 rxvt_vlog (fmt, arg_ptr);
231 va_end (arg_ptr);
232 }
233
234 void
235 rxvt_fatal (const char *fmt,...)
236 {
237 va_list arg_ptr;
238
239 rxvt_log ("%s: ", RESNAME);
240
241 va_start (arg_ptr, fmt);
242 rxvt_vlog (fmt, arg_ptr);
243 va_end (arg_ptr);
244
245 rxvt_exit_failure ();
246 }
247
248 void
249 rxvt_exit_failure ()
250 {
251 static class rxvt_failure_exception rxvt_failure_exception;
252 throw (rxvt_failure_exception);
253 }
254
255 /*
256 * remove leading/trailing space in place.
257 */
258 char *
259 rxvt_strtrim (char *str) noexcept
260 {
261 char *r, *s;
262
263 if (!str || !*str) /* shortcut */
264 return str;
265
266 /* skip leading spaces */
267 for (s = str; *s && isspace (*s); s++) ;
268
269 /* goto end of string */
270 r = s + strlen (s) - 1;
271
272 /* dump return and other trailing whitespace */
273 while (r > s && isspace (*r))
274 r--;
275
276 memmove (str, s, r + 1 - s);
277 str[r + 1 - s] = 0;
278
279 return str;
280 }
281
282 /*
283 * Split a string into an array based on the given delimiter, stripping leading and
284 * trailing spaces from each entry. Empty strings are properly returned
285 */
286 char **
287 rxvt_strsplit (char delim, const char *str) noexcept
288 {
289 int l, n;
290 char *s, *t;
291 char **ret;
292
293 s = strdup (str ? str : "");
294
295 for (n = 1, t = s; *t; t++)
296 if (*t == delim)
297 n++;
298
299 ret = (char **)malloc ((n + 1) * sizeof (char *));
300 ret[n] = NULL;
301
302 for (l = 0, t = s; l < n; l++)
303 {
304 for (; *t && *t != delim; t++)
305 ;
306 *t = '\0';
307 ret[l] = s;
308 rxvt_strtrim (ret[l]);
309 s = ++t;
310 }
311
312 return ret;
313 }
314
315 void *
316 rxvt_malloc (size_t size)
317 {
318 void *p = malloc (size);
319
320 if (!p)
321 rxvt_fatal ("memory allocation failure. aborting.\n");
322
323 return p;
324 }
325
326 void *
327 rxvt_calloc (size_t number, size_t size)
328 {
329 void *p = calloc (number, size);
330
331 if (!p)
332 rxvt_fatal ("memory allocation failure. aborting.\n");
333
334 return p;
335 }
336
337 void *
338 rxvt_realloc (void *ptr, size_t size)
339 {
340 void *p = realloc (ptr, size);
341
342 if (!p)
343 rxvt_fatal ("memory allocation failure. aborting.\n");
344
345 return p;
346 }
347
348 KeySym
349 rxvt_XKeycodeToKeysym (Display *dpy, KeyCode code, int index)
350 {
351 int size;
352 KeySym *mapping = XGetKeyboardMapping (dpy, code, 1, &size);
353 KeySym keysym = IN_RANGE_EXC (index, 0, size) ? mapping[index] : NoSymbol;
354 XFree (mapping);
355 return keysym;
356 }