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