comparison src/os_macosx.m @ 2309:543ea69d037f vim73

Add clipboard support in Mac console. (Bjorn Winckler)
author Bram Moolenaar <bram@vim.org>
date Wed, 14 Jul 2010 13:58:07 +0200
parents src/os_macosx.c@cccb71c2c5c1
children 3e4574a4b627
comparison
equal deleted inserted replaced
2308:cb025511f6b6 2309:543ea69d037f
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 /*
11 * os_macosx.m -- Mac specific things for Mac OS/X.
12 */
13
14 #ifndef MACOS_X_UNIX
15 Error: MACOS 9 is no longer supported in Vim 7
16 #endif
17
18 #include "vim.h"
19 #import <Cocoa/Cocoa.h>
20
21
22 NSString *VimPboardType = @"VimPboardType";
23
24
25 #ifdef _DEBUG
26 void
27 Trace(char* fmt, ...)
28 {
29 char buf[2048];
30 va_list args;
31
32 va_start(args, fmt);
33 /* vsnprintf(buf, sizeof(buf), fmt, args);*/
34 fprintf(stderr, "%s", buf);
35 va_end(args);
36 }
37 #endif
38
39 #ifdef MACOS_X_ICONVEMU
40 /*
41 * Libiconv emulation layer
42 */
43
44 struct _iconv_t
45 {
46 TECObjectRef tec;
47 TECObjectRef tecReverse;
48 TECSnifferObjectRef sniff;
49 TextEncoding from;
50 TextEncoding to;
51 };
52 /* typedef struct _iconv_t *iconv_t; */
53
54
55 static int last_errno = 0;
56
57 /*
58 * Get TextEncoding from iconv's encoding name
59 */
60 static TextEncoding
61 get_textencoding(const char* encodename)
62 {
63 static struct {
64 const char* name;
65 TextEncoding encode;
66 } encodetable[] = {
67 /* ISO-8859 encodings family */
68 {"latin1", kTextEncodingISOLatin1},
69 {"latin2", kTextEncodingISOLatin2},
70 {"latin3", kTextEncodingISOLatin3},
71 {"latin4", kTextEncodingISOLatin4},
72 {"latin5", kTextEncodingISOLatin5},
73 {"latin6", kTextEncodingISOLatin6},
74 {"latin7", kTextEncodingISOLatin7},
75 {"latin8", kTextEncodingISOLatin8},
76 {"latin9", kTextEncodingISOLatin9},
77 {"iso-8859-1", kTextEncodingISOLatin1},
78 {"iso-8859-2", kTextEncodingISOLatin2},
79 {"iso-8859-3", kTextEncodingISOLatin3},
80 {"iso-8859-4", kTextEncodingISOLatin4},
81 {"iso-8859-5", kTextEncodingISOLatinCyrillic},
82 {"iso-8859-6", kTextEncodingISOLatinArabic},
83 {"iso-8859-7", kTextEncodingISOLatinGreek},
84 {"iso-8859-8", kTextEncodingISOLatinHebrew},
85 {"iso-8859-9", kTextEncodingISOLatin5},
86 {"iso-8859-10", kTextEncodingISOLatin6},
87 {"iso-8859-15", kTextEncodingISOLatin9},
88
89 /* Unicode encodings. */
90 /* TODO: Add other type of unicode */
91 {"ucs-2", kTextEncodingMacUnicode},
92
93 /* Japanese encoding aliases */
94 {"cp932", kTextEncodingShiftJIS},
95 {"shift-jis", kTextEncodingShiftJIS},
96 {"euc-jp", kTextEncodingEUC_JP},
97 {"iso-2022-jp", kTextEncodingISO_2022_JP},
98 {"iso-2022-jp-1", kTextEncodingISO_2022_JP_1},
99 {"iso-2022-jp-2", kTextEncodingISO_2022_JP_2},
100 {"iso-2022-jp-3", kTextEncodingISO_2022_JP_3},
101
102 /* Other aliases. These aliases in this block are just guessed. */
103 /* TODO: Must be verified. */
104 {"gb2312", kTextEncodingGB_2312_80},
105 {"cp936", kTextEncodingMacChineseSimp},
106 {"euc-cn", kTextEncodingEUC_CN},
107 {"cp950", kTextEncodingMacChineseTrad},
108 {"euc-tw", kTextEncodingEUC_TW},
109 {"cp949", kTextEncodingMacKorean},
110 {"euc-kr", kTextEncodingEUC_KR},
111
112 /*
113 * All encodings supported by Macintosh. You can find these values
114 * in a file:
115 * /System/Library/Frameworks/CoreServices.framework/Versions/A/
116 * Frameworks/CarbonCore.framework/Versions/A/Headers/TextCommon.h
117 */
118 {"MacRoman", kTextEncodingMacRoman},
119 {"MacJapanese", kTextEncodingMacJapanese},
120 {"MacChineseTrad", kTextEncodingMacChineseTrad},
121 {"MacKorean", kTextEncodingMacKorean},
122 {"MacArabic", kTextEncodingMacArabic},
123 {"MacHebrew", kTextEncodingMacHebrew},
124 {"MacGreek", kTextEncodingMacGreek},
125 {"MacCyrillic", kTextEncodingMacCyrillic},
126 {"MacDevanagari", kTextEncodingMacDevanagari},
127 {"MacGurmukhi", kTextEncodingMacGurmukhi},
128 {"MacGujarati", kTextEncodingMacGujarati},
129 {"MacOriya", kTextEncodingMacOriya},
130 {"MacBengali", kTextEncodingMacBengali},
131 {"MacTamil", kTextEncodingMacTamil},
132 {"MacTelugu", kTextEncodingMacTelugu},
133 {"MacKannada", kTextEncodingMacKannada},
134 {"MacMalayalam", kTextEncodingMacMalayalam},
135 {"MacSinhalese", kTextEncodingMacSinhalese},
136 {"MacBurmese", kTextEncodingMacBurmese},
137 {"MacKhmer", kTextEncodingMacKhmer},
138 {"MacThai", kTextEncodingMacThai},
139 {"MacLaotian", kTextEncodingMacLaotian},
140 {"MacGeorgian", kTextEncodingMacGeorgian},
141 {"MacArmenian", kTextEncodingMacArmenian},
142 {"MacChineseSimp", kTextEncodingMacChineseSimp},
143 {"MacTibetan", kTextEncodingMacTibetan},
144 {"MacMongolian", kTextEncodingMacMongolian},
145 {"MacEthiopic", kTextEncodingMacEthiopic},
146 {"MacCentralEurRoman", kTextEncodingMacCentralEurRoman},
147 {"MacVietnamese", kTextEncodingMacVietnamese},
148 {"MacExtArabic", kTextEncodingMacExtArabic},
149 {"MacSymbol", kTextEncodingMacSymbol},
150 {"MacDingbats", kTextEncodingMacDingbats},
151 {"MacTurkish", kTextEncodingMacTurkish},
152 {"MacCroatian", kTextEncodingMacCroatian},
153 {"MacIcelandic", kTextEncodingMacIcelandic},
154 {"MacRomanian", kTextEncodingMacRomanian},
155 {"MacCeltic", kTextEncodingMacCeltic},
156 {"MacGaelic", kTextEncodingMacGaelic},
157 {"MacKeyboardGlyphs", kTextEncodingMacKeyboardGlyphs},
158 {"MacTradChinese", kTextEncodingMacTradChinese},
159 {"MacRSymbol", kTextEncodingMacRSymbol},
160 {"MacSimpChinese", kTextEncodingMacSimpChinese},
161 {"MacGeez", kTextEncodingMacGeez},
162 {"MacEastEurRoman", kTextEncodingMacEastEurRoman},
163 {"MacUninterp", kTextEncodingMacUninterp},
164 {"MacUnicode", kTextEncodingMacUnicode},
165 {"MacFarsi", kTextEncodingMacFarsi},
166 {"MacUkrainian", kTextEncodingMacUkrainian},
167 {"MacInuit", kTextEncodingMacInuit},
168 {"MacVT100", kTextEncodingMacVT100},
169 {"MacHFS", kTextEncodingMacHFS},
170 {"UnicodeDefault", kTextEncodingUnicodeDefault},
171 {"UnicodeV1_1", kTextEncodingUnicodeV1_1},
172 {"ISO10646_1993", kTextEncodingISO10646_1993},
173 {"UnicodeV2_0", kTextEncodingUnicodeV2_0},
174 {"UnicodeV2_1", kTextEncodingUnicodeV2_1},
175 {"UnicodeV3_0", kTextEncodingUnicodeV3_0},
176 {"UnicodeV3_1", kTextEncodingUnicodeV3_1},
177 {"UnicodeV3_2", kTextEncodingUnicodeV3_2},
178 {"ISOLatin1", kTextEncodingISOLatin1},
179 {"ISOLatin2", kTextEncodingISOLatin2},
180 {"ISOLatin3", kTextEncodingISOLatin3},
181 {"ISOLatin4", kTextEncodingISOLatin4},
182 {"ISOLatinCyrillic", kTextEncodingISOLatinCyrillic},
183 {"ISOLatinArabic", kTextEncodingISOLatinArabic},
184 {"ISOLatinGreek", kTextEncodingISOLatinGreek},
185 {"ISOLatinHebrew", kTextEncodingISOLatinHebrew},
186 {"ISOLatin5", kTextEncodingISOLatin5},
187 {"ISOLatin6", kTextEncodingISOLatin6},
188 {"ISOLatin7", kTextEncodingISOLatin7},
189 {"ISOLatin8", kTextEncodingISOLatin8},
190 {"ISOLatin9", kTextEncodingISOLatin9},
191 {"DOSLatinUS", kTextEncodingDOSLatinUS},
192 {"DOSGreek", kTextEncodingDOSGreek},
193 {"DOSBalticRim", kTextEncodingDOSBalticRim},
194 {"DOSLatin1", kTextEncodingDOSLatin1},
195 {"DOSGreek1", kTextEncodingDOSGreek1},
196 {"DOSLatin2", kTextEncodingDOSLatin2},
197 {"DOSCyrillic", kTextEncodingDOSCyrillic},
198 {"DOSTurkish", kTextEncodingDOSTurkish},
199 {"DOSPortuguese", kTextEncodingDOSPortuguese},
200 {"DOSIcelandic", kTextEncodingDOSIcelandic},
201 {"DOSHebrew", kTextEncodingDOSHebrew},
202 {"DOSCanadianFrench", kTextEncodingDOSCanadianFrench},
203 {"DOSArabic", kTextEncodingDOSArabic},
204 {"DOSNordic", kTextEncodingDOSNordic},
205 {"DOSRussian", kTextEncodingDOSRussian},
206 {"DOSGreek2", kTextEncodingDOSGreek2},
207 {"DOSThai", kTextEncodingDOSThai},
208 {"DOSJapanese", kTextEncodingDOSJapanese},
209 {"DOSChineseSimplif", kTextEncodingDOSChineseSimplif},
210 {"DOSKorean", kTextEncodingDOSKorean},
211 {"DOSChineseTrad", kTextEncodingDOSChineseTrad},
212 {"WindowsLatin1", kTextEncodingWindowsLatin1},
213 {"WindowsANSI", kTextEncodingWindowsANSI},
214 {"WindowsLatin2", kTextEncodingWindowsLatin2},
215 {"WindowsCyrillic", kTextEncodingWindowsCyrillic},
216 {"WindowsGreek", kTextEncodingWindowsGreek},
217 {"WindowsLatin5", kTextEncodingWindowsLatin5},
218 {"WindowsHebrew", kTextEncodingWindowsHebrew},
219 {"WindowsArabic", kTextEncodingWindowsArabic},
220 {"WindowsBalticRim", kTextEncodingWindowsBalticRim},
221 {"WindowsVietnamese", kTextEncodingWindowsVietnamese},
222 {"WindowsKoreanJohab", kTextEncodingWindowsKoreanJohab},
223 {"US_ASCII", kTextEncodingUS_ASCII},
224 {"JIS_X0201_76", kTextEncodingJIS_X0201_76},
225 {"JIS_X0208_83", kTextEncodingJIS_X0208_83},
226 {"JIS_X0208_90", kTextEncodingJIS_X0208_90},
227 {"JIS_X0212_90", kTextEncodingJIS_X0212_90},
228 {"JIS_C6226_78", kTextEncodingJIS_C6226_78},
229 {"ShiftJIS_X0213_00", kTextEncodingShiftJIS_X0213_00},
230 {"GB_2312_80", kTextEncodingGB_2312_80},
231 {"GBK_95", kTextEncodingGBK_95},
232 {"GB_18030_2000", kTextEncodingGB_18030_2000},
233 {"KSC_5601_87", kTextEncodingKSC_5601_87},
234 {"KSC_5601_92_Johab", kTextEncodingKSC_5601_92_Johab},
235 {"CNS_11643_92_P1", kTextEncodingCNS_11643_92_P1},
236 {"CNS_11643_92_P2", kTextEncodingCNS_11643_92_P2},
237 {"CNS_11643_92_P3", kTextEncodingCNS_11643_92_P3},
238 {"ISO_2022_JP", kTextEncodingISO_2022_JP},
239 {"ISO_2022_JP_2", kTextEncodingISO_2022_JP_2},
240 {"ISO_2022_JP_1", kTextEncodingISO_2022_JP_1},
241 {"ISO_2022_JP_3", kTextEncodingISO_2022_JP_3},
242 {"ISO_2022_CN", kTextEncodingISO_2022_CN},
243 {"ISO_2022_CN_EXT", kTextEncodingISO_2022_CN_EXT},
244 {"ISO_2022_KR", kTextEncodingISO_2022_KR},
245 {"EUC_JP", kTextEncodingEUC_JP},
246 {"EUC_CN", kTextEncodingEUC_CN},
247 {"EUC_TW", kTextEncodingEUC_TW},
248 {"EUC_KR", kTextEncodingEUC_KR},
249 {"ShiftJIS", kTextEncodingShiftJIS},
250 {"KOI8_R", kTextEncodingKOI8_R},
251 {"Big5", kTextEncodingBig5},
252 {"MacRomanLatin1", kTextEncodingMacRomanLatin1},
253 {"HZ_GB_2312", kTextEncodingHZ_GB_2312},
254 {"Big5_HKSCS_1999", kTextEncodingBig5_HKSCS_1999},
255 {"NextStepLatin", kTextEncodingNextStepLatin},
256 {"EBCDIC_US", kTextEncodingEBCDIC_US},
257 {"EBCDIC_CP037", kTextEncodingEBCDIC_CP037},
258 {"MultiRun", kTextEncodingMultiRun},
259
260 /* Terminator */
261 {NULL, -1},
262 };
263 int i;
264
265 i = 0;
266 for (i = 0; encodetable[i].name != NULL; ++i)
267 {
268 if (STRICMP(encodename, encodetable[i].name) == 0)
269 break;
270 }
271 return encodetable[i].encode;
272 }
273
274 /*
275 * iconv interfaces
276 */
277
278 iconv_t
279 iconv_open(const char* tocode, const char* fromcode)
280 {
281 TextEncoding toEnc, fromEnc;
282 iconv_t cd = NULL;
283 OSStatus st;
284
285 /* Verify to/from encoding name */
286 toEnc = get_textencoding(tocode);
287 fromEnc = get_textencoding(fromcode);
288 if (toEnc < 0 || fromEnc < 0)
289 goto ICONV_OPEN_ERR;
290
291 /* Allocate memory to object */
292 cd = (iconv_t)alloc(sizeof(struct _iconv_t));
293 if (!cd)
294 goto ICONV_OPEN_ERR;
295 vim_memset(cd, 0, sizeof(struct _iconv_t));
296
297 /* Create converter */
298 if (fromEnc != toEnc)
299 {
300 TRACE("*** fromEnc=%d toEnc=%d\n", (int)fromEnc, (int)toEnc);
301 st = TECCreateConverter(&cd->tec, fromEnc, toEnc);
302 if (st != 0)
303 {
304 TRACE("*** TECCreateConverter()=%d\n", (int)st);
305 goto ICONV_OPEN_ERR;
306 }
307 /* Create reverse converter */
308 st = TECCreateConverter(&cd->tecReverse, toEnc, fromEnc);
309 if (st != 0)
310 {
311 TRACE("*** TECCreateConverter()=%d (reverse)\n", (int)st);
312 goto ICONV_OPEN_ERR;
313 }
314 /* Create Sniffer */
315 st = TECCreateSniffer(&cd->sniff, &fromEnc, 1);
316 if (st != 0)
317 {
318 TRACE("*** TECCreateSniffer()=%d\n", (int)st);
319 goto ICONV_OPEN_ERR;
320 }
321 }
322
323 cd->from = fromEnc;
324 cd->to = toEnc;
325 last_errno = 0;
326 return cd;
327
328 ICONV_OPEN_ERR:
329 if (cd)
330 iconv_close(cd);
331 last_errno = EINVAL;
332 return (iconv_t)-1;
333 }
334
335 /*
336 * Used when there are same value in 'from encoding' and 'to encoding'.
337 * TEC doesn't support conversion between same encodings, and
338 * TECCreateConverter() failed.
339 */
340 static size_t
341 null_conv(iconv_t cd, const char **inbuf, size_t *inbytesleft,
342 char **outbuf, size_t *outbytesleft)
343 {
344 const char* buf_in = inbuf && *inbuf ? *inbuf : NULL;
345 char* buf_out = outbuf && *outbuf ? *outbuf : NULL;
346
347 if (buf_in)
348 {
349 int in_len = inbytesleft ? *inbytesleft : 0;
350 int out_len = outbytesleft ? *outbytesleft : 0;
351
352 if (!buf_out || out_len <= 0)
353 {
354 last_errno = E2BIG;
355 return -1;
356 }
357 else if (in_len > 0)
358 {
359 int len = in_len < out_len ? in_len : out_len;
360
361 memcpy (buf_out, buf_in, len);
362 *inbuf += len;
363 *outbuf += len;
364 *inbytesleft -= len;
365 *outbytesleft -= len;
366 if (*outbytesleft <= 0)
367 {
368 last_errno = E2BIG;
369 return -1;
370 }
371 }
372 }
373 last_errno = 0;
374 return 0;
375 }
376
377 size_t
378 iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft,
379 char **outbuf, size_t *outbytesleft)
380 {
381 ConstTextPtr buf_in;
382 TextPtr buf_out;
383 ByteCount out_len, out_true;
384 ByteCount in_len, in_true;
385 OSStatus st;
386
387 if (!cd)
388 {
389 last_errno = ENOENT; /* TODO: Another error code should be set */
390 return -1;
391 }
392 if (cd->from == cd->to)
393 return null_conv(cd, inbuf, inbytesleft, outbuf, outbytesleft) ;
394
395 buf_in = (TextPtr) inbuf ;
396 buf_out = (TextPtr) outbuf ;
397 out_len = out_true = -1;
398 in_len = in_true = -1;
399
400 if (buf_in && buf_out)
401 {
402 ItemCount error, feature;
403
404 /* Normal convert mode */
405 if (!inbytesleft || !outbytesleft)
406 {
407 last_errno = EFAULT;
408 return -1;
409 }
410 in_len = *inbytesleft;
411 out_len = *outbytesleft;
412
413 /* Check stream is form in expected encoding or not */
414 st = TECSniffTextEncoding(cd->sniff, (TextPtr)buf_in, in_len,
415 &cd->from, 1, &error, 1, &feature, 1);
416 TRACE("TECSniffTextEncoding()=%d error=%d feature=%d\n",
417 (int)st, (int)error, (int)feature);
418 if ((error != 0 || feature == 0)
419 && !(error == 0xffffffff && feature == 0xffffffff))
420 /* Not expected encoding */
421 st = kTECUnmappableElementErr;
422 else
423 {
424 /* Do convert */
425 st = TECConvertText(cd->tec,
426 buf_in, in_len, &in_true,
427 buf_out, out_len, &out_true);
428 /* Verify converted text. Compare original text with reverse
429 * converted text. If not match, there is some problem on
430 * converting. */
431 if (st == 0 && in_true > 0)
432 {
433 ByteCount rev_in, rev_out;
434 TextPtr buf_rev = (TextPtr)alloc(in_true);
435
436 if (buf_rev)
437 {
438 st = TECConvertText(cd->tecReverse,
439 buf_out, out_true, &rev_in,
440 buf_rev, in_true, &rev_out);
441 if (st != 0 || rev_in != out_true || rev_out != in_true
442 || memcmp(buf_rev, buf_in, rev_out) != 0)
443 {
444 #ifdef ICONVOSX_DEBUG
445 fprintf(stderr, " reverse conversion failed.\n");
446 #endif
447 st = kTECUnmappableElementErr;
448 }
449 vim_free(buf_rev);
450 }
451 else
452 st = kTECUnmappableElementErr;
453 }
454 }
455 }
456 else if (!buf_in && buf_out)
457 {
458 /* Flush all buffered strings to buffer, and reset status */
459 if (!outbytesleft)
460 {
461 last_errno = EFAULT;
462 return -1;
463 }
464 out_len = *outbytesleft;
465 st = TECFlushText(cd->tec,
466 buf_out, out_len, &out_true);
467 }
468 else if (!buf_in && !buf_out)
469 {
470 /* Reset cd's status and cancel buffered strings */
471 unsigned char tmp_out[256];
472
473 buf_out = tmp_out;
474 out_len = sizeof(tmp_out);
475 st = TECFlushText(cd->tec,
476 buf_out, out_len, &out_true);
477 }
478 else
479 {
480 last_errno = EFAULT;
481 return -1;
482 }
483 TRACE("st=%d, buf_in=%p, in_len=%d, in_true=%d\n"
484 " buf_out=%p, out_len=%d, out_true=%d\n", (int)st,
485 buf_in, (int)in_len, (int)in_true,
486 buf_out, (int)out_len, (int)out_true);
487
488 switch (st)
489 {
490 case 0:
491 /* No error */
492 if (inbytesleft)
493 *inbytesleft -= in_true;
494 if (outbytesleft)
495 *outbytesleft -= out_true;
496 if (inbuf && *inbuf)
497 *inbuf += in_true;
498 if (outbuf && *outbuf)
499 *outbuf += out_true;
500 last_errno = 0;
501 return 0; /* No error */
502 case kTECUnmappableElementErr:
503 last_errno = EILSEQ;
504 case kTECIncompleteElementErr:
505 last_errno = EINVAL;
506 case kTECOutputBufferFullStatus:
507 last_errno = E2BIG;
508 return -1;
509 default:
510 TRACE("iconv(%p, %p, %p, %p, %p) failed. (%d)\n",
511 cd, inbuf, inbytesleft, outbuf, outbytesleft, (int)st);
512 last_errno = EFAULT;
513 return -1;
514 }
515 }
516
517 int
518 iconv_close(iconv_t cd)
519 {
520 if (cd)
521 {
522 /* Free all elements of iconv_t */
523 if (cd->tec)
524 TECDisposeConverter(cd->tec);
525 if (cd->tecReverse)
526 TECDisposeConverter(cd->tecReverse);
527 if (cd->sniff)
528 TECDisposeSniffer(cd->sniff);
529 vim_free(cd);
530 last_errno = 0;
531 return 0;
532 }
533 else
534 {
535 last_errno = EINVAL;
536 return -1;
537 }
538 }
539
540 int *
541 iconv_errno()
542 {
543 return &last_errno;
544 }
545 #endif /* MACOS_X_ICONVEMU */
546
547 #ifdef USE_MCH_GETTEXT
548
549 #define GETTEXT_BUFNUM 64
550 #define GETTEXT_BUFSIZE 256
551
552 char *
553 mch_gettext(const char *msgid)
554 {
555 static char buf[GETTEXT_BUFNUM][GETTEXT_BUFSIZE];
556 static int bufnum = 0;
557 const char *msg = NULL;
558 CFStringRef strkey = NULL, strmsg = NULL;
559 CFStringEncoding enc;
560
561 if (!msgid)
562 goto MCH_GETTEXT_FINISH;
563 enc = CFStringGetSystemEncoding();
564 TRACE("mch_gettext(%s)\n", msgid);
565
566 strkey = CFStringCreateWithCString(NULL, msgid, enc);
567 if (!strkey)
568 {
569 TRACE(" Can't create a CFString for msgid.\n");
570 goto MCH_GETTEXT_FINISH;
571 }
572
573 strmsg = CFCopyLocalizedString(strkey, NULL);
574 if (!strmsg)
575 {
576 TRACE(" No localized strings for msgid.\n");
577 goto MCH_GETTEXT_FINISH;
578 }
579
580 msg = CFStringGetCStringPtr(strmsg, enc);
581 if (!msg)
582 {
583 /* This is as backup when CFStringGetCStringPtr was failed */
584 CFStringGetCString(strmsg, buf[bufnum], GETTEXT_BUFSIZE, enc);
585 msg = buf[bufnum];
586 if (++bufnum >= GETTEXT_BUFNUM)
587 bufnum = 0;
588 }
589 TRACE(" Localized to: %s\n", msg);
590
591 MCH_GETTEXT_FINISH:
592 if (strkey)
593 CFRelease(strkey);
594 if (strmsg)
595 CFRelease(strmsg);
596 return (char *)(msg ? msg : msgid);
597 }
598
599 char *
600 mch_bindtextdomain(const char *domain, const char *dirname)
601 {
602 TRACE("mch_bindtextdomain(%s, %s)\n", domain, dirname);
603 return (char*)dirname;
604 }
605
606 char *
607 mch_textdomain(const char *domain)
608 {
609 TRACE("mch_textdomain(%s)\n", domain);
610 return (char*)domain;
611 }
612 #endif
613
614
615
616 #ifdef FEAT_CLIPBOARD
617
618 void
619 clip_mch_lose_selection(VimClipboard *cbd)
620 {
621 }
622
623
624 int
625 clip_mch_own_selection(VimClipboard *cbd)
626 {
627 /* This is called whenever there is a new selection and 'guioptions'
628 * contains the "a" flag (automatically copy selection). Return TRUE, else
629 * the "a" flag does nothing. Note that there is no concept of "ownership"
630 * of the clipboard in Mac OS X.
631 */
632 return TRUE;
633 }
634
635
636 void
637 clip_mch_request_selection(VimClipboard *cbd)
638 {
639 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
640
641 NSPasteboard *pb = [NSPasteboard generalPasteboard];
642 NSArray *supportedTypes = [NSArray arrayWithObjects:VimPboardType,
643 NSStringPboardType, nil];
644 NSString *bestType = [pb availableTypeFromArray:supportedTypes];
645 if (!bestType) goto releasepool;
646
647 int motion_type = MCHAR;
648 NSString *string = nil;
649
650 if ([bestType isEqual:VimPboardType])
651 {
652 /* This type should consist of an array with two objects:
653 * 1. motion type (NSNumber)
654 * 2. text (NSString)
655 * If this is not the case we fall back on using NSStringPboardType.
656 */
657 id plist = [pb propertyListForType:VimPboardType];
658 if ([plist isKindOfClass:[NSArray class]] && [plist count] == 2)
659 {
660 id obj = [plist objectAtIndex:1];
661 if ([obj isKindOfClass:[NSString class]])
662 {
663 motion_type = [[plist objectAtIndex:0] intValue];
664 string = obj;
665 }
666 }
667 }
668
669 if (!string)
670 {
671 /* Use NSStringPboardType. The motion type is set to line-wise if the
672 * string contains at least one EOL character, otherwise it is set to
673 * character-wise (block-wise is never used).
674 */
675 NSMutableString *mstring =
676 [[pb stringForType:NSStringPboardType] mutableCopy];
677 if (!mstring) goto releasepool;
678
679 /* Replace unrecognized end-of-line sequences with \x0a (line feed). */
680 NSRange range = { 0, [mstring length] };
681 unsigned n = [mstring replaceOccurrencesOfString:@"\x0d\x0a"
682 withString:@"\x0a" options:0
683 range:range];
684 if (0 == n)
685 {
686 n = [mstring replaceOccurrencesOfString:@"\x0d" withString:@"\x0a"
687 options:0 range:range];
688 }
689
690 /* Scan for newline character to decide whether the string should be
691 * pasted line-wise or character-wise.
692 */
693 motion_type = MCHAR;
694 if (0 < n || NSNotFound != [mstring rangeOfString:@"\n"].location)
695 motion_type = MLINE;
696
697 string = mstring;
698 }
699
700 if (!(MCHAR == motion_type || MLINE == motion_type || MBLOCK == motion_type
701 || MAUTO == motion_type))
702 motion_type = MCHAR;
703
704 char_u *str = (char_u*)[string UTF8String];
705 int len = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
706
707 #ifdef FEAT_MBYTE
708 if (input_conv.vc_type != CONV_NONE)
709 str = string_convert(&input_conv, str, &len);
710 #endif
711
712 if (str)
713 clip_yank_selection(motion_type, str, len, cbd);
714
715 #ifdef FEAT_MBYTE
716 if (input_conv.vc_type != CONV_NONE)
717 vim_free(str);
718 #endif
719
720 releasepool:
721 [pool release];
722 }
723
724
725 /*
726 * Send the current selection to the clipboard.
727 */
728 void
729 clip_mch_set_selection(VimClipboard *cbd)
730 {
731 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
732
733 /* If the '*' register isn't already filled in, fill it in now. */
734 cbd->owned = TRUE;
735 clip_get_selection(cbd);
736 cbd->owned = FALSE;
737
738 /* Get the text to put on the pasteboard. */
739 long_u llen = 0; char_u *str = 0;
740 int motion_type = clip_convert_selection(&str, &llen, cbd);
741 if (motion_type < 0)
742 goto releasepool;
743
744 /* TODO: Avoid overflow. */
745 int len = (int)llen;
746 #ifdef FEAT_MBYTE
747 if (output_conv.vc_type != CONV_NONE)
748 {
749 char_u *conv_str = string_convert(&output_conv, str, &len);
750 if (conv_str)
751 {
752 vim_free(str);
753 str = conv_str;
754 }
755 }
756 #endif
757
758 if (len > 0)
759 {
760 NSString *string = [[NSString alloc]
761 initWithBytes:str length:len encoding:NSUTF8StringEncoding];
762
763 /* See clip_mch_request_selection() for info on pasteboard types. */
764 NSPasteboard *pb = [NSPasteboard generalPasteboard];
765 NSArray *supportedTypes = [NSArray arrayWithObjects:VimPboardType,
766 NSStringPboardType, nil];
767 [pb declareTypes:supportedTypes owner:nil];
768
769 NSNumber *motion = [NSNumber numberWithInt:motion_type];
770 NSArray *plist = [NSArray arrayWithObjects:motion, string, nil];
771 [pb setPropertyList:plist forType:VimPboardType];
772
773 [pb setString:string forType:NSStringPboardType];
774
775 [string release];
776 }
777
778 vim_free(str);
779 releasepool:
780 [pool release];
781 }
782
783 #endif /* FEAT_CLIPBOARD */