xref: /vim-8.2.3635/src/os_macosx.m (revision 94688b8a)
1/* vi:set ts=8 sts=4 sw=4 noet:
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/* Suppress compiler warnings to non-C89 code. */
15#if defined(__clang__) && defined(__STRICT_ANSI__)
16# pragma clang diagnostic push
17# pragma clang diagnostic ignored "-Wc99-extensions"
18# pragma clang diagnostic push
19# pragma clang diagnostic ignored "-Wdeclaration-after-statement"
20#endif
21
22/* Avoid a conflict for the definition of Boolean between Mac header files and
23 * X11 header files. */
24#define NO_X11_INCLUDES
25
26#include "vim.h"
27#import <AppKit/AppKit.h>
28
29
30/*
31 * Clipboard support for the console.
32 * Don't include this when building the GUI version, the functions in
33 * gui_mac.c are used then.  TODO: remove those instead?
34 * But for MacVim we do need these ones.
35 */
36#if defined(FEAT_CLIPBOARD) && (!defined(FEAT_GUI_ENABLED) || defined(FEAT_GUI_MACVIM))
37
38/* Used to identify clipboard data copied from Vim. */
39
40NSString *VimPboardType = @"VimPboardType";
41
42    void
43clip_mch_lose_selection(VimClipboard *cbd UNUSED)
44{
45}
46
47
48    int
49clip_mch_own_selection(VimClipboard *cbd UNUSED)
50{
51    /* This is called whenever there is a new selection and 'guioptions'
52     * contains the "a" flag (automatically copy selection).  Return TRUE, else
53     * the "a" flag does nothing.  Note that there is no concept of "ownership"
54     * of the clipboard in Mac OS X.
55     */
56    return TRUE;
57}
58
59
60    void
61clip_mch_request_selection(VimClipboard *cbd)
62{
63    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
64
65    NSPasteboard *pb = [NSPasteboard generalPasteboard];
66#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
67    NSArray *supportedTypes = [NSArray arrayWithObjects:VimPboardType,
68	    NSPasteboardTypeString, nil];
69#else
70    NSArray *supportedTypes = [NSArray arrayWithObjects:VimPboardType,
71	    NSStringPboardType, nil];
72#endif
73    NSString *bestType = [pb availableTypeFromArray:supportedTypes];
74    if (!bestType) goto releasepool;
75
76    int motion_type = MAUTO;
77    NSString *string = nil;
78
79    if ([bestType isEqual:VimPboardType])
80    {
81	/* This type should consist of an array with two objects:
82	 *   1. motion type (NSNumber)
83	 *   2. text (NSString)
84	 * If this is not the case we fall back on using NSPasteboardTypeString.
85	 */
86	id plist = [pb propertyListForType:VimPboardType];
87	if ([plist isKindOfClass:[NSArray class]] && [plist count] == 2)
88	{
89	    id obj = [plist objectAtIndex:1];
90	    if ([obj isKindOfClass:[NSString class]])
91	    {
92		motion_type = [[plist objectAtIndex:0] intValue];
93		string = obj;
94	    }
95	}
96    }
97
98    if (!string)
99    {
100	/* Use NSPasteboardTypeString.  The motion type is detected automatically.
101	 */
102#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
103	NSMutableString *mstring =
104		[[pb stringForType:NSPasteboardTypeString] mutableCopy];
105#else
106	NSMutableString *mstring =
107		[[pb stringForType:NSStringPboardType] mutableCopy];
108#endif
109	if (!mstring) goto releasepool;
110
111	/* Replace unrecognized end-of-line sequences with \x0a (line feed). */
112	NSRange range = { 0, [mstring length] };
113	unsigned n = [mstring replaceOccurrencesOfString:@"\x0d\x0a"
114					     withString:@"\x0a" options:0
115						  range:range];
116	if (0 == n)
117	{
118	    n = [mstring replaceOccurrencesOfString:@"\x0d" withString:@"\x0a"
119					   options:0 range:range];
120	}
121
122	string = mstring;
123    }
124
125    /* Default to MAUTO, uses MCHAR or MLINE depending on trailing NL. */
126    if (!(MCHAR == motion_type || MLINE == motion_type || MBLOCK == motion_type
127	    || MAUTO == motion_type))
128	motion_type = MAUTO;
129
130    char_u *str = (char_u*)[string UTF8String];
131    int len = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
132
133    if (input_conv.vc_type != CONV_NONE)
134	str = string_convert(&input_conv, str, &len);
135
136    if (str)
137	clip_yank_selection(motion_type, str, len, cbd);
138
139    if (input_conv.vc_type != CONV_NONE)
140	vim_free(str);
141
142releasepool:
143    [pool release];
144}
145
146
147/*
148 * Send the current selection to the clipboard.
149 */
150    void
151clip_mch_set_selection(VimClipboard *cbd)
152{
153    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
154
155    /* If the '*' register isn't already filled in, fill it in now. */
156    cbd->owned = TRUE;
157    clip_get_selection(cbd);
158    cbd->owned = FALSE;
159
160    /* Get the text to put on the pasteboard. */
161    long_u llen = 0; char_u *str = 0;
162    int motion_type = clip_convert_selection(&str, &llen, cbd);
163    if (motion_type < 0)
164	goto releasepool;
165
166    /* TODO: Avoid overflow. */
167    int len = (int)llen;
168    if (output_conv.vc_type != CONV_NONE)
169    {
170	char_u *conv_str = string_convert(&output_conv, str, &len);
171	if (conv_str)
172	{
173	    vim_free(str);
174	    str = conv_str;
175	}
176    }
177
178    if (len > 0)
179    {
180	NSString *string = [[NSString alloc]
181	    initWithBytes:str length:len encoding:NSUTF8StringEncoding];
182
183	/* See clip_mch_request_selection() for info on pasteboard types. */
184	NSPasteboard *pb = [NSPasteboard generalPasteboard];
185#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
186	NSArray *supportedTypes = [NSArray arrayWithObjects:VimPboardType,
187		NSPasteboardTypeString, nil];
188#else
189	NSArray *supportedTypes = [NSArray arrayWithObjects:VimPboardType,
190		NSStringPboardType, nil];
191#endif
192	[pb declareTypes:supportedTypes owner:nil];
193
194	NSNumber *motion = [NSNumber numberWithInt:motion_type];
195	NSArray *plist = [NSArray arrayWithObjects:motion, string, nil];
196	[pb setPropertyList:plist forType:VimPboardType];
197
198#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
199	[pb setString:string forType:NSPasteboardTypeString];
200#else
201	[pb setString:string forType:NSStringPboardType];
202#endif
203
204	[string release];
205    }
206
207    vim_free(str);
208releasepool:
209    [pool release];
210}
211
212#endif /* FEAT_CLIPBOARD */
213
214/* Lift the compiler warning suppression. */
215#if defined(__clang__) && defined(__STRICT_ANSI__)
216# pragma clang diagnostic pop
217# pragma clang diagnostic pop
218#endif
219