blob: 619e86d691ec153163e8a5130e7526b36f4a3e64 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* 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/*
Bram Moolenaar164fca32010-07-14 13:58:07 +020011 * os_macosx.m -- Mac specific things for Mac OS/X.
Bram Moolenaar071d4272004-06-13 20:20:40 +000012 */
13
Bram Moolenaar164fca32010-07-14 13:58:07 +020014#ifndef MACOS_X_UNIX
Bram Moolenaar9372a112005-12-06 19:59:18 +000015 Error: MACOS 9 is no longer supported in Vim 7
Bram Moolenaar071d4272004-06-13 20:20:40 +000016#endif
17
Bram Moolenaar164fca32010-07-14 13:58:07 +020018#include "vim.h"
19#import <Cocoa/Cocoa.h>
20
21
22NSString *VimPboardType = @"VimPboardType";
23
24
Bram Moolenaar071d4272004-06-13 20:20:40 +000025#ifdef _DEBUG
26 void
27Trace(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
44struct _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
55static int last_errno = 0;
56
57/*
58 * Get TextEncoding from iconv's encoding name
59 */
60 static TextEncoding
61get_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},
Bram Moolenaar78622822005-08-23 21:00:13 +000087 {"iso-8859-15", kTextEncodingISOLatin9},
Bram Moolenaar071d4272004-06-13 20:20:40 +000088
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
279iconv_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;
Bram Moolenaar7db5fc82010-05-24 11:59:29 +0200295 vim_memset(cd, 0, sizeof(struct _iconv_t));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000296
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
328ICONV_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
Bram Moolenaarab79bcb2004-07-18 21:34:53 +0000341null_conv(iconv_t cd, const char **inbuf, size_t *inbytesleft,
342 char **outbuf, size_t *outbytesleft)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000343{
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
Bram Moolenaarab79bcb2004-07-18 21:34:53 +0000378iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft,
379 char **outbuf, size_t *outbytesleft)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000380{
Bram Moolenaarab79bcb2004-07-18 21:34:53 +0000381 ConstTextPtr buf_in;
382 TextPtr buf_out;
383 ByteCount out_len, out_true;
384 ByteCount in_len, in_true;
385 OSStatus st;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000386
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
518iconv_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
Bram Moolenaarab79bcb2004-07-18 21:34:53 +0000540 int *
Bram Moolenaar071d4272004-06-13 20:20:40 +0000541iconv_errno()
542{
543 return &last_errno;
544}
545#endif /* MACOS_X_ICONVEMU */
546
Bram Moolenaar164fca32010-07-14 13:58:07 +0200547#ifdef FEAT_CLIPBOARD
548
549 void
550clip_mch_lose_selection(VimClipboard *cbd)
551{
552}
553
554
555 int
556clip_mch_own_selection(VimClipboard *cbd)
557{
558 /* This is called whenever there is a new selection and 'guioptions'
559 * contains the "a" flag (automatically copy selection). Return TRUE, else
560 * the "a" flag does nothing. Note that there is no concept of "ownership"
561 * of the clipboard in Mac OS X.
562 */
563 return TRUE;
564}
565
566
567 void
568clip_mch_request_selection(VimClipboard *cbd)
569{
570 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
571
572 NSPasteboard *pb = [NSPasteboard generalPasteboard];
573 NSArray *supportedTypes = [NSArray arrayWithObjects:VimPboardType,
574 NSStringPboardType, nil];
575 NSString *bestType = [pb availableTypeFromArray:supportedTypes];
576 if (!bestType) goto releasepool;
577
578 int motion_type = MCHAR;
579 NSString *string = nil;
580
581 if ([bestType isEqual:VimPboardType])
582 {
583 /* This type should consist of an array with two objects:
584 * 1. motion type (NSNumber)
585 * 2. text (NSString)
586 * If this is not the case we fall back on using NSStringPboardType.
587 */
588 id plist = [pb propertyListForType:VimPboardType];
589 if ([plist isKindOfClass:[NSArray class]] && [plist count] == 2)
590 {
591 id obj = [plist objectAtIndex:1];
592 if ([obj isKindOfClass:[NSString class]])
593 {
594 motion_type = [[plist objectAtIndex:0] intValue];
595 string = obj;
596 }
597 }
598 }
599
600 if (!string)
601 {
602 /* Use NSStringPboardType. The motion type is set to line-wise if the
603 * string contains at least one EOL character, otherwise it is set to
604 * character-wise (block-wise is never used).
605 */
606 NSMutableString *mstring =
607 [[pb stringForType:NSStringPboardType] mutableCopy];
608 if (!mstring) goto releasepool;
609
610 /* Replace unrecognized end-of-line sequences with \x0a (line feed). */
611 NSRange range = { 0, [mstring length] };
612 unsigned n = [mstring replaceOccurrencesOfString:@"\x0d\x0a"
613 withString:@"\x0a" options:0
614 range:range];
615 if (0 == n)
616 {
617 n = [mstring replaceOccurrencesOfString:@"\x0d" withString:@"\x0a"
618 options:0 range:range];
619 }
Bram Moolenaard43848c2010-07-14 14:28:26 +0200620
Bram Moolenaar164fca32010-07-14 13:58:07 +0200621 /* Scan for newline character to decide whether the string should be
622 * pasted line-wise or character-wise.
623 */
624 motion_type = MCHAR;
625 if (0 < n || NSNotFound != [mstring rangeOfString:@"\n"].location)
626 motion_type = MLINE;
627
628 string = mstring;
629 }
630
631 if (!(MCHAR == motion_type || MLINE == motion_type || MBLOCK == motion_type
632 || MAUTO == motion_type))
633 motion_type = MCHAR;
634
635 char_u *str = (char_u*)[string UTF8String];
636 int len = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
637
638#ifdef FEAT_MBYTE
639 if (input_conv.vc_type != CONV_NONE)
640 str = string_convert(&input_conv, str, &len);
641#endif
642
643 if (str)
644 clip_yank_selection(motion_type, str, len, cbd);
645
646#ifdef FEAT_MBYTE
647 if (input_conv.vc_type != CONV_NONE)
648 vim_free(str);
649#endif
650
651releasepool:
652 [pool release];
653}
654
655
656/*
657 * Send the current selection to the clipboard.
658 */
659 void
660clip_mch_set_selection(VimClipboard *cbd)
661{
662 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
663
664 /* If the '*' register isn't already filled in, fill it in now. */
665 cbd->owned = TRUE;
666 clip_get_selection(cbd);
667 cbd->owned = FALSE;
Bram Moolenaard43848c2010-07-14 14:28:26 +0200668
Bram Moolenaar164fca32010-07-14 13:58:07 +0200669 /* Get the text to put on the pasteboard. */
670 long_u llen = 0; char_u *str = 0;
671 int motion_type = clip_convert_selection(&str, &llen, cbd);
672 if (motion_type < 0)
673 goto releasepool;
674
675 /* TODO: Avoid overflow. */
676 int len = (int)llen;
677#ifdef FEAT_MBYTE
678 if (output_conv.vc_type != CONV_NONE)
679 {
680 char_u *conv_str = string_convert(&output_conv, str, &len);
681 if (conv_str)
682 {
683 vim_free(str);
684 str = conv_str;
685 }
686 }
687#endif
688
689 if (len > 0)
690 {
691 NSString *string = [[NSString alloc]
692 initWithBytes:str length:len encoding:NSUTF8StringEncoding];
693
694 /* See clip_mch_request_selection() for info on pasteboard types. */
695 NSPasteboard *pb = [NSPasteboard generalPasteboard];
696 NSArray *supportedTypes = [NSArray arrayWithObjects:VimPboardType,
697 NSStringPboardType, nil];
698 [pb declareTypes:supportedTypes owner:nil];
699
700 NSNumber *motion = [NSNumber numberWithInt:motion_type];
701 NSArray *plist = [NSArray arrayWithObjects:motion, string, nil];
702 [pb setPropertyList:plist forType:VimPboardType];
703
704 [pb setString:string forType:NSStringPboardType];
Bram Moolenaard43848c2010-07-14 14:28:26 +0200705
Bram Moolenaar164fca32010-07-14 13:58:07 +0200706 [string release];
707 }
708
709 vim_free(str);
710releasepool:
711 [pool release];
712}
713
714#endif /* FEAT_CLIPBOARD */