comparison src/os_mac_conv.c @ 18:293621502c4d v7.0010

updated for version 7.0010
author vimboss
date Sun, 18 Jul 2004 21:34:53 +0000
parents
children 4ac1dce8dd5e
comparison
equal deleted inserted replaced
17:9be87deaeb52 18:293621502c4d
1 /* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9 /*
10 * os_mac_conv.c: Code specifically for Mac string conversions.
11 *
12 * This code has been put in a separate file to avoid the conflicts that are
13 * caused by including both the X11 and Carbon header files.
14 */
15
16 #define NO_X11_INCLUDES
17 #include "vim.h"
18
19 extern char_u *mac_string_convert __ARGS((char_u *ptr, int len, int *lenp, int fail_on_error, int from, int to, int *unconvlenp));
20 extern int macroman2enc __ARGS((char_u *ptr, long *sizep, long real_size));
21 extern int enc2macroman __ARGS((char_u *from, size_t fromlen, char_u *to, int *tolenp, int maxtolen, char_u *rest, int *restlenp));
22
23 /*
24 * A Mac version of string_convert_ext() for special cases.
25 */
26 char_u *
27 mac_string_convert(ptr, len, lenp, fail_on_error, from_enc, to_enc, unconvlenp)
28 char_u *ptr;
29 int len;
30 int *lenp;
31 int fail_on_error;
32 int from_enc;
33 int to_enc;
34 int *unconvlenp;
35 {
36 char_u *retval, *d;
37 CFStringRef cfstr;
38 int buflen, in, out, l, i;
39 CFStringEncoding from;
40 CFStringEncoding to;
41
42 switch (from_enc)
43 {
44 case 'l': from = kCFStringEncodingISOLatin1; break;
45 case 'm': from = kCFStringEncodingMacRoman; break;
46 case 'u': from = kCFStringEncodingUTF8; break;
47 default: return NULL;
48 }
49 switch (to_enc)
50 {
51 case 'l': to = kCFStringEncodingISOLatin1; break;
52 case 'm': to = kCFStringEncodingMacRoman; break;
53 case 'u': to = kCFStringEncodingUTF8; break;
54 default: return NULL;
55 }
56
57 if (unconvlenp != NULL)
58 *unconvlenp = 0;
59 cfstr = CFStringCreateWithBytes(NULL, ptr, len, from, 0);
60
61 /* When conversion failed, try excluding bytes from the end, helps when
62 * there is an incomplete byte sequence. Only do up to 6 bytes to avoid
63 * looping a long time when there really is something unconvertable. */
64 while (cfstr == NULL && unconvlenp != NULL && len > 1 && *unconvlenp < 6)
65 {
66 --len;
67 ++*unconvlenp;
68 cfstr = CFStringCreateWithBytes(NULL, ptr, len, from, 0);
69 }
70 if (cfstr == NULL)
71 return NULL;
72 if (to == kCFStringEncodingUTF8)
73 buflen = len * 6 + 1;
74 else
75 buflen = len + 1;
76 retval = alloc(buflen);
77 if (retval == NULL)
78 {
79 CFRelease(cfstr);
80 return NULL;
81 }
82 if (!CFStringGetCString(cfstr, retval, buflen, to))
83 {
84 CFRelease(cfstr);
85 if (fail_on_error)
86 {
87 vim_free(retval);
88 return NULL;
89 }
90
91 /* conversion failed for the whole string, but maybe it will work
92 * for each character */
93 for (d = retval, in = 0, out = 0; in < len && out < buflen - 1;)
94 {
95 if (from == kCFStringEncodingUTF8)
96 l = utf_ptr2len_check(ptr + in);
97 else
98 l = 1;
99 cfstr = CFStringCreateWithBytes(NULL, ptr + in, l, from, 0);
100 if (cfstr == NULL)
101 {
102 *d++ = '?';
103 out++;
104 }
105 else
106 {
107 if (!CFStringGetCString(cfstr, d, buflen - out, to))
108 {
109 *d++ = '?';
110 out++;
111 }
112 else
113 {
114 i = strlen(d);
115 d += i;
116 out += i;
117 }
118 CFRelease(cfstr);
119 }
120 in += l;
121 }
122 *d = NUL;
123 if (lenp != NULL)
124 *lenp = out;
125 return retval;
126 }
127 CFRelease(cfstr);
128 if (lenp != NULL)
129 *lenp = strlen(retval);
130 return retval;
131 }
132
133 /*
134 * Conversion from Apple MacRoman char encoding to UTF-8 or latin1, using
135 * standard Carbon framework.
136 * Input: "ptr[*sizep]".
137 * "real_size" is the size of the buffer that "ptr" points to.
138 * output is in-place, "sizep" is adjusted.
139 * Returns OK or FAIL.
140 */
141 int
142 macroman2enc(ptr, sizep, real_size)
143 char_u *ptr;
144 long *sizep;
145 long real_size;
146 {
147 CFStringRef cfstr;
148 CFRange r;
149 CFIndex len = *sizep;
150
151 /* MacRoman is an 8-bit encoding, no need to move bytes to
152 * conv_rest[]. */
153 cfstr = CFStringCreateWithBytes(NULL, ptr, len,
154 kCFStringEncodingMacRoman, 0);
155 /*
156 * If there is a conversion error, try using another
157 * conversion.
158 */
159 if (cfstr == NULL)
160 return FAIL;
161
162 r.location = 0;
163 r.length = CFStringGetLength(cfstr);
164 if (r.length != CFStringGetBytes(cfstr, r,
165 (enc_utf8) ? kCFStringEncodingUTF8 : kCFStringEncodingISOLatin1,
166 0, /* no lossy conversion */
167 0, /* not external representation */
168 ptr + *sizep, real_size - *sizep, &len))
169 {
170 CFRelease(cfstr);
171 return FAIL;
172 }
173 CFRelease(cfstr);
174 mch_memmove(ptr, ptr + *sizep, len);
175 *sizep = len;
176
177 return OK;
178 }
179
180 /*
181 * Conversion from UTF-8 or latin1 to MacRoman.
182 * Input: "from[fromlen]"
183 * Output: "to[maxtolen]" length in "*tolenp"
184 * Unconverted rest in rest[*restlenp].
185 * Returns OK or FAIL.
186 */
187 int
188 enc2macroman(from, fromlen, to, tolenp, maxtolen, rest, restlenp)
189 char_u *from;
190 size_t fromlen;
191 char_u *to;
192 int *tolenp;
193 int maxtolen;
194 char_u *rest;
195 int *restlenp;
196 {
197 CFStringRef cfstr;
198 CFRange r;
199 CFIndex l;
200
201 *restlenp = 0;
202 cfstr = CFStringCreateWithBytes(NULL, from, fromlen,
203 (enc_utf8) ? kCFStringEncodingUTF8 : kCFStringEncodingISOLatin1,
204 0);
205 while (cfstr == NULL && *restlenp < 3 && fromlen > 1)
206 {
207 rest[*restlenp++] = from[--fromlen];
208 cfstr = CFStringCreateWithBytes(NULL, from, fromlen,
209 (enc_utf8) ? kCFStringEncodingUTF8 : kCFStringEncodingISOLatin1,
210 0);
211 }
212 if (cfstr == NULL)
213 return FAIL;
214
215 r.location = 0;
216 r.length = CFStringGetLength(cfstr);
217 if (r.length != CFStringGetBytes(cfstr, r,
218 kCFStringEncodingMacRoman,
219 0, /* no lossy conversion */
220 0, /* not external representation (since vim
221 * handles this internally */
222 to, maxtolen, &l))
223 {
224 CFRelease(cfstr);
225 return FAIL;
226 }
227 CFRelease(cfstr);
228 *tolenp = l;
229 return OK;
230 }