ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/misc.C
Revision: 1.54
Committed: Sat May 30 06:56:20 2009 UTC (14 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: before_dynamic_fontidx, rel-9_10, dynamic_fontidx, rel-9_09, rel-9_07
Changes since 1.53: +2 -2 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.40 /*----------------------------------------------------------------------*
2 pcg 1.13 * File: misc.C
3 pcg 1.1 *----------------------------------------------------------------------*
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 root 1.39 * Copyright (c) 2003-2006 Marc Lehmann <pcg@goof.com>
10 pcg 1.1 *
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 2 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 pcg 1.3 char *
30 pcg 1.10 rxvt_wcstombs (const wchar_t *str, int len)
31     {
32 root 1.19 if (len < 0) len = wcslen (str);
33    
34 pcg 1.10 mbstate mbs;
35     char *r = (char *)rxvt_malloc (len * MB_CUR_MAX + 1);
36    
37     char *dst = r;
38     while (len--)
39     {
40 root 1.24 ssize_t l = wcrtomb (dst, *str++, mbs);
41 root 1.31
42 pcg 1.10 if (l < 0)
43 root 1.52 {
44     *dst++ = '?';
45     wcrtomb (0, 0, mbs); // reset undefined state
46     }
47 pcg 1.10 else
48     dst += l;
49     }
50    
51     *dst++ = 0;
52    
53 root 1.24 return (char *)rxvt_realloc (r, dst - r);
54 pcg 1.10 }
55    
56 root 1.19 wchar_t *
57     rxvt_mbstowcs (const char *str, int len)
58     {
59     if (len < 0) len = strlen (str);
60    
61     wchar_t *r = (wchar_t *)rxvt_malloc ((len + 1) * sizeof (wchar_t));
62    
63 root 1.24 if ((ssize_t)mbstowcs (r, str, len + 1) < 0)
64 root 1.19 *r = 0;
65    
66     return r;
67     }
68    
69     char *
70     rxvt_wcstoutf8 (const wchar_t *str, int len)
71     {
72     if (len < 0) len = wcslen (str);
73    
74     char *r = (char *)rxvt_malloc (len * 4 + 1);
75     char *p = r;
76    
77     while (len--)
78     {
79 root 1.22 unicode_t w = *str++ & UNICODE_MASK;
80 root 1.19
81     if (w < 0x000080)
82     *p++ = w;
83     else if (w < 0x000800)
84     *p++ = 0xc0 | ( w >> 6),
85     *p++ = 0x80 | ( w & 0x3f);
86     else if (w < 0x010000)
87 ayin 1.48 *p++ = 0xe0 | ( w >> 12),
88 root 1.19 *p++ = 0x80 | ((w >> 6) & 0x3f),
89     *p++ = 0x80 | ( w & 0x3f);
90     else if (w < 0x110000)
91     *p++ = 0xf0 | ( w >> 18),
92     *p++ = 0x80 | ((w >> 12) & 0x3f),
93     *p++ = 0x80 | ((w >> 6) & 0x3f),
94     *p++ = 0x80 | ( w & 0x3f);
95     else
96     *p++ = '?';
97     }
98    
99 root 1.24 *p++ = 0;
100 root 1.19
101 root 1.24 return (char *)rxvt_realloc (r, p - r);
102 root 1.19 }
103    
104     wchar_t *
105     rxvt_utf8towcs (const char *str, int len)
106     {
107     if (len < 0) len = strlen (str);
108    
109 root 1.21 wchar_t *r = (wchar_t *)rxvt_malloc ((len + 1) * sizeof (wchar_t)),
110     *p = r;
111 root 1.19
112 root 1.21 unsigned char *s = (unsigned char *)str,
113     *e = s + len;
114 root 1.19
115 root 1.21 for (;;)
116 root 1.19 {
117 root 1.21 len = e - s;
118    
119     if (len == 0)
120     break;
121     else if (s[0] < 0x80)
122     *p++ = *s++;
123     else if (len >= 2
124 ayin 1.49 && s[0] >= 0xc2 && s[0] <= 0xdf
125 root 1.19 && (s[1] & 0xc0) == 0x80)
126     {
127     *p++ = ((s[0] & 0x1f) << 6)
128     | (s[1] & 0x3f);
129 root 1.21 s += 2;
130 root 1.19 }
131 root 1.21 else if (len >= 3
132 root 1.19 && ( (s[0] == 0xe0 && s[1] >= 0xa0 && s[1] <= 0xbf)
133     || (s[0] >= 0xe1 && s[0] <= 0xec && s[1] >= 0x80 && s[1] <= 0xbf)
134     || (s[0] == 0xed && s[1] >= 0x80 && s[1] <= 0x9f)
135     || (s[0] >= 0xee && s[0] <= 0xef && s[1] >= 0x80 && s[1] <= 0xbf)
136     )
137     && (s[2] & 0xc0) == 0x80)
138     {
139     *p++ = ((s[0] & 0x0f) << 12)
140     | ((s[1] & 0x3f) << 6)
141     | (s[2] & 0x3f);
142 root 1.21 s += 3;
143 root 1.19 }
144 root 1.21 else if (len >= 4
145 root 1.19 && ( (s[0] == 0xf0 && s[1] >= 0x90 && s[1] <= 0xbf)
146     || (s[0] >= 0xf1 && s[0] <= 0xf3 && s[1] >= 0x80 && s[1] <= 0xbf)
147     || (s[0] == 0xf4 && s[1] >= 0x80 && s[1] <= 0x8f)
148     )
149     && (s[2] & 0xc0) == 0x80
150     && (s[3] & 0xc0) == 0x80)
151     {
152 ayin 1.49 *p++ = ((s[0] & 0x07) << 18)
153     | ((s[1] & 0x3f) << 12)
154     | ((s[2] & 0x3f) << 6)
155 root 1.19 | (s[3] & 0x3f);
156 root 1.21 s += 4;
157 root 1.19 }
158     else
159     {
160     *p++ = 0xfffd;
161 root 1.21 s++;
162 root 1.19 }
163     }
164    
165     *p = 0;
166    
167     return r;
168     }
169    
170 root 1.53 const char *
171 ayin 1.46 rxvt_basename (const char *str) NOTHROW
172 pcg 1.1 {
173 root 1.54 const char *base = strrchr (str, '/');
174 pcg 1.1
175 root 1.54 return base ? base + 1 : str;
176 pcg 1.1 }
177    
178     /*
179     * Print an error message
180     */
181     void
182 root 1.36 rxvt_vlog (const char *fmt, va_list arg_ptr) NOTHROW
183 pcg 1.12 {
184     char msg[1024];
185    
186     vsnprintf (msg, sizeof msg, fmt, arg_ptr);
187    
188     if (GET_R && GET_R->log_hook)
189     (*GET_R->log_hook) (msg);
190     else
191     write (STDOUT_FILENO, msg, strlen (msg));
192     }
193    
194     void
195 root 1.36 rxvt_log (const char *fmt,...) NOTHROW
196 pcg 1.1 {
197 pcg 1.8 va_list arg_ptr;
198 pcg 1.1
199 pcg 1.7 va_start (arg_ptr, fmt);
200 pcg 1.12 rxvt_vlog (fmt, arg_ptr);
201 pcg 1.7 va_end (arg_ptr);
202 pcg 1.1 }
203    
204     /*
205 pcg 1.12 * Print an error message
206     */
207     void
208 root 1.36 rxvt_warn (const char *fmt,...) NOTHROW
209 pcg 1.12 {
210     va_list arg_ptr;
211    
212     rxvt_log ("%s: ", RESNAME);
213    
214     va_start (arg_ptr, fmt);
215     rxvt_vlog (fmt, arg_ptr);
216     va_end (arg_ptr);
217     }
218    
219     void
220 root 1.36 rxvt_fatal (const char *fmt,...) THROW ((class rxvt_failure_exception))
221 pcg 1.12 {
222     va_list arg_ptr;
223    
224     rxvt_log ("%s: ", RESNAME);
225    
226     va_start (arg_ptr, fmt);
227     rxvt_vlog (fmt, arg_ptr);
228     va_end (arg_ptr);
229    
230     rxvt_exit_failure ();
231     }
232    
233     void
234 root 1.36 rxvt_exit_failure () THROW ((class rxvt_failure_exception))
235 pcg 1.12 {
236 root 1.36 static class rxvt_failure_exception rxvt_failure_exception;
237 pcg 1.12 throw (rxvt_failure_exception);
238     }
239    
240     /*
241 ayin 1.44 * remove leading/trailing space in place.
242 pcg 1.1 */
243 ayin 1.47 char *
244 ayin 1.46 rxvt_strtrim (char *str) NOTHROW
245 pcg 1.1 {
246 pcg 1.8 char *r, *s;
247 pcg 1.1
248 pcg 1.5 if (!str || !*str) /* shortcut */
249     return str;
250 pcg 1.1
251 pcg 1.5 /* skip leading spaces */
252 pcg 1.7 for (s = str; *s && isspace (*s); s++) ;
253 root 1.25
254 pcg 1.5 /* goto end of string */
255 root 1.25 r = s + strlen (s) - 1;
256    
257     /* dump return and other trailing whitespace */
258     while (r > s && isspace (*r))
259     r--;
260    
261     memmove (str, s, r + 1 - s);
262     str[r + 1 - s] = 0;
263 pcg 1.1
264 pcg 1.5 return str;
265 pcg 1.1 }
266    
267     /*
268     * Split a comma-separated string into an array, stripping leading and
269 root 1.25 * trailing spaces from each entry. Empty strings are properly returned
270 pcg 1.1 */
271 ayin 1.47 char **
272 root 1.36 rxvt_splitcommastring (const char *cs) NOTHROW
273 pcg 1.1 {
274 pcg 1.5 int l, n, p;
275     const char *s, *t;
276     char **ret;
277    
278     if ((s = cs) == NULL)
279     s = "";
280    
281     for (n = 1, t = s; *t; t++)
282     if (*t == ',')
283     n++;
284 root 1.25
285 pcg 1.7 ret = (char **)malloc ((n + 1) * sizeof (char *));
286 pcg 1.5 ret[n] = NULL;
287    
288     for (l = 0, t = s; l < n; l++)
289     {
290     for ( ; *t && *t != ','; t++) ;
291     p = t - s;
292 pcg 1.7 ret[l] = (char *)malloc (p + 1);
293 ayin 1.51 memcpy (ret[l], s, p);
294 pcg 1.5 ret[l][p] = '\0';
295 ayin 1.46 rxvt_strtrim (ret[l]);
296 pcg 1.5 s = ++t;
297 pcg 1.1 }
298 root 1.25
299 pcg 1.5 return ret;
300 pcg 1.1 }
301    
302 root 1.16 void
303 root 1.36 rxvt_freecommastring (char **cs) NOTHROW
304 root 1.16 {
305     for (int i = 0; cs[i]; ++i)
306     free (cs[i]);
307    
308     free (cs);
309     }
310    
311 ayin 1.50 void *
312     rxvt_malloc (size_t size)
313     {
314     void *p = malloc (size);
315 pcg 1.1
316 ayin 1.50 if (!p)
317     rxvt_fatal ("memory allocation failure. aborting.\n");
318 root 1.28
319 ayin 1.50 return p;
320     }
321    
322     void *
323     rxvt_calloc (size_t number, size_t size)
324     {
325     void *p = calloc (number, size);
326    
327     if (!p)
328     rxvt_fatal ("memory allocation failure. aborting.\n");
329    
330     return p;
331     }
332    
333     void *
334     rxvt_realloc (void *ptr, size_t size)
335     {
336     void *p = realloc (ptr, size);
337    
338     if (!p)
339     rxvt_fatal ("memory allocation failure. aborting.\n");
340    
341     return p;
342     }