diff options
author | Bram Moolenaar <Bram@vim.org> | 2004-07-18 21:34:53 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2004-07-18 21:34:53 +0000 |
commit | ab79bcbac383aa26fec23f8610995122a9ff4be6 (patch) | |
tree | 87d08c555b6a806c4cfffde6b42886e5b4094f83 /src/os_mac_conv.c | |
parent | 21cf823a906f1f66391a145a976fdae8e98e0394 (diff) | |
download | vim-git-ab79bcbac383aa26fec23f8610995122a9ff4be6.tar.gz |
updated for version 7.0010v7.0010
Diffstat (limited to 'src/os_mac_conv.c')
-rw-r--r-- | src/os_mac_conv.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/src/os_mac_conv.c b/src/os_mac_conv.c new file mode 100644 index 000000000..3dfacfe68 --- /dev/null +++ b/src/os_mac_conv.c @@ -0,0 +1,230 @@ +/* vi:set ts=8 sts=4 sw=4: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ +/* + * os_mac_conv.c: Code specifically for Mac string conversions. + * + * This code has been put in a separate file to avoid the conflicts that are + * caused by including both the X11 and Carbon header files. + */ + +#define NO_X11_INCLUDES +#include "vim.h" + +extern char_u *mac_string_convert __ARGS((char_u *ptr, int len, int *lenp, int fail_on_error, int from, int to, int *unconvlenp)); +extern int macroman2enc __ARGS((char_u *ptr, long *sizep, long real_size)); +extern int enc2macroman __ARGS((char_u *from, size_t fromlen, char_u *to, int *tolenp, int maxtolen, char_u *rest, int *restlenp)); + +/* + * A Mac version of string_convert_ext() for special cases. + */ + char_u * +mac_string_convert(ptr, len, lenp, fail_on_error, from_enc, to_enc, unconvlenp) + char_u *ptr; + int len; + int *lenp; + int fail_on_error; + int from_enc; + int to_enc; + int *unconvlenp; +{ + char_u *retval, *d; + CFStringRef cfstr; + int buflen, in, out, l, i; + CFStringEncoding from; + CFStringEncoding to; + + switch (from_enc) + { + case 'l': from = kCFStringEncodingISOLatin1; break; + case 'm': from = kCFStringEncodingMacRoman; break; + case 'u': from = kCFStringEncodingUTF8; break; + default: return NULL; + } + switch (to_enc) + { + case 'l': to = kCFStringEncodingISOLatin1; break; + case 'm': to = kCFStringEncodingMacRoman; break; + case 'u': to = kCFStringEncodingUTF8; break; + default: return NULL; + } + + if (unconvlenp != NULL) + *unconvlenp = 0; + cfstr = CFStringCreateWithBytes(NULL, ptr, len, from, 0); + + /* When conversion failed, try excluding bytes from the end, helps when + * there is an incomplete byte sequence. Only do up to 6 bytes to avoid + * looping a long time when there really is something unconvertable. */ + while (cfstr == NULL && unconvlenp != NULL && len > 1 && *unconvlenp < 6) + { + --len; + ++*unconvlenp; + cfstr = CFStringCreateWithBytes(NULL, ptr, len, from, 0); + } + if (cfstr == NULL) + return NULL; + if (to == kCFStringEncodingUTF8) + buflen = len * 6 + 1; + else + buflen = len + 1; + retval = alloc(buflen); + if (retval == NULL) + { + CFRelease(cfstr); + return NULL; + } + if (!CFStringGetCString(cfstr, retval, buflen, to)) + { + CFRelease(cfstr); + if (fail_on_error) + { + vim_free(retval); + return NULL; + } + + /* conversion failed for the whole string, but maybe it will work + * for each character */ + for (d = retval, in = 0, out = 0; in < len && out < buflen - 1;) + { + if (from == kCFStringEncodingUTF8) + l = utf_ptr2len_check(ptr + in); + else + l = 1; + cfstr = CFStringCreateWithBytes(NULL, ptr + in, l, from, 0); + if (cfstr == NULL) + { + *d++ = '?'; + out++; + } + else + { + if (!CFStringGetCString(cfstr, d, buflen - out, to)) + { + *d++ = '?'; + out++; + } + else + { + i = strlen(d); + d += i; + out += i; + } + CFRelease(cfstr); + } + in += l; + } + *d = NUL; + if (lenp != NULL) + *lenp = out; + return retval; + } + CFRelease(cfstr); + if (lenp != NULL) + *lenp = strlen(retval); + return retval; +} + +/* + * Conversion from Apple MacRoman char encoding to UTF-8 or latin1, using + * standard Carbon framework. + * Input: "ptr[*sizep]". + * "real_size" is the size of the buffer that "ptr" points to. + * output is in-place, "sizep" is adjusted. + * Returns OK or FAIL. + */ + int +macroman2enc(ptr, sizep, real_size) + char_u *ptr; + long *sizep; + long real_size; +{ + CFStringRef cfstr; + CFRange r; + CFIndex len = *sizep; + + /* MacRoman is an 8-bit encoding, no need to move bytes to + * conv_rest[]. */ + cfstr = CFStringCreateWithBytes(NULL, ptr, len, + kCFStringEncodingMacRoman, 0); + /* + * If there is a conversion error, try using another + * conversion. + */ + if (cfstr == NULL) + return FAIL; + + r.location = 0; + r.length = CFStringGetLength(cfstr); + if (r.length != CFStringGetBytes(cfstr, r, + (enc_utf8) ? kCFStringEncodingUTF8 : kCFStringEncodingISOLatin1, + 0, /* no lossy conversion */ + 0, /* not external representation */ + ptr + *sizep, real_size - *sizep, &len)) + { + CFRelease(cfstr); + return FAIL; + } + CFRelease(cfstr); + mch_memmove(ptr, ptr + *sizep, len); + *sizep = len; + + return OK; +} + +/* + * Conversion from UTF-8 or latin1 to MacRoman. + * Input: "from[fromlen]" + * Output: "to[maxtolen]" length in "*tolenp" + * Unconverted rest in rest[*restlenp]. + * Returns OK or FAIL. + */ + int +enc2macroman(from, fromlen, to, tolenp, maxtolen, rest, restlenp) + char_u *from; + size_t fromlen; + char_u *to; + int *tolenp; + int maxtolen; + char_u *rest; + int *restlenp; +{ + CFStringRef cfstr; + CFRange r; + CFIndex l; + + *restlenp = 0; + cfstr = CFStringCreateWithBytes(NULL, from, fromlen, + (enc_utf8) ? kCFStringEncodingUTF8 : kCFStringEncodingISOLatin1, + 0); + while (cfstr == NULL && *restlenp < 3 && fromlen > 1) + { + rest[*restlenp++] = from[--fromlen]; + cfstr = CFStringCreateWithBytes(NULL, from, fromlen, + (enc_utf8) ? kCFStringEncodingUTF8 : kCFStringEncodingISOLatin1, + 0); + } + if (cfstr == NULL) + return FAIL; + + r.location = 0; + r.length = CFStringGetLength(cfstr); + if (r.length != CFStringGetBytes(cfstr, r, + kCFStringEncodingMacRoman, + 0, /* no lossy conversion */ + 0, /* not external representation (since vim + * handles this internally */ + to, maxtolen, &l)) + { + CFRelease(cfstr); + return FAIL; + } + CFRelease(cfstr); + *tolenp = l; + return OK; +} |