blob: 34a7012120e97e722255f8f4e43e9db2ce6ec64b [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
Bram Moolenaar164fca32010-07-14 13:58:07 +020022#ifdef FEAT_CLIPBOARD
23
Bram Moolenaar66bd1c92010-07-14 20:31:44 +020024/* Used to identify clipboard data copied from Vim. */
25
26NSString *VimPboardType = @"VimPboardType";
27
Bram Moolenaar164fca32010-07-14 13:58:07 +020028 void
29clip_mch_lose_selection(VimClipboard *cbd)
30{
31}
32
33
34 int
35clip_mch_own_selection(VimClipboard *cbd)
36{
37 /* This is called whenever there is a new selection and 'guioptions'
38 * contains the "a" flag (automatically copy selection). Return TRUE, else
39 * the "a" flag does nothing. Note that there is no concept of "ownership"
40 * of the clipboard in Mac OS X.
41 */
42 return TRUE;
43}
44
45
46 void
47clip_mch_request_selection(VimClipboard *cbd)
48{
49 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
50
51 NSPasteboard *pb = [NSPasteboard generalPasteboard];
52 NSArray *supportedTypes = [NSArray arrayWithObjects:VimPboardType,
53 NSStringPboardType, nil];
54 NSString *bestType = [pb availableTypeFromArray:supportedTypes];
55 if (!bestType) goto releasepool;
56
57 int motion_type = MCHAR;
58 NSString *string = nil;
59
60 if ([bestType isEqual:VimPboardType])
61 {
62 /* This type should consist of an array with two objects:
63 * 1. motion type (NSNumber)
64 * 2. text (NSString)
65 * If this is not the case we fall back on using NSStringPboardType.
66 */
67 id plist = [pb propertyListForType:VimPboardType];
68 if ([plist isKindOfClass:[NSArray class]] && [plist count] == 2)
69 {
70 id obj = [plist objectAtIndex:1];
71 if ([obj isKindOfClass:[NSString class]])
72 {
73 motion_type = [[plist objectAtIndex:0] intValue];
74 string = obj;
75 }
76 }
77 }
78
79 if (!string)
80 {
81 /* Use NSStringPboardType. The motion type is set to line-wise if the
82 * string contains at least one EOL character, otherwise it is set to
83 * character-wise (block-wise is never used).
84 */
85 NSMutableString *mstring =
86 [[pb stringForType:NSStringPboardType] mutableCopy];
87 if (!mstring) goto releasepool;
88
89 /* Replace unrecognized end-of-line sequences with \x0a (line feed). */
90 NSRange range = { 0, [mstring length] };
91 unsigned n = [mstring replaceOccurrencesOfString:@"\x0d\x0a"
92 withString:@"\x0a" options:0
93 range:range];
94 if (0 == n)
95 {
96 n = [mstring replaceOccurrencesOfString:@"\x0d" withString:@"\x0a"
97 options:0 range:range];
98 }
Bram Moolenaard43848c2010-07-14 14:28:26 +020099
Bram Moolenaar164fca32010-07-14 13:58:07 +0200100 /* Scan for newline character to decide whether the string should be
101 * pasted line-wise or character-wise.
102 */
103 motion_type = MCHAR;
104 if (0 < n || NSNotFound != [mstring rangeOfString:@"\n"].location)
105 motion_type = MLINE;
106
107 string = mstring;
108 }
109
110 if (!(MCHAR == motion_type || MLINE == motion_type || MBLOCK == motion_type
111 || MAUTO == motion_type))
112 motion_type = MCHAR;
113
114 char_u *str = (char_u*)[string UTF8String];
115 int len = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
116
117#ifdef FEAT_MBYTE
118 if (input_conv.vc_type != CONV_NONE)
119 str = string_convert(&input_conv, str, &len);
120#endif
121
122 if (str)
123 clip_yank_selection(motion_type, str, len, cbd);
124
125#ifdef FEAT_MBYTE
126 if (input_conv.vc_type != CONV_NONE)
127 vim_free(str);
128#endif
129
130releasepool:
131 [pool release];
132}
133
134
135/*
136 * Send the current selection to the clipboard.
137 */
138 void
139clip_mch_set_selection(VimClipboard *cbd)
140{
141 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
142
143 /* If the '*' register isn't already filled in, fill it in now. */
144 cbd->owned = TRUE;
145 clip_get_selection(cbd);
146 cbd->owned = FALSE;
Bram Moolenaard43848c2010-07-14 14:28:26 +0200147
Bram Moolenaar164fca32010-07-14 13:58:07 +0200148 /* Get the text to put on the pasteboard. */
149 long_u llen = 0; char_u *str = 0;
150 int motion_type = clip_convert_selection(&str, &llen, cbd);
151 if (motion_type < 0)
152 goto releasepool;
153
154 /* TODO: Avoid overflow. */
155 int len = (int)llen;
156#ifdef FEAT_MBYTE
157 if (output_conv.vc_type != CONV_NONE)
158 {
159 char_u *conv_str = string_convert(&output_conv, str, &len);
160 if (conv_str)
161 {
162 vim_free(str);
163 str = conv_str;
164 }
165 }
166#endif
167
168 if (len > 0)
169 {
170 NSString *string = [[NSString alloc]
171 initWithBytes:str length:len encoding:NSUTF8StringEncoding];
172
173 /* See clip_mch_request_selection() for info on pasteboard types. */
174 NSPasteboard *pb = [NSPasteboard generalPasteboard];
175 NSArray *supportedTypes = [NSArray arrayWithObjects:VimPboardType,
176 NSStringPboardType, nil];
177 [pb declareTypes:supportedTypes owner:nil];
178
179 NSNumber *motion = [NSNumber numberWithInt:motion_type];
180 NSArray *plist = [NSArray arrayWithObjects:motion, string, nil];
181 [pb setPropertyList:plist forType:VimPboardType];
182
183 [pb setString:string forType:NSStringPboardType];
Bram Moolenaard43848c2010-07-14 14:28:26 +0200184
Bram Moolenaar164fca32010-07-14 13:58:07 +0200185 [string release];
186 }
187
188 vim_free(str);
189releasepool:
190 [pool release];
191}
192
193#endif /* FEAT_CLIPBOARD */