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