summaryrefslogtreecommitdiff
path: root/src/os_mac_conv.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2004-07-18 21:34:53 +0000
committerBram Moolenaar <Bram@vim.org>2004-07-18 21:34:53 +0000
commitab79bcbac383aa26fec23f8610995122a9ff4be6 (patch)
tree87d08c555b6a806c4cfffde6b42886e5b4094f83 /src/os_mac_conv.c
parent21cf823a906f1f66391a145a976fdae8e98e0394 (diff)
downloadvim-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.c230
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;
+}