1/* 2 3 Copyright (c) 2009 MacUIM Project http://code.google.com/p/macuim/ 4 5 All rights reserved. 6 7 Redistribution and use in source and binary forms, with or without 8 modification, are permitted provided that the following conditions 9 are met: 10 11 1. Redistributions of source code must retain the above copyright 12 notice, this list of conditions and the following disclaimer. 13 2. Redistributions in binary form must reproduce the above copyright 14 notice, this list of conditions and the following disclaimer in the 15 documentation and/or other materials provided with the distribution. 16 3. Neither the name of authors nor the names of its contributors 17 may be used to endorse or promote products derived from this software 18 without specific prior written permission. 19 20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND 21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE 24 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 SUCH DAMAGE. 31 32*/ 33 34#import "MacUIMController.h" 35#import "UimHelperController.h" 36 37static UimHelperController *sharedController; 38 39static void helperRead(CFSocketRef sock, CFSocketCallBackType callbackType, 40 CFDataRef address, const void *data, void *info) 41{ 42 [sharedController helperRead:(CFSocketRef)sock]; 43} 44 45static void helperDisconnect() 46{ 47 [sharedController helperDisconnect]; 48} 49 50@implementation UimHelperController 51 52+ (id)sharedController 53{ 54 if (!sharedController) 55 [[self alloc] init]; 56 57 return sharedController; 58} 59 60- (id)init 61{ 62 if (sharedController) 63 return sharedController; 64 65 self = [super init]; 66 sharedController = self; 67 68 uimRun = NULL; 69 uimSock = NULL; 70 uimFD = -1; 71 isMacUIMfocused = YES; 72 73 return self; 74} 75 76- (void)dealloc 77{ 78 sharedController = nil; 79 [super dealloc]; 80} 81 82- (void)checkHelperConnection 83{ 84 if (uimFD != -1) 85 return; /* already connected */ 86 87 uimFD = uim_helper_init_client_fd(helperDisconnect); 88 if (uimFD == -1) 89 return; 90 91 if (!uimSock) { 92 CFSocketContext sockContext; 93 94 sockContext.version = 0; 95 sockContext.info = NULL; 96 sockContext.retain = NULL; 97 sockContext.release = NULL; 98 sockContext.copyDescription = NULL; 99 100 uimSock = CFSocketCreateWithNative(kCFAllocatorDefault, 101 uimFD, 102 kCFSocketReadCallBack, 103 helperRead, 104 &sockContext); 105 106 if (!uimSock) 107 return; 108 109 } 110 111 if (!uimRun) { 112 uimRun = CFSocketCreateRunLoopSource(kCFAllocatorDefault, 113 uimSock, 0); 114 if (!uimRun) { 115 CFRelease(uimSock); 116 uimSock = NULL; 117 return; 118 } 119 CFRunLoopAddSource(CFRunLoopGetCurrent(), uimRun, 120 kCFRunLoopDefaultMode); 121 } 122} 123 124- (void)helperRead:(CFSocketRef)sock; 125{ 126 char *msg; 127 128 uim_helper_read_proc(CFSocketGetNative(sock)); 129 while ((msg = uim_helper_get_message())) { 130 [self parseHelperString:msg]; 131 free(msg); 132 } 133} 134 135- (void)parseHelperString:(const char *)str 136{ 137 MacUIMController *activeContext; 138 139 activeContext = [MacUIMController activeContext]; 140 141 if (strncmp("im_change", str, 9) == 0) { 142 [self parseIMChangeString:str]; 143 } else if (strncmp("prop_update_custom", str, 18) == 0) { 144 CFMutableStringRef cfstr; 145 CFArrayRef array; 146 CFIndex count; 147 148 cfstr = CFStringCreateMutable(NULL, 0); 149 CFStringAppendCString(cfstr, str, kCFStringEncodingUTF8); 150 151 array = CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault, cfstr, CFSTR("\n")); 152 153 if (array && (count = CFArrayGetCount(array)) >= 3) { 154 CFStringRef second = CFArrayGetValueAtIndex(array, 1); 155 CFStringRef third = CFArrayGetValueAtIndex(array, 2); 156 if (second && third) { 157 int custom_len_max = CFStringGetMaximumSizeForEncoding(CFStringGetLength(second), kCFStringEncodingUTF8); 158 int val_len_max = CFStringGetMaximumSizeForEncoding(CFStringGetLength(third), kCFStringEncodingUTF8); 159 char custom[custom_len_max]; 160 char val[val_len_max]; 161 162 CFStringGetCString(second, custom, 163 custom_len_max, 164 kCFStringEncodingUTF8); 165 CFStringGetCString(third, val, 166 val_len_max, 167 kCFStringEncodingUTF8); 168 [MacUIMController updateCustom:custom:val]; 169 } 170 } 171 CFRelease(array); 172 CFRelease(cfstr); 173 } else if (strncmp("custom_reload_notify", str, 20) == 0) { 174 uim_prop_reload_configs(); 175 } else if (isMacUIMfocused) { 176 if (strncmp("prop_list_get", str, 13) == 0) { 177 uim_prop_list_update([activeContext uc]); 178 } else if (strncmp("prop_activate", str, 13) == 0) { 179 CFMutableStringRef cfstr; 180 CFArrayRef array; 181 182 cfstr = CFStringCreateMutable(NULL, 0); 183 CFStringAppendCString(cfstr, str, kCFStringEncodingUTF8); 184 //NSLog(@"prop_activate: %@", (NSString *)cfstr); 185 186 array = CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault, cfstr, CFSTR("\n")); 187 188 if (array && (CFArrayGetCount(array) >= 2)) { 189 CFStringRef second; 190 second = CFArrayGetValueAtIndex(array, 1); 191 if (second) { 192 int max = CFStringGetMaximumSizeForEncoding(CFStringGetLength(second), kCFStringEncodingUTF8); 193 char how[max]; 194 CFStringGetCString(second, how, max, 195 kCFStringEncodingUTF8); 196 //BlockUpdatePreedit(); 197 //NSLog(@"call uim_prop_activate %@", (NSString *)second); 198 uim_prop_activate([activeContext uc], how); 199 //UnblockUpdatePreedit(); 200 } 201 } 202 CFRelease(array); 203 CFRelease(cfstr); 204 } else if (strncmp("focus_in", str, 8) == 0) { 205 isMacUIMfocused = NO; 206 } 207 } 208} 209 210// just do whole IM switch in MacUIM 211- (void)parseIMChangeString:(const char *)str 212{ 213 char *eol, *im; 214 215 eol = strchr(str, '\n'); 216 if (eol == NULL) 217 return; 218 im = eol + 1; 219 eol = strchr(im, '\n'); 220 if (eol == NULL) 221 return; 222 *eol = '\0'; 223 224 [MacUIMController switchIM:im]; 225} 226 227- (void)helperDisconnect 228{ 229 NSLog(@"helperDisconnect"); 230 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), uimRun, 231 kCFRunLoopDefaultMode); 232 CFRelease(uimRun); 233 CFRelease(uimSock); 234 235 uimRun = NULL; 236 uimSock = NULL; 237 uimFD = -1; 238} 239 240- (void)focusIn:(uim_context)uc 241{ 242 uim_helper_client_focus_in(uc); 243 isMacUIMfocused = YES; 244} 245 246- (void)focusOut:(uim_context)uc 247{ 248 uim_helper_client_focus_out(uc); 249} 250 251- (void)send:(const char *)string 252{ 253 uim_helper_send_message(uimFD, string); 254} 255 256@end 257