diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..f0b9df629 --- /dev/null +++ b/.clang-format @@ -0,0 +1,2 @@ +BasedOnStyle: Chromium +SortIncludes: false \ No newline at end of file diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000..28fd0c7ef --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,3 @@ +# apply clang format +ce94f9c4403b9c33d5e251fc7f1e15c44725d881 + diff --git a/.github/workflows/commit-ci.yml b/.github/workflows/commit-ci.yml index e2bd4be61..c16cc6bc7 100644 --- a/.github/workflows/commit-ci.yml +++ b/.github/workflows/commit-ci.yml @@ -12,6 +12,12 @@ jobs: with: submodules: true + - name: Install clang-format + run: brew install clang-format + + - name: Lint + run: make clang-format-lint + - name: Configure build environment run: | echo git_ref_name="$(git describe --always)" >> $GITHUB_ENV diff --git a/.github/workflows/pull-request-ci.yml b/.github/workflows/pull-request-ci.yml index 43200eb2c..d2553dea3 100644 --- a/.github/workflows/pull-request-ci.yml +++ b/.github/workflows/pull-request-ci.yml @@ -9,6 +9,12 @@ jobs: with: submodules: true + - name: Install clang-format + run: brew install clang-format + + - name: Lint + run: make clang-format-lint + - name: Configure build environment run: | echo git_ref_name="$(git describe --always)" >> $GITHUB_ENV diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml index 29cb204aa..ebe9eaa25 100644 --- a/.github/workflows/release-ci.yml +++ b/.github/workflows/release-ci.yml @@ -15,6 +15,12 @@ jobs: fetch-depth: 0 submodules: true + - name: Install clang-format + run: brew install clang-format + + - name: Lint + run: make clang-format-lint + - name: Build Squirrel run: ./action-build.sh archive diff --git a/Makefile b/Makefile index bb63620ec..f2314cea0 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ $(RIME_DEPS): $(MAKE) -C librime deps librime: $(RIME_DEPS) - $(MAKE) -C librime install + $(MAKE) -C librime release install $(MAKE) copy-rime-binaries copy-rime-binaries: @@ -78,6 +78,12 @@ copy-opencc-data: deps: librime data +clang-format-lint: + find . -name '*.m' -o -name '*.h' -maxdepth 1 | xargs clang-format -Werror --dry-run || { echo Please lint your code by '"'"make clang-format-apply"'"'.; false; } + +clang-format-apply: + find . -name '*.m' -o -name '*.h' -maxdepth 1 | xargs clang-format --verbose -i + ifdef ARCHS BUILD_SETTINGS += ARCHS="$(ARCHS)" BUILD_SETTINGS += ONLY_ACTIVE_ARCH=NO diff --git a/Squirrel.xcodeproj/project.pbxproj b/Squirrel.xcodeproj/project.pbxproj index 6898ec0ae..c1c4c593e 100644 --- a/Squirrel.xcodeproj/project.pbxproj +++ b/Squirrel.xcodeproj/project.pbxproj @@ -84,6 +84,7 @@ A4FC48CB0F6530EF0069BE81 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A4FC48C90F6530EF0069BE81 /* Localizable.strings */; }; D26434552706A15100857391 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D26434542706A15100857391 /* QuartzCore.framework */; }; E93074B70A5C264700470842 /* InputMethodKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E93074B60A5C264700470842 /* InputMethodKit.framework */; }; + F45E005F2B8CA81C00179B75 /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F45E005E2B8CA81C00179B75 /* UserNotifications.framework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -278,6 +279,7 @@ A4FC48CA0F6530EF0069BE81 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; D26434542706A15100857391 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; E93074B60A5C264700470842 /* InputMethodKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = InputMethodKit.framework; path = /System/Library/Frameworks/InputMethodKit.framework; sourceTree = ""; }; + F45E005E2B8CA81C00179B75 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -287,6 +289,7 @@ files = ( D26434552706A15100857391 /* QuartzCore.framework in Frameworks */, 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, + F45E005F2B8CA81C00179B75 /* UserNotifications.framework in Frameworks */, E93074B70A5C264700470842 /* InputMethodKit.framework in Frameworks */, A4B8E1B30F645B870094E08B /* Carbon.framework in Frameworks */, 447765C925C30E97002415AF /* Sparkle.framework in Frameworks */, @@ -379,6 +382,7 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( + F45E005E2B8CA81C00179B75 /* UserNotifications.framework */, D26434542706A15100857391 /* QuartzCore.framework */, 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, diff --git a/SquirrelApplicationDelegate.h b/SquirrelApplicationDelegate.h index 4f3e421d6..d6284c10b 100644 --- a/SquirrelApplicationDelegate.h +++ b/SquirrelApplicationDelegate.h @@ -3,33 +3,35 @@ @class SquirrelConfig; @class SquirrelPanel; -// Note: the SquirrelApplicationDelegate is instantiated automatically as an outlet of NSApp's instance +// Note: the SquirrelApplicationDelegate is instantiated automatically as an +// outlet of NSApp's instance @interface SquirrelApplicationDelegate : NSObject -@property(nonatomic, copy) IBOutlet NSMenu *menu; -@property(nonatomic, strong) IBOutlet SquirrelPanel *panel; -@property(nonatomic, strong) IBOutlet id updater; +@property(nonatomic, weak) IBOutlet NSMenu* menu; +@property(nonatomic, weak) IBOutlet SquirrelPanel* panel; +@property(nonatomic, weak) IBOutlet id updater; -@property(nonatomic, readonly, strong) SquirrelConfig *config; +@property(nonatomic, readonly, strong) SquirrelConfig* config; @property(nonatomic, readonly) BOOL enableNotifications; --(IBAction)deploy:(id)sender; --(IBAction)syncUserData:(id)sender; --(IBAction)configure:(id)sender; --(IBAction)openWiki:(id)sender; +- (IBAction)deploy:(id)sender; +- (IBAction)syncUserData:(id)sender; +- (IBAction)configure:(id)sender; +- (IBAction)openWiki:(id)sender; --(void)setupRime; --(void)startRimeWithFullCheck:(BOOL)fullCheck; --(void)loadSettings; --(void)loadSchemaSpecificSettings:(NSString *)schemaId; +- (void)setupRime; +- (void)startRimeWithFullCheck:(BOOL)fullCheck; +- (void)loadSettings; +- (void)loadSchemaSpecificSettings:(NSString*)schemaId; -@property (nonatomic, readonly) BOOL problematicLaunchDetected; +@property(nonatomic, readonly) BOOL problematicLaunchDetected; @end @interface NSApplication (SquirrelApp) -@property(nonatomic, readonly, strong) SquirrelApplicationDelegate *squirrelAppDelegate; +@property(nonatomic, readonly, strong) + SquirrelApplicationDelegate* squirrelAppDelegate; @end diff --git a/SquirrelApplicationDelegate.m b/SquirrelApplicationDelegate.m index db1479ab6..647f76de0 100644 --- a/SquirrelApplicationDelegate.m +++ b/SquirrelApplicationDelegate.m @@ -3,75 +3,98 @@ #import #import "SquirrelConfig.h" #import "SquirrelPanel.h" +#import -static NSString *const kRimeWikiURL = @"https://github.com/rime/home/wiki"; +static NSString* const kRimeWikiURL = @"https://github.com/rime/home/wiki"; @implementation SquirrelApplicationDelegate --(IBAction)deploy:(id)sender -{ +- (IBAction)deploy:(id)sender { NSLog(@"Start maintenance..."); [self shutdownRime]; [self startRimeWithFullCheck:YES]; [self loadSettings]; } --(IBAction)syncUserData:(id)sender -{ +- (IBAction)syncUserData:(id)sender { NSLog(@"Sync user data"); rime_get_api()->sync_user_data(); } --(IBAction)configure:(id)sender -{ - [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[@"file://" stringByAppendingString:(@"~/Library/Rime").stringByStandardizingPath]]]; +- (IBAction)configure:(id)sender { + [[NSWorkspace sharedWorkspace] + openURL:[NSURL fileURLWithPath:@"~/Library/Rime/" + .stringByExpandingTildeInPath + isDirectory:YES]]; } --(IBAction)openWiki:(id)sender -{ +- (IBAction)openWiki:(id)sender { [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:kRimeWikiURL]]; } void show_message(const char* msg_text, const char* msg_id) { - @autoreleasepool { - id notification = [[NSClassFromString(@"NSUserNotification") alloc] init]; - [notification performSelector:@selector(setTitle:) - withObject:NSLocalizedString(@"Squirrel", nil)]; - [notification performSelector:@selector(setSubtitle:) - withObject:NSLocalizedString(@(msg_text), nil)]; - id notificationCenter = [(id)NSClassFromString(@"NSUserNotificationCenter") - performSelector:@selector(defaultUserNotificationCenter)]; - [notificationCenter performSelector:@selector(removeAllDeliveredNotifications)]; - [notificationCenter performSelector:@selector(deliverNotification:) - withObject:notification]; - } + UNUserNotificationCenter* center = + UNUserNotificationCenter.currentNotificationCenter; + [center requestAuthorizationWithOptions:UNAuthorizationOptionAlert | + UNAuthorizationOptionProvisional + completionHandler:^(BOOL granted, NSError* error) { + if (error) { + NSLog(@"User notification authorization error: %@", + error.debugDescription); + } + }]; + [center getNotificationSettingsWithCompletionHandler:^( + UNNotificationSettings* settings) { + if ((settings.authorizationStatus == UNAuthorizationStatusAuthorized || + settings.authorizationStatus == UNAuthorizationStatusProvisional) && + (settings.alertSetting == UNNotificationSettingEnabled)) { + UNMutableNotificationContent* content = + [[UNMutableNotificationContent alloc] init]; + content.title = NSLocalizedString(@"Squirrel", nil); + content.subtitle = NSLocalizedString(@(msg_text), nil); + if (@available(macOS 12.0, *)) { + content.interruptionLevel = UNNotificationInterruptionLevelActive; + } + UNNotificationRequest* request = + [UNNotificationRequest requestWithIdentifier:@"SquirrelNotification" + content:content + trigger:nil]; + [center addNotificationRequest:request + withCompletionHandler:^(NSError* error) { + if (error) { + NSLog(@"User notification request error: %@", + error.debugDescription); + } + }]; + } + }]; } -static void show_status_message(const char *msg_text_long, const char *msg_text_short, const char* msg_id) { +static void show_status_message(const char* msg_text_long, + const char* msg_text_short, + const char* msg_id) { SquirrelPanel* panel = NSApp.squirrelAppDelegate.panel; - if (panel) { - NSString *msgLong = msg_text_long ? @(msg_text_long) : nil; - NSString *msgShort = msg_text_short ? @(msg_text_short) : nil; - [panel updateStatusLong: msgLong statusShort: msgShort]; - } + NSString* msgLong = msg_text_long ? @(msg_text_long) : nil; + NSString* msgShort = msg_text_short ? @(msg_text_short) : nil; + [panel updateStatusLong:msgLong statusShort:msgShort]; } -void notification_handler(void* context_object, RimeSessionId session_id, - const char* message_type, const char* message_value) { +void notification_handler(void* context_object, + RimeSessionId session_id, + const char* message_type, + const char* message_value) { if (!strcmp(message_type, "deploy")) { if (!strcmp(message_value, "start")) { show_message("deploy_start", message_type); - } - else if (!strcmp(message_value, "success")) { + } else if (!strcmp(message_value, "success")) { show_message("deploy_success", message_type); - } - else if (!strcmp(message_value, "failure")) { + } else if (!strcmp(message_value, "failure")) { show_message("deploy_failure", message_type); } return; } // off? - id app_delegate = (__bridge id)context_object; + SquirrelApplicationDelegate* app_delegate = (__bridge id)context_object; if (app_delegate && ![app_delegate enableNotifications]) { return; } @@ -88,42 +111,49 @@ void notification_handler(void* context_object, RimeSessionId session_id, if (!strcmp(message_type, "option")) { Bool state = message_value[0] != '!'; const char* option_name = message_value + !state; - struct rime_string_slice_t state_label_long = rime_get_api()->get_state_label_abbreviated(session_id, option_name, state, NO); - struct rime_string_slice_t state_label_short = rime_get_api()->get_state_label_abbreviated(session_id, option_name, state, YES); - + struct rime_string_slice_t state_label_long = + rime_get_api()->get_state_label_abbreviated(session_id, option_name, + state, False); + struct rime_string_slice_t state_label_short = + rime_get_api()->get_state_label_abbreviated(session_id, option_name, + state, True); + if (state_label_long.str || state_label_short.str) { - const char *short_message = state_label_short.length < strlen(state_label_short.str) ? NULL : state_label_short.str; + const char* short_message = + state_label_short.length < strlen(state_label_short.str) + ? NULL + : state_label_short.str; show_status_message(state_label_long.str, short_message, message_type); } } } --(void)setupRime -{ - NSString* userDataDir = (@"~/Library/Rime").stringByStandardizingPath; +- (void)setupRime { + NSString* userDataDir = @"~/Library/Rime".stringByExpandingTildeInPath; NSFileManager* fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:userDataDir]) { if (![fileManager createDirectoryAtPath:userDataDir withIntermediateDirectories:YES attributes:nil - error:NULL]) { + error:nil]) { NSLog(@"Error creating user data directory: %@", userDataDir); } } - rime_get_api()->set_notification_handler(notification_handler, (__bridge void *)(self)); + rime_get_api()->set_notification_handler(notification_handler, + (__bridge void*)(self)); RIME_STRUCT(RimeTraits, squirrel_traits); - squirrel_traits.shared_data_dir = [NSBundle mainBundle].sharedSupportPath.UTF8String; + squirrel_traits.shared_data_dir = + [NSBundle mainBundle].sharedSupportPath.UTF8String; squirrel_traits.user_data_dir = userDataDir.UTF8String; squirrel_traits.distribution_code_name = "Squirrel"; squirrel_traits.distribution_name = "鼠鬚管"; - squirrel_traits.distribution_version = - [[NSBundle mainBundle].infoDictionary[@"CFBundleVersion"] UTF8String]; + squirrel_traits.distribution_version = [[[NSBundle mainBundle] + objectForInfoDictionaryKey:(NSString*)kCFBundleVersionKey] UTF8String]; squirrel_traits.app_name = "rime.squirrel"; rime_get_api()->setup(&squirrel_traits); } --(void)startRimeWithFullCheck:(BOOL)fullCheck -{ +- (void)startRimeWithFullCheck:(BOOL)fullCheck { NSLog(@"Initializing la rime..."); rime_get_api()->initialize(NULL); // check for configuration updates @@ -138,25 +168,25 @@ - (void)shutdownRime { rime_get_api()->finalize(); } --(void)loadSettings { +- (void)loadSettings { _config = [[SquirrelConfig alloc] init]; if (![_config openBaseConfig]) { return; } - _enableNotifications = - ![[_config getString:@"show_notifications_when"] isEqualToString:@"never"]; + _enableNotifications = ![[_config getString:@"show_notifications_when"] + isEqualToString:@"never"]; [self.panel loadConfig:_config forDarkMode:NO]; if (@available(macOS 10.14, *)) { [self.panel loadConfig:_config forDarkMode:YES]; } } --(void)loadSchemaSpecificSettings:(NSString *)schemaId { +- (void)loadSchemaSpecificSettings:(NSString*)schemaId { if (schemaId.length == 0 || [schemaId characterAtIndex:0] == '.') { return; } - SquirrelConfig *schema = [[SquirrelConfig alloc] init]; + SquirrelConfig* schema = [[SquirrelConfig alloc] init]; if ([schema openWithSchemaId:schemaId baseConfig:self.config] && [schema hasSection:@"style"]) { [self.panel loadConfig:schema forDarkMode:NO]; @@ -164,7 +194,7 @@ -(void)loadSchemaSpecificSettings:(NSString *)schemaId { [self.panel loadConfig:self.config forDarkMode:NO]; } if (@available(macOS 10.14, *)) { - if ([schema openWithSchemaId:schemaId baseConfig:self.config] && + if ([schema openWithSchemaId:schemaId baseConfig:self.config] && [schema hasSection:@"style"]) { [self.panel loadConfig:schema forDarkMode:YES]; } else { @@ -175,64 +205,67 @@ -(void)loadSchemaSpecificSettings:(NSString *)schemaId { } // prevent freezing the system --(BOOL)problematicLaunchDetected -{ +- (BOOL)problematicLaunchDetected { BOOL detected = NO; - NSString* logfile = - [NSTemporaryDirectory() stringByAppendingPathComponent:@"squirrel_launch.dat"]; - //NSLog(@"[DEBUG] archive: %@", logfile); - NSData* archive = [NSData dataWithContentsOfFile:logfile - options:NSDataReadingUncached - error:nil]; + NSURL* logfile = [[NSURL fileURLWithPath:NSTemporaryDirectory() + isDirectory:YES] + URLByAppendingPathComponent:@"squirrel_launch.dat"]; + // NSLog(@"[DEBUG] archive: %@", logfile); + NSData* archive = [NSData dataWithContentsOfURL:logfile + options:NSDataReadingUncached + error:nil]; if (archive) { - NSDate* previousLaunch = [NSKeyedUnarchiver unarchivedObjectOfClass:NSDate.class fromData:archive error:NULL]; - if (previousLaunch && previousLaunch.timeIntervalSinceNow >= -2) { + NSDate* previousLaunch = + [NSKeyedUnarchiver unarchivedObjectOfClass:NSDate.class + fromData:archive + error:nil]; + if (previousLaunch.timeIntervalSinceNow >= -2) { detected = YES; } } NSDate* now = [NSDate date]; - NSData* record = [NSKeyedArchiver archivedDataWithRootObject:now requiringSecureCoding:NO error:NULL]; - [record writeToFile:logfile atomically:NO]; + NSData* record = [NSKeyedArchiver archivedDataWithRootObject:now + requiringSecureCoding:NO + error:nil]; + [record writeToURL:logfile atomically:NO]; return detected; } --(void)workspaceWillPowerOff:(NSNotification *)aNotification -{ +- (void)workspaceWillPowerOff:(NSNotification*)aNotification { NSLog(@"Finalizing before logging out."); [self shutdownRime]; } --(void)rimeNeedsReload:(NSNotification *)aNotification -{ +- (void)rimeNeedsReload:(NSNotification*)aNotification { NSLog(@"Reloading rime on demand."); [self deploy:nil]; } --(void)rimeNeedsSync:(NSNotification *)aNotification -{ +- (void)rimeNeedsSync:(NSNotification*)aNotification { NSLog(@"Sync rime on demand."); [self syncUserData:nil]; } --(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender -{ +- (NSApplicationTerminateReply)applicationShouldTerminate: + (NSApplication*)sender { NSLog(@"Squirrel is quitting."); rime_get_api()->cleanup_all_sessions(); return NSTerminateNow; } -//add an awakeFromNib item so that we can set the action method. Note that -//any menuItems without an action will be disabled when displayed in the Text -//Input Menu. --(void)awakeFromNib -{ - NSNotificationCenter* center = [NSWorkspace sharedWorkspace].notificationCenter; +// add an awakeFromNib item so that we can set the action method. Note that +// any menuItems without an action will be disabled when displayed in the Text +// Input Menu. +- (void)awakeFromNib { + NSNotificationCenter* center = + [NSWorkspace sharedWorkspace].notificationCenter; [center addObserver:self selector:@selector(workspaceWillPowerOff:) name:NSWorkspaceWillPowerOffNotification object:nil]; - NSDistributedNotificationCenter* notifCenter = [NSDistributedNotificationCenter defaultCenter]; + NSDistributedNotificationCenter* notifCenter = + [NSDistributedNotificationCenter defaultCenter]; [notifCenter addObserver:self selector:@selector(rimeNeedsReload:) name:@"SquirrelReloadNotification" @@ -242,25 +275,20 @@ -(void)awakeFromNib selector:@selector(rimeNeedsSync:) name:@"SquirrelSyncNotification" object:nil]; - } --(void)dealloc -{ +- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSDistributedNotificationCenter defaultCenter] removeObserver:self]; - if (_panel) { - [_panel hide]; - } + [_panel hide]; } -@end //SquirrelApplicationDelegate +@end // SquirrelApplicationDelegate @implementation NSApplication (SquirrelApp) --(SquirrelApplicationDelegate *)squirrelAppDelegate { - return (SquirrelApplicationDelegate *)self.delegate; +- (SquirrelApplicationDelegate*)squirrelAppDelegate { + return (SquirrelApplicationDelegate*)self.delegate; } @end - diff --git a/SquirrelConfig.h b/SquirrelConfig.h index c4bd50145..baca6c49d 100644 --- a/SquirrelConfig.h +++ b/SquirrelConfig.h @@ -1,32 +1,31 @@ #import -typedef NSDictionary SquirrelAppOptions; -typedef NSMutableDictionary SquirrelMutableAppOptions; +typedef NSDictionary SquirrelAppOptions; +typedef NSMutableDictionary SquirrelMutableAppOptions; @interface SquirrelConfig : NSObject @property(nonatomic, readonly) BOOL isOpen; -@property(nonatomic, copy) NSString *colorSpace; -@property(nonatomic, readonly) NSString *schemaId; +@property(nonatomic, strong) NSString* colorSpace; +@property(nonatomic, strong, readonly) NSString* schemaId; - (BOOL)openBaseConfig; -- (BOOL)openWithSchemaId:(NSString *)schemaId - baseConfig:(SquirrelConfig *)config; +- (BOOL)openWithSchemaId:(NSString*)schemaId baseConfig:(SquirrelConfig*)config; - (void)close; -- (BOOL)hasSection:(NSString *)section; +- (BOOL)hasSection:(NSString*)section; -- (BOOL)getBool:(NSString *)option; -- (NSInteger)getInt:(NSString *)option; -- (double)getDouble:(NSString *)option; -- (NSNumber *)getOptionalBool:(NSString *)option; -- (NSNumber *)getOptionalInt:(NSString *)option; -- (NSNumber *)getOptionalDouble:(NSString *)option; +- (BOOL)getBool:(NSString*)option; +- (int)getInt:(NSString*)option; +- (double)getDouble:(NSString*)option; +- (NSNumber*)getOptionalBool:(NSString*)option; +- (NSNumber*)getOptionalInt:(NSString*)option; +- (NSNumber*)getOptionalDouble:(NSString*)option; -- (NSString *)getString:(NSString *)option; +- (NSString*)getString:(NSString*)option; // 0xaabbggrr or 0xbbggrr -- (NSColor *)getColor:(NSString *)option; +- (NSColor*)getColor:(NSString*)option; -- (SquirrelAppOptions *)getAppOptions:(NSString *)appName; +- (SquirrelAppOptions*)getAppOptions:(NSString*)appName; @end diff --git a/SquirrelConfig.m b/SquirrelConfig.m index d816f1b40..7d26d75c1 100644 --- a/SquirrelConfig.m +++ b/SquirrelConfig.m @@ -3,38 +3,27 @@ #import @implementation SquirrelConfig { - NSMutableDictionary *_cache; + NSMutableDictionary* _cache; RimeConfig _config; - NSString *_schemaId; - SquirrelConfig *_baseConfig; - BOOL _isOpen; + SquirrelConfig* _baseConfig; } - (instancetype)init { - self = [super init]; - if (self) { + if (self = [super init]) { _cache = [[NSMutableDictionary alloc] init]; + _colorSpace = @"srgb"; } - self.colorSpace = @"srgb"; return self; } -- (BOOL)isOpen { - return _isOpen; -} - -- (NSString *)schemaId { - return _schemaId; -} - - (BOOL)openBaseConfig { [self close]; _isOpen = !!rime_get_api()->config_open("squirrel", &_config); return _isOpen; } -- (BOOL)openWithSchemaId:(NSString *)schemaId - baseConfig:(SquirrelConfig *)baseConfig { +- (BOOL)openWithSchemaId:(NSString*)schemaId + baseConfig:(SquirrelConfig*)baseConfig { [self close]; _isOpen = !!rime_get_api()->schema_open(schemaId.UTF8String, &_config); if (_isOpen) { @@ -52,10 +41,15 @@ - (void)close { } } -- (BOOL)hasSection:(NSString *)section { +- (void)dealloc { + [self close]; +} + +- (BOOL)hasSection:(NSString*)section { if (_isOpen) { RimeConfigIterator iterator = {0}; - if (rime_get_api()->config_begin_map(&iterator, &_config, section.UTF8String)) { + if (rime_get_api()->config_begin_map(&iterator, &_config, + section.UTF8String)) { rime_get_api()->config_end(&iterator); return YES; } @@ -63,74 +57,82 @@ - (BOOL)hasSection:(NSString *)section { return NO; } -- (BOOL)getBool:(NSString *)option { +- (BOOL)getBool:(NSString*)option { return [self getOptionalBool:option].boolValue; } -- (NSInteger)getInt:(NSString *)option { - return [self getOptionalInt:option].integerValue; +- (int)getInt:(NSString*)option { + return [self getOptionalInt:option].intValue; } -- (double)getDouble:(NSString *)option { +- (double)getDouble:(NSString*)option { return [self getOptionalDouble:option].doubleValue; } -- (NSNumber *)getOptionalBool:(NSString *)option { - NSNumber* cachedValue = [self cachedValueOfClass:[NSNumber class] forKey:option]; +- (NSNumber*)getOptionalBool:(NSString*)option { + NSNumber* cachedValue = [self cachedValueOfObjCType:@encode(BOOL) + forKey:option]; if (cachedValue) { return cachedValue; } Bool value; - if (_isOpen && rime_get_api()->config_get_bool(&_config, option.UTF8String, &value)) { + if (_isOpen && + rime_get_api()->config_get_bool(&_config, option.UTF8String, &value)) { return _cache[option] = @(!!value); } return [_baseConfig getOptionalBool:option]; } -- (NSNumber *)getOptionalInt:(NSString *)option { - NSNumber *cachedValue = [self cachedValueOfClass:[NSNumber class] forKey:option]; +- (NSNumber*)getOptionalInt:(NSString*)option { + NSNumber* cachedValue = [self cachedValueOfObjCType:@encode(int) + forKey:option]; if (cachedValue) { return cachedValue; } int value; - if (_isOpen && rime_get_api()->config_get_int(&_config, option.UTF8String, &value)) { + if (_isOpen && + rime_get_api()->config_get_int(&_config, option.UTF8String, &value)) { return _cache[option] = @(value); } return [_baseConfig getOptionalInt:option]; - } -- (NSNumber *)getOptionalDouble:(NSString *)option { - NSNumber *cachedValue = [self cachedValueOfClass:[NSNumber class] forKey:option]; +- (NSNumber*)getOptionalDouble:(NSString*)option { + NSNumber* cachedValue = [self cachedValueOfObjCType:@encode(double) + forKey:option]; if (cachedValue) { return cachedValue; } double value; - if (_isOpen && rime_get_api()->config_get_double(&_config, option.UTF8String, &value)) { + if (_isOpen && + rime_get_api()->config_get_double(&_config, option.UTF8String, &value)) { return _cache[option] = @(value); } return [_baseConfig getOptionalDouble:option]; } -- (NSString *)getString:(NSString *)option { - NSString *cachedValue = [self cachedValueOfClass:[NSString class] forKey:option]; +- (NSString*)getString:(NSString*)option { + NSString* cachedValue = [self cachedValueOfClass:[NSString class] + forKey:option]; if (cachedValue) { return cachedValue; } - const char *value = - _isOpen ? rime_get_api()->config_get_cstring(&_config, option.UTF8String) : NULL; + const char* value = + _isOpen ? rime_get_api()->config_get_cstring(&_config, option.UTF8String) + : NULL; if (value) { return _cache[option] = @(value); } return [_baseConfig getString:option]; } -- (NSColor *)getColor:(NSString *)option { - NSColor *cachedValue = [self cachedValueOfClass:[NSColor class] forKey:option]; +- (NSColor*)getColor:(NSString*)option { + NSColor* cachedValue = [self cachedValueOfClass:[NSColor class] + forKey:option]; if (cachedValue) { return cachedValue; } - NSColor *color = [self colorFromString:[self getString:option]]; + NSColor* color = [self colorFromString:[self getString:option]]; if (color) { _cache[option] = color; return color; @@ -138,13 +140,15 @@ - (NSColor *)getColor:(NSString *)option { return [_baseConfig getColor:option]; } -- (SquirrelAppOptions *)getAppOptions:(NSString *)appName { - NSString * rootKey = [@"app_options/" stringByAppendingString:appName]; - SquirrelMutableAppOptions* appOptions = [[SquirrelMutableAppOptions alloc] init]; +- (SquirrelAppOptions*)getAppOptions:(NSString*)appName { + NSString* rootKey = [@"app_options/" stringByAppendingString:appName]; + SquirrelMutableAppOptions* appOptions = + [[SquirrelMutableAppOptions alloc] init]; RimeConfigIterator iterator; rime_get_api()->config_begin_map(&iterator, &_config, rootKey.UTF8String); while (rime_get_api()->config_next(&iterator)) { - //NSLog(@"DEBUG option[%d]: %s (%s)", iterator.index, iterator.key, iterator.path); + // NSLog(@"DEBUG option[%d]: %s (%s)", iterator.index, iterator.key, + // iterator.path); BOOL value = [self getBool:@(iterator.path)]; appOptions[@(iterator.key)] = @(value); } @@ -154,15 +158,24 @@ - (SquirrelAppOptions *)getAppOptions:(NSString *)appName { #pragma mark - Private methods -- (id)cachedValueOfClass:(Class)aClass forKey:(NSString *)key { +- (id)cachedValueOfClass:(Class)aClass forKey:(NSString*)key { + id value = [_cache objectForKey:key]; + if ([value isMemberOfClass:aClass]) { + return value; + } + return nil; +} + +- (NSNumber*)cachedValueOfObjCType:(const char*)type forKey:(NSString*)key { id value = [_cache objectForKey:key]; - if (value && [value isKindOfClass:aClass]) { + if ([value isMemberOfClass:NSNumber.class] && + !strcmp([value objCType], type)) { return value; } return nil; } -- (NSColor *)colorFromString:(NSString *)string { +- (NSColor*)colorFromString:(NSString*)string { if (string == nil) { return nil; } @@ -176,15 +189,15 @@ - (NSColor *)colorFromString:(NSString *)string { sscanf(string.UTF8String, "0x%02x%02x%02x", &b, &g, &r); } if ([self.colorSpace isEqualToString:@"display_p3"]) { - return [NSColor colorWithDisplayP3Red:(CGFloat)r / 255. - green:(CGFloat)g / 255. - blue:(CGFloat)b / 255. - alpha:(CGFloat)a / 255.]; + return [NSColor colorWithDisplayP3Red:r / 255.0 + green:g / 255.0 + blue:b / 255.0 + alpha:a / 255.0]; } else { // sRGB by default - return [NSColor colorWithSRGBRed:(CGFloat)r / 255. - green:(CGFloat)g / 255. - blue:(CGFloat)b / 255. - alpha:(CGFloat)a / 255.]; + return [NSColor colorWithSRGBRed:r / 255.0 + green:g / 255.0 + blue:b / 255.0 + alpha:a / 255.0]; } } diff --git a/SquirrelInputController.m b/SquirrelInputController.m index 02f0ef8a4..69e9de150 100644 --- a/SquirrelInputController.m +++ b/SquirrelInputController.m @@ -7,35 +7,34 @@ #import #import -@interface SquirrelInputController(Private) --(void)createSession; --(void)destroySession; --(void)rimeConsumeCommittedText; --(void)rimeUpdate; --(void)updateAppOptions; +@interface SquirrelInputController (Private) +- (void)createSession; +- (void)destroySession; +- (void)rimeConsumeCommittedText; +- (void)rimeUpdate; +- (void)updateAppOptions; @end const int N_KEY_ROLL_OVER = 50; @implementation SquirrelInputController { - id _currentClient; - NSString *_preeditString; + NSString* _preeditString; NSRange _selRange; NSUInteger _caretPos; - NSArray *_candidates; - NSUInteger _lastModifier; + NSArray* _candidates; + NSEventModifierFlags _lastModifier; NSEventType _lastEventType; RimeSessionId _session; - NSString *_schemaId; + NSString* _schemaId; BOOL _inlinePreedit; BOOL _inlineCandidate; // for chord-typing int _chordKeyCodes[N_KEY_ROLL_OVER]; int _chordModifiers[N_KEY_ROLL_OVER]; int _chordKeyCount; - NSTimer *_chordTimer; + NSTimer* _chordTimer; NSTimeInterval _chordDuration; - NSString *_currentApp; + NSString* _currentApp; } /*! @@ -43,16 +42,13 @@ @implementation SquirrelInputController { @abstract Receive incoming event @discussion This method receives key events from the client application. */ -- (BOOL)handleEvent:(NSEvent*)event client:(id)sender -{ +- (BOOL)handleEvent:(NSEvent*)event client:(id)sender { // Return YES to indicate the the key input was received and dealt with. // Key processing will not continue in that case. In other words the // system will not deliver a key down event to the application. // Returning NO means the original key down will be passed on to the client. - _currentClient = sender; - - NSUInteger modifiers = event.modifierFlags; + NSEventModifierFlags modifiers = event.modifierFlags; BOOL handled = NO; @@ -64,7 +60,7 @@ - (BOOL)handleEvent:(NSEvent*)event client:(id)sender } } - NSString* app = [_currentClient bundleIdentifier]; + NSString* app = [sender bundleIdentifier]; if (![_currentApp isEqualToString:app]) { _currentApp = [app copy]; @@ -77,19 +73,22 @@ - (BOOL)handleEvent:(NSEvent*)event client:(id)sender handled = YES; break; } - //NSLog(@"FLAGSCHANGED client: %@, modifiers: 0x%lx", sender, modifiers); + // NSLog(@"FLAGSCHANGED client: %@, modifiers: 0x%lx", sender, + // modifiers); int rime_modifiers = osx_modifiers_to_rime_modifiers(modifiers); int rime_keycode = 0; - // For flags-changed event, keyCode is available since macOS 10.15 (#715) - Bool keyCodeAvailable = NO; + // For flags-changed event, keyCode is available since macOS 10.15 + // (#715) + BOOL keyCodeAvailable = NO; if (@available(macOS 10.15, *)) { keyCodeAvailable = YES; - rime_keycode = osx_keycode_to_rime_keycode(event.keyCode, 0, 0, 0); - //NSLog(@"keyCode: %d", event.keyCode); + rime_keycode = + osx_keycode_to_rime_keycode((int)event.keyCode, 0, 0, 0); + // NSLog(@"keyCode: %d", event.keyCode); } int release_mask = 0; NSUInteger changes = _lastModifier ^ modifiers; - if (changes & OSX_CAPITAL_MASK) { + if (changes & NSEventModifierFlagCapsLock) { if (!keyCodeAvailable) { rime_keycode = XK_Caps_Lock; } @@ -99,33 +98,41 @@ - (BOOL)handleEvent:(NSEvent*)event client:(id)sender rime_modifiers ^= kLockMask; [self processKey:rime_keycode modifiers:rime_modifiers]; } - if (changes & OSX_SHIFT_MASK) { + if (changes & NSEventModifierFlagShift) { if (!keyCodeAvailable) { rime_keycode = XK_Shift_L; } - release_mask = modifiers & OSX_SHIFT_MASK ? 0 : kReleaseMask; - [self processKey:rime_keycode modifiers:(rime_modifiers | release_mask)]; + release_mask = + modifiers & NSEventModifierFlagShift ? 0 : kReleaseMask; + [self processKey:rime_keycode + modifiers:(rime_modifiers | release_mask)]; } - if (changes & OSX_CTRL_MASK) { + if (changes & NSEventModifierFlagControl) { if (!keyCodeAvailable) { rime_keycode = XK_Control_L; } - release_mask = modifiers & OSX_CTRL_MASK ? 0 : kReleaseMask; - [self processKey:rime_keycode modifiers:(rime_modifiers | release_mask)]; + release_mask = + modifiers & NSEventModifierFlagControl ? 0 : kReleaseMask; + [self processKey:rime_keycode + modifiers:(rime_modifiers | release_mask)]; } - if (changes & OSX_ALT_MASK) { + if (changes & NSEventModifierFlagOption) { if (!keyCodeAvailable) { rime_keycode = XK_Alt_L; } - release_mask = modifiers & OSX_ALT_MASK ? 0 : kReleaseMask; - [self processKey:rime_keycode modifiers:(rime_modifiers | release_mask)]; + release_mask = + modifiers & NSEventModifierFlagOption ? 0 : kReleaseMask; + [self processKey:rime_keycode + modifiers:(rime_modifiers | release_mask)]; } - if (changes & OSX_COMMAND_MASK) { + if (changes & NSEventModifierFlagCommand) { if (!keyCodeAvailable) { rime_keycode = XK_Super_L; } - release_mask = modifiers & OSX_COMMAND_MASK ? 0 : kReleaseMask; - [self processKey:rime_keycode modifiers:(rime_modifiers | release_mask)]; + release_mask = + modifiers & NSEventModifierFlagCommand ? 0 : kReleaseMask; + [self processKey:rime_keycode + modifiers:(rime_modifiers | release_mask)]; // do not update UI when using Command key break; } @@ -133,21 +140,24 @@ - (BOOL)handleEvent:(NSEvent*)event client:(id)sender } break; case NSEventTypeKeyDown: { // ignore Command+X hotkeys. - if (modifiers & OSX_COMMAND_MASK) + if (modifiers & NSEventModifierFlagCommand) { break; + } - int keyCode = event.keyCode; + ushort keyCode = event.keyCode; NSString* keyChars = event.charactersIgnoringModifiers; if (!isalpha(keyChars.UTF8String[0])) { keyChars = event.characters; } - //NSLog(@"KEYDOWN client: %@, modifiers: 0x%lx, keyCode: %d, keyChars: [%@]", - // sender, modifiers, keyCode, keyChars); + // NSLog(@"KEYDOWN client: %@, modifiers: 0x%lx, keyCode: %d, keyChars: + // [%@]", + // sender, modifiers, keyCode, keyChars); // translate osx keyevents to rime keyevents int rime_keycode = osx_keycode_to_rime_keycode( - keyCode, keyChars.UTF8String[0], modifiers & OSX_SHIFT_MASK, - modifiers & OSX_CAPITAL_MASK); + (int)keyCode, (int)keyChars.UTF8String[0], + (int)modifiers & NSEventModifierFlagShift, + (int)modifiers & NSEventModifierFlagCapsLock); if (rime_keycode) { int rime_modifiers = osx_modifiers_to_rime_modifiers(modifiers); handled = [self processKey:rime_keycode modifiers:rime_modifiers]; @@ -165,31 +175,33 @@ - (BOOL)handleEvent:(NSEvent*)event client:(id)sender return handled; } --(BOOL)processKey:(int)rime_keycode modifiers:(int)rime_modifiers -{ +- (BOOL)processKey:(int)rime_keycode modifiers:(int)rime_modifiers { // TODO add special key event preprocessing here // with linear candidate list, arrow keys may behave differently. - Bool is_linear = NSApp.squirrelAppDelegate.panel.linear; + Bool is_linear = (Bool)NSApp.squirrelAppDelegate.panel.linear; if (is_linear != rime_get_api()->get_option(_session, "_linear")) { rime_get_api()->set_option(_session, "_linear", is_linear); } // with vertical text, arrow keys may behave differently. - Bool is_vertical = NSApp.squirrelAppDelegate.panel.vertical; + Bool is_vertical = (Bool)NSApp.squirrelAppDelegate.panel.vertical; if (is_vertical != rime_get_api()->get_option(_session, "_vertical")) { rime_get_api()->set_option(_session, "_vertical", is_vertical); } - BOOL handled = (BOOL)rime_get_api()->process_key(_session, rime_keycode, rime_modifiers); - //NSLog(@"rime_keycode: 0x%x, rime_modifiers: 0x%x, handled = %d", rime_keycode, rime_modifiers, handled); + BOOL handled = + (BOOL)rime_get_api()->process_key(_session, rime_keycode, rime_modifiers); + // NSLog(@"rime_keycode: 0x%x, rime_modifiers: 0x%x, handled = %d", + // rime_keycode, rime_modifiers, handled); // TODO add special key event postprocessing here if (!handled) { - BOOL isVimBackInCommandMode = rime_keycode == XK_Escape || - ((rime_modifiers & kControlMask) && (rime_keycode == XK_c || - rime_keycode == XK_C || - rime_keycode == XK_bracketleft)); + BOOL isVimBackInCommandMode = + rime_keycode == XK_Escape || + ((rime_modifiers & kControlMask) && + (rime_keycode == XK_c || rime_keycode == XK_C || + rime_keycode == XK_bracketleft)); if (isVimBackInCommandMode && rime_get_api()->get_option(_session, "vim_mode") && !rime_get_api()->get_option(_session, "ascii_mode")) { @@ -201,15 +213,14 @@ -(BOOL)processKey:(int)rime_keycode modifiers:(int)rime_modifiers // Simulate key-ups for every interesting key-down for chord-typing. if (handled) { bool is_chording_key = - (rime_keycode >= XK_space && rime_keycode <= XK_asciitilde) || - rime_keycode == XK_Control_L || rime_keycode == XK_Control_R || - rime_keycode == XK_Alt_L || rime_keycode == XK_Alt_R || - rime_keycode == XK_Shift_L || rime_keycode == XK_Shift_R; + (rime_keycode >= XK_space && rime_keycode <= XK_asciitilde) || + rime_keycode == XK_Control_L || rime_keycode == XK_Control_R || + rime_keycode == XK_Alt_L || rime_keycode == XK_Alt_R || + rime_keycode == XK_Shift_L || rime_keycode == XK_Shift_R; if (is_chording_key && rime_get_api()->get_option(_session, "_chord_typing")) { [self updateChord:rime_keycode modifiers:rime_modifiers]; - } - else if ((rime_modifiers & kReleaseMask) == 0) { + } else if ((rime_modifiers & kReleaseMask) == 0) { // non-chording key pressed [self clearChord]; } @@ -219,7 +230,8 @@ -(BOOL)processKey:(int)rime_keycode modifiers:(int)rime_modifiers } - (BOOL)selectCandidate:(NSInteger)index { - BOOL success = rime_get_api()->select_candidate_on_current_page(_session, (int) index); + BOOL success = + rime_get_api()->select_candidate_on_current_page(_session, (int)index); if (success) { [self rimeUpdate]; } @@ -239,15 +251,13 @@ - (BOOL)pageUp:(BOOL)up { return handled; } --(void)onChordTimer:(NSTimer *)timer -{ +- (void)onChordTimer:(NSTimer*)timer { // chord release triggered by timer int processed_keys = 0; if (_chordKeyCount && _session) { // simulate key-ups for (int i = 0; i < _chordKeyCount; ++i) { - if (rime_get_api()->process_key(_session, - _chordKeyCodes[i], + if (rime_get_api()->process_key(_session, _chordKeyCodes[i], (_chordModifiers[i] | kReleaseMask))) ++processed_keys; } @@ -258,9 +268,8 @@ -(void)onChordTimer:(NSTimer *)timer } } --(void)updateChord:(int)keycode modifiers:(int)modifiers -{ - //NSLog(@"update chord: {%s} << %x", _chord, keycode); +- (void)updateChord:(int)keycode modifiers:(int)modifiers { + // NSLog(@"update chord: {%s} << %x", _chord, keycode); for (int i = 0; i < _chordKeyCount; ++i) { if (_chordKeyCodes[i] == keycode) return; @@ -273,12 +282,13 @@ -(void)updateChord:(int)keycode modifiers:(int)modifiers _chordModifiers[_chordKeyCount] = modifiers; ++_chordKeyCount; // reset timer - if (_chordTimer && _chordTimer.valid) { + if (_chordTimer.valid) { [_chordTimer invalidate]; } _chordDuration = 0.1; - NSNumber *duration = [NSApp.squirrelAppDelegate.config getOptionalDouble:@"chord_duration"]; - if (duration && duration.doubleValue > 0) { + NSNumber* duration = + [NSApp.squirrelAppDelegate.config getOptionalDouble:@"chord_duration"]; + if (duration.doubleValue > 0) { _chordDuration = duration.doubleValue; } _chordTimer = [NSTimer scheduledTimerWithTimeInterval:_chordDuration @@ -288,33 +298,31 @@ -(void)updateChord:(int)keycode modifiers:(int)modifiers repeats:NO]; } --(void)clearChord -{ +- (void)clearChord { _chordKeyCount = 0; - if (_chordTimer) { - if (_chordTimer.valid) { - [_chordTimer invalidate]; - } + if (_chordTimer.valid) { + [_chordTimer invalidate]; _chordTimer = nil; } } --(NSUInteger)recognizedEvents:(id)sender -{ - //NSLog(@"recognizedEvents:"); +- (NSUInteger)recognizedEvents:(id)sender { + // NSLog(@"recognizedEvents:"); return NSEventMaskKeyDown | NSEventMaskFlagsChanged; } --(void)activateServer:(id)sender -{ - //NSLog(@"activateServer:"); - NSString *keyboardLayout = [NSApp.squirrelAppDelegate.config getString:@"keyboard_layout"]; - if ([keyboardLayout isEqualToString:@"last"] || [keyboardLayout isEqualToString:@""]) { - keyboardLayout = NULL; +- (void)activateServer:(id)sender { + // NSLog(@"activateServer:"); + NSString* keyboardLayout = + [NSApp.squirrelAppDelegate.config getString:@"keyboard_layout"]; + if ([keyboardLayout isEqualToString:@"last"] || + [keyboardLayout isEqualToString:@""]) { + keyboardLayout = nil; } else if ([keyboardLayout isEqualToString:@"default"]) { keyboardLayout = @"com.apple.keylayout.ABC"; } else if (![keyboardLayout hasPrefix:@"com.apple.keylayout."]) { - keyboardLayout = [NSString stringWithFormat:@"com.apple.keylayout.%@", keyboardLayout]; + keyboardLayout = + [NSString stringWithFormat:@"com.apple.keylayout.%@", keyboardLayout]; } if (keyboardLayout) { [sender overrideKeyboardWithKeyboardNamed:keyboardLayout]; @@ -322,23 +330,29 @@ -(void)activateServer:(id)sender _preeditString = @""; } --(instancetype)initWithServer:(IMKServer*)server delegate:(id)delegate client:(id)inputClient -{ - //NSLog(@"initWithServer:delegate:client:"); - if (self = [super initWithServer:server delegate:delegate client:inputClient]) { - _currentClient = inputClient; +- (instancetype)initWithServer:(IMKServer*)server + delegate:(id)delegate + client:(id)inputClient { + // NSLog(@"initWithServer:delegate:client:"); + if (self = [super initWithServer:server + delegate:delegate + client:inputClient]) { [self createSession]; } return self; } --(void)deactivateServer:(id)sender -{ - //NSLog(@"deactivateServer:"); - [NSApp.squirrelAppDelegate.panel hide]; +- (void)deactivateServer:(id)sender { + // NSLog(@"deactivateServer:"); + [self hidePalettes]; [self commitComposition:sender]; } +- (void)hidePalettes { + [NSApp.squirrelAppDelegate.panel hide]; + [super hidePalettes]; +} + /*! @method @abstract Called when a user action was taken that ends an input session. @@ -350,120 +364,112 @@ -(void)deactivateServer:(id)sender to clean up if that is necessary. */ --(void)commitComposition:(id)sender -{ - //NSLog(@"commitComposition:"); - // commit raw input +- (void)commitComposition:(id)sender { + // NSLog(@"commitComposition:"); + // commit raw input if (_session) { const char* raw_input = rime_get_api()->get_input(_session); if (raw_input) { - [self commitString: @(raw_input)]; + [self commitString:@(raw_input)]; rime_get_api()->clear_composition(_session); } } } // a piece of comment from SunPinyin's macos wrapper says: -// > though we specified the showPrefPanel: in SunPinyinApplicationDelegate as the -// > action receiver, the IMKInputController will actually receive the event. -// so here we deliver messages to our responsible SquirrelApplicationDelegate --(void)deploy:(id)sender -{ +// > though we specified the showPrefPanel: in SunPinyinApplicationDelegate as +// the > action receiver, the IMKInputController will actually receive the +// event. so here we deliver messages to our responsible +// SquirrelApplicationDelegate +- (void)deploy:(id)sender { [NSApp.squirrelAppDelegate deploy:sender]; } --(void)syncUserData:(id)sender -{ +- (void)syncUserData:(id)sender { [NSApp.squirrelAppDelegate syncUserData:sender]; } --(void)configure:(id)sender -{ +- (void)configure:(id)sender { [NSApp.squirrelAppDelegate configure:sender]; } --(void)checkForUpdates:(id)sender -{ - [NSApp.squirrelAppDelegate.updater performSelector:@selector(checkForUpdates:) withObject:sender]; +- (void)checkForUpdates:(id)sender { + [NSApp.squirrelAppDelegate.updater performSelector:@selector(checkForUpdates:) + withObject:sender]; } --(void)openWiki:(id)sender -{ +- (void)openWiki:(id)sender { [NSApp.squirrelAppDelegate openWiki:sender]; } --(NSMenu*)menu -{ +- (NSMenu*)menu { return NSApp.squirrelAppDelegate.menu; } --(NSArray*)candidates:(id)sender -{ +- (NSArray*)candidates:(id)sender { return _candidates; } --(void)dealloc -{ +- (void)dealloc { [self destroySession]; } --(void)commitString:(NSString*)string -{ - //NSLog(@"commitString:"); - [_currentClient insertText:string - replacementRange:NSMakeRange(NSNotFound, 0)]; +- (void)commitString:(NSString*)string { + // NSLog(@"commitString:"); + [self.client insertText:string replacementRange:NSMakeRange(NSNotFound, 0)]; _preeditString = @""; - [NSApp.squirrelAppDelegate.panel hide]; + [self hidePalettes]; } --(void)showPreeditString:(NSString*)preedit - selRange:(NSRange)range - caretPos:(NSUInteger)pos -{ - //NSLog(@"showPreeditString: '%@'", preedit); +- (void)showPreeditString:(NSString*)preedit + selRange:(NSRange)range + caretPos:(NSUInteger)pos { + // NSLog(@"showPreeditString: '%@'", preedit); - if ([_preeditString isEqualToString:preedit] && - _caretPos == pos && _selRange.location == range.location && _selRange.length == range.length) + if ([_preeditString isEqualToString:preedit] && _caretPos == pos && + NSEqualRanges(_selRange, range)) { return; + } _preeditString = preedit; _selRange = range; _caretPos = pos; - //NSLog(@"selRange.location = %ld, selRange.length = %ld; caretPos = %ld", - // range.location, range.length, pos); + // NSLog(@"selRange.location = %ld, selRange.length = %ld; caretPos = %ld", + // range.location, range.length, pos); NSDictionary* attrs; - NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString:preedit]; + NSMutableAttributedString* attrString = + [[NSMutableAttributedString alloc] initWithString:preedit]; if (range.location > 0) { NSRange convertedRange = NSMakeRange(0, range.location); attrs = [self markForStyle:kTSMHiliteConvertedText atRange:convertedRange]; [attrString setAttributes:attrs range:convertedRange]; } { - NSRange remainingRange = NSMakeRange(range.location, preedit.length - range.location); - attrs = [self markForStyle:kTSMHiliteSelectedRawText atRange:remainingRange]; + NSRange remainingRange = + NSMakeRange(range.location, preedit.length - range.location); + attrs = [self markForStyle:kTSMHiliteSelectedRawText + atRange:remainingRange]; [attrString setAttributes:attrs range:remainingRange]; } - [_currentClient setMarkedText:attrString - selectionRange:NSMakeRange(pos, 0) - replacementRange:NSMakeRange(NSNotFound, 0)]; - + [self.client setMarkedText:attrString + selectionRange:NSMakeRange(pos, 0) + replacementRange:NSMakeRange(NSNotFound, NSNotFound)]; } --(void)showPanelWithPreedit:(NSString*)preedit - selRange:(NSRange)selRange - caretPos:(NSUInteger)caretPos - candidates:(NSArray*)candidates - comments:(NSArray*)comments - labels:(NSArray*)labels - highlighted:(NSUInteger)index -{ - //NSLog(@"showPanelWithPreedit:...:"); +- (void)showPanelWithPreedit:(NSString*)preedit + selRange:(NSRange)selRange + caretPos:(NSUInteger)caretPos + candidates:(NSArray*)candidates + comments:(NSArray*)comments + labels:(NSArray*)labels + highlighted:(NSUInteger)index { + // NSLog(@"showPanelWithPreedit:...:"); _candidates = candidates; NSRect inputPos; - [_currentClient attributesForCharacterIndex:0 lineHeightRectangle:&inputPos]; + [self.client attributesForCharacterIndex:0 lineHeightRectangle:&inputPos]; SquirrelPanel* panel = NSApp.squirrelAppDelegate.panel; panel.position = inputPos; panel.inputController = self; @@ -477,15 +483,13 @@ -(void)showPanelWithPreedit:(NSString*)preedit update:YES]; } -@end // SquirrelController - +@end // SquirrelController // implementation of private interface -@implementation SquirrelInputController(Private) +@implementation SquirrelInputController (Private) --(void)createSession -{ - NSString* app = [_currentClient bundleIdentifier]; +- (void)createSession { + NSString* app = [self.client bundleIdentifier]; NSLog(@"createSession: %@", app); _currentApp = [app copy]; _session = rime_get_api()->create_session(); @@ -497,11 +501,11 @@ -(void)createSession } } --(void)updateAppOptions -{ +- (void)updateAppOptions { if (!_currentApp) return; - SquirrelAppOptions* appOptions = [NSApp.squirrelAppDelegate.config getAppOptions:_currentApp]; + SquirrelAppOptions* appOptions = + [NSApp.squirrelAppDelegate.config getAppOptions:_currentApp]; if (appOptions) { for (NSString* key in appOptions) { BOOL value = appOptions[key].boolValue; @@ -511,9 +515,8 @@ -(void)updateAppOptions } } --(void)destroySession -{ - //NSLog(@"destroySession:"); +- (void)destroySession { + // NSLog(@"destroySession:"); if (_session) { rime_get_api()->destroy_session(_session); _session = 0; @@ -521,26 +524,23 @@ -(void)destroySession [self clearChord]; } --(void)rimeConsumeCommittedText -{ +- (void)rimeConsumeCommittedText { RIME_STRUCT(RimeCommit, commit); if (rime_get_api()->get_commit(_session, &commit)) { - NSString *commitText = @(commit.text); - [self commitString: commitText]; + NSString* commitText = @(commit.text); + [self commitString:commitText]; rime_get_api()->free_commit(&commit); } } -NSString *substr(const char *str, int length) { - char substring[length+1]; - strncpy(substring, str, length); - substring[length] = '\0'; - return [NSString stringWithCString:substring encoding:NSUTF8StringEncoding]; +NSString* substr(const char* str, int length) { + return [[NSString alloc] initWithBytes:str + length:(NSUInteger)length + encoding:NSUTF8StringEncoding]; } --(void)rimeUpdate -{ - //NSLog(@"rimeUpdate"); +- (void)rimeUpdate { + // NSLog(@"rimeUpdate"); [self rimeConsumeCommittedText]; RIME_STRUCT(RimeStatus, status); @@ -552,7 +552,7 @@ -(void)rimeUpdate // inline preedit _inlinePreedit = (NSApp.squirrelAppDelegate.panel.inlinePreedit && !rime_get_api()->get_option(_session, "no_inline")) || - rime_get_api()->get_option(_session, "inline"); + rime_get_api()->get_option(_session, "inline"); _inlineCandidate = (NSApp.squirrelAppDelegate.panel.inlineCandidate && !rime_get_api()->get_option(_session, "no_inline")); // if not inline, embed soft cursor in preedit string @@ -564,59 +564,87 @@ -(void)rimeUpdate RIME_STRUCT(RimeContext, ctx); if (rime_get_api()->get_context(_session, &ctx)) { // update preedit text - const char *preedit = ctx.composition.preedit; - NSString *preeditText = preedit ? @(preedit) : @""; + const char* preedit = ctx.composition.preedit; + NSString* preeditText = preedit ? @(preedit) : @""; NSUInteger start = substr(preedit, ctx.composition.sel_start).length; NSUInteger end = substr(preedit, ctx.composition.sel_end).length; NSUInteger caretPos = substr(preedit, ctx.composition.cursor_pos).length; NSRange selRange = NSMakeRange(start, end - start); if (_inlineCandidate) { - const char *candidatePreview = ctx.commit_text_preview; - NSString *candidatePreviewText = candidatePreview ? @(candidatePreview) : @""; + const char* candidatePreview = ctx.commit_text_preview; + NSString* candidatePreviewText = + candidatePreview ? @(candidatePreview) : @""; if (_inlinePreedit) { - if ((caretPos >= NSMaxRange(selRange)) && (caretPos < preeditText.length)) { - candidatePreviewText = [candidatePreviewText stringByAppendingString:[preeditText substringWithRange:NSMakeRange(caretPos, preeditText.length-caretPos)]]; + if ((caretPos >= NSMaxRange(selRange)) && + (caretPos < preeditText.length)) { + candidatePreviewText = [candidatePreviewText + stringByAppendingString: + [preeditText + substringWithRange:NSMakeRange( + caretPos, + preeditText.length - caretPos)]]; } - [self showPreeditString:candidatePreviewText selRange:NSMakeRange(selRange.location, candidatePreviewText.length-selRange.location) caretPos:candidatePreviewText.length-(preeditText.length-caretPos)]; + [self showPreeditString:candidatePreviewText + selRange:NSMakeRange(selRange.location, + candidatePreviewText.length - + selRange.location) + caretPos:candidatePreviewText.length - + (preeditText.length - caretPos)]; } else { - if ((NSMaxRange(selRange) < caretPos) && (caretPos > selRange.location)) { - candidatePreviewText = [candidatePreviewText substringWithRange:NSMakeRange(0, candidatePreviewText.length-(caretPos-NSMaxRange(selRange)))]; - } else if ((NSMaxRange(selRange) < preeditText.length) && (caretPos <= selRange.location)) { - candidatePreviewText = [candidatePreviewText substringWithRange:NSMakeRange(0, candidatePreviewText.length-(preeditText.length-NSMaxRange(selRange)))]; + if ((NSMaxRange(selRange) < caretPos) && + (caretPos > selRange.location)) { + candidatePreviewText = [candidatePreviewText + substringToIndex:candidatePreviewText.length - (caretPos - end)]; + } else if ((NSMaxRange(selRange) < preeditText.length) && + (caretPos <= selRange.location)) { + candidatePreviewText = [candidatePreviewText + substringToIndex:candidatePreviewText.length - + (preeditText.length - end)]; } - [self showPreeditString:candidatePreviewText selRange:NSMakeRange(selRange.location, candidatePreviewText.length-selRange.location) caretPos:candidatePreviewText.length]; + [self showPreeditString:candidatePreviewText + selRange:NSMakeRange(selRange.location, + candidatePreviewText.length - + selRange.location) + caretPos:candidatePreviewText.length]; } } else { if (_inlinePreedit) { - [self showPreeditString:preeditText selRange:selRange caretPos:caretPos]; + [self showPreeditString:preeditText + selRange:selRange + caretPos:caretPos]; } else { - NSRange empty = {0, 0}; - // TRICKY: display a non-empty string to prevent iTerm2 from echoing each character in preedit. - // note this is a full-shape space U+3000; using half shape characters like "..." will result in - // an unstable baseline when composing Chinese characters. - [self showPreeditString:(preedit ? @" " : @"") selRange:empty caretPos:0]; + // TRICKY: display a non-empty string to prevent iTerm2 from echoing + // each character in preedit. note this is a full-shape space U+3000; + // using half shape characters like "..." will result in an unstable + // baseline when composing Chinese characters. + [self showPreeditString:(preedit ? @" " : @"") + selRange:NSMakeRange(0, 0) + caretPos:0]; } } // update candidates - NSMutableArray *candidates = [NSMutableArray array]; - NSMutableArray *comments = [NSMutableArray array]; - NSUInteger i; - for (i = 0; i < ctx.menu.num_candidates; ++i) { + NSUInteger numCandidates = (NSUInteger)ctx.menu.num_candidates; + NSMutableArray* candidates = + [[NSMutableArray alloc] initWithCapacity:numCandidates]; + NSMutableArray* comments = + [[NSMutableArray alloc] initWithCapacity:numCandidates]; + for (NSUInteger i = 0; i < (NSUInteger)ctx.menu.num_candidates; ++i) { [candidates addObject:@(ctx.menu.candidates[i].text)]; if (ctx.menu.candidates[i].comment) { [comments addObject:@(ctx.menu.candidates[i].comment)]; - } - else { + } else { [comments addObject:@""]; } } NSArray* labels; if (ctx.menu.select_keys) { - labels = @[@(ctx.menu.select_keys)]; + labels = @[ @(ctx.menu.select_keys) ]; } else if (ctx.select_labels) { - NSMutableArray *selectLabels = [NSMutableArray array]; - for (i = 0; i < ctx.menu.page_size; ++i) { + NSUInteger pageSize = (NSUInteger)ctx.menu.page_size; + NSMutableArray* selectLabels = + [[NSMutableArray alloc] initWithCapacity:pageSize]; + for (NSUInteger i = 0; i < pageSize; ++i) { char* label_str = ctx.select_labels[i]; [selectLabels addObject:@(label_str)]; } @@ -624,17 +652,18 @@ -(void)rimeUpdate } else { labels = @[]; } - [self showPanelWithPreedit:(_inlinePreedit ? nil : preeditText) - selRange:selRange - caretPos:caretPos - candidates:candidates - comments:comments - labels:labels - highlighted:ctx.menu.highlighted_candidate_index]; + [self + showPanelWithPreedit:(_inlinePreedit ? nil : preeditText) + selRange:selRange + caretPos:caretPos + candidates:candidates + comments:comments + labels:labels + highlighted:(NSUInteger)ctx.menu.highlighted_candidate_index]; rime_get_api()->free_context(&ctx); } else { - [NSApp.squirrelAppDelegate.panel hide]; + [self hidePalettes]; } } -@end // SquirrelController(Private) +@end // SquirrelController(Private) diff --git a/SquirrelPanel.h b/SquirrelPanel.h index 159b2a8ad..5844ad7a5 100644 --- a/SquirrelPanel.h +++ b/SquirrelPanel.h @@ -17,22 +17,22 @@ // position of input caret on screen. @property(nonatomic, assign) NSRect position; // position of input caret on screen. -@property(nonatomic, assign) SquirrelInputController *inputController; +@property(nonatomic, assign) SquirrelInputController* inputController; --(void)showPreedit:(NSString*)preedit - selRange:(NSRange)selRange - caretPos:(NSUInteger)caretPos - candidates:(NSArray*)candidates - comments:(NSArray*)comments - labels:(NSArray*)labels - highlighted:(NSUInteger)index - update:(BOOL)update; +- (void)showPreedit:(NSString*)preedit + selRange:(NSRange)selRange + caretPos:(NSUInteger)caretPos + candidates:(NSArray*)candidates + comments:(NSArray*)comments + labels:(NSArray*)labels + highlighted:(NSUInteger)index + update:(BOOL)update; --(void)hide; +- (void)hide; --(void)updateStatusLong:(NSString*)messageLong statusShort:(NSString*)messageShort; +- (void)updateStatusLong:(NSString*)messageLong + statusShort:(NSString*)messageShort; --(void)loadConfig:(SquirrelConfig*)config - forDarkMode:(BOOL)isDark; +- (void)loadConfig:(SquirrelConfig*)config forDarkMode:(BOOL)isDark; @end diff --git a/SquirrelPanel.m b/SquirrelPanel.m index 892471dd4..a7ec23945 100644 --- a/SquirrelPanel.m +++ b/SquirrelPanel.m @@ -7,19 +7,19 @@ static const CGFloat kDefaultFontSize = 24; static const CGFloat kBlendedBackgroundColorFraction = 1.0 / 5; static const NSTimeInterval kShowStatusDuration = 1.2; -static NSString *const kDefaultCandidateFormat = @"%c.\u00A0%@"; +static NSString* const kDefaultCandidateFormat = @"%c.\u00A0%@"; @interface SquirrelTheme : NSObject @property(nonatomic, assign) BOOL native; @property(nonatomic, assign) BOOL memorizeSize; -@property(nonatomic, strong, readonly) NSColor *backgroundColor; -@property(nonatomic, strong, readonly) NSColor *highlightedBackColor; -@property(nonatomic, strong, readonly) NSColor *candidateBackColor; -@property(nonatomic, strong, readonly) NSColor *highlightedPreeditColor; -@property(nonatomic, strong, readonly) NSColor *preeditBackgroundColor; -@property(nonatomic, strong, readonly) NSColor *borderColor; +@property(nonatomic, strong, readonly) NSColor* backgroundColor; +@property(nonatomic, strong, readonly) NSColor* highlightedBackColor; +@property(nonatomic, strong, readonly) NSColor* candidateBackColor; +@property(nonatomic, strong, readonly) NSColor* highlightedPreeditColor; +@property(nonatomic, strong, readonly) NSColor* preeditBackgroundColor; +@property(nonatomic, strong, readonly) NSColor* borderColor; @property(nonatomic, readonly) CGFloat cornerRadius; @property(nonatomic, readonly) CGFloat hilitedCornerRadius; @@ -37,29 +37,30 @@ @interface SquirrelTheme : NSObject @property(nonatomic, readonly) BOOL inlinePreedit; @property(nonatomic, readonly) BOOL inlineCandidate; -@property(nonatomic, strong, readonly) NSDictionary *attrs; -@property(nonatomic, strong, readonly) NSDictionary *highlightedAttrs; -@property(nonatomic, strong, readonly) NSDictionary *labelAttrs; -@property(nonatomic, strong, readonly) NSDictionary *labelHighlightedAttrs; -@property(nonatomic, strong, readonly) NSDictionary *commentAttrs; -@property(nonatomic, strong, readonly) NSDictionary *commentHighlightedAttrs; -@property(nonatomic, strong, readonly) NSDictionary *preeditAttrs; -@property(nonatomic, strong, readonly) NSDictionary *preeditHighlightedAttrs; -@property(nonatomic, strong, readonly) NSParagraphStyle *paragraphStyle; -@property(nonatomic, strong, readonly) NSParagraphStyle *preeditParagraphStyle; - -@property(nonatomic, strong, readonly) NSString *prefixLabelFormat, *suffixLabelFormat; -@property(nonatomic, strong, readonly) NSString *statusMessageType; - -- (void)setCandidateFormat:(NSString *)candidateFormat; -- (void)setStatusMessageType:(NSString *)statusMessageType; - -- (void)setBackgroundColor:(NSColor *)backgroundColor - highlightedBackColor:(NSColor *)highlightedBackColor - candidateBackColor:(NSColor *)candidateBackColor - highlightedPreeditColor:(NSColor *)highlightedPreeditColor - preeditBackgroundColor:(NSColor *)preeditBackgroundColor - borderColor:(NSColor *)borderColor; +@property(nonatomic, strong, readonly) NSDictionary* attrs; +@property(nonatomic, strong, readonly) NSDictionary* highlightedAttrs; +@property(nonatomic, strong, readonly) NSDictionary* labelAttrs; +@property(nonatomic, strong, readonly) NSDictionary* labelHighlightedAttrs; +@property(nonatomic, strong, readonly) NSDictionary* commentAttrs; +@property(nonatomic, strong, readonly) NSDictionary* commentHighlightedAttrs; +@property(nonatomic, strong, readonly) NSDictionary* preeditAttrs; +@property(nonatomic, strong, readonly) NSDictionary* preeditHighlightedAttrs; +@property(nonatomic, strong, readonly) NSParagraphStyle* paragraphStyle; +@property(nonatomic, strong, readonly) NSParagraphStyle* preeditParagraphStyle; + +@property(nonatomic, strong, readonly) NSString *prefixLabelFormat, + *suffixLabelFormat; +@property(nonatomic, strong, readonly) NSString* statusMessageType; + +- (void)setCandidateFormat:(NSString*)candidateFormat; +- (void)setStatusMessageType:(NSString*)statusMessageType; + +- (void)setBackgroundColor:(NSColor*)backgroundColor + highlightedBackColor:(NSColor*)highlightedBackColor + candidateBackColor:(NSColor*)candidateBackColor + highlightedPreeditColor:(NSColor*)highlightedPreeditColor + preeditBackgroundColor:(NSColor*)preeditBackgroundColor + borderColor:(NSColor*)borderColor; - (void)setCornerRadius:(CGFloat)cornerRadius hilitedCornerRadius:(CGFloat)hilitedCornerRadius @@ -77,24 +78,25 @@ - (void)setCornerRadius:(CGFloat)cornerRadius inlinePreedit:(BOOL)inlinePreedit inlineCandidate:(BOOL)inlineCandidate; -- (void) setAttrs:(NSMutableDictionary *)attrs - highlightedAttrs:(NSMutableDictionary *)highlightedAttrs - labelAttrs:(NSMutableDictionary *)labelAttrs - labelHighlightedAttrs:(NSMutableDictionary *)labelHighlightedAttrs - commentAttrs:(NSMutableDictionary *)commentAttrs - commentHighlightedAttrs:(NSMutableDictionary *)commentHighlightedAttrs - preeditAttrs:(NSMutableDictionary *)preeditAttrs - preeditHighlightedAttrs:(NSMutableDictionary *)preeditHighlightedAttrs; +- (void)setAttrs:(NSDictionary*)attrs + highlightedAttrs:(NSDictionary*)highlightedAttrs + labelAttrs:(NSDictionary*)labelAttrs + labelHighlightedAttrs:(NSDictionary*)labelHighlightedAttrs + commentAttrs:(NSDictionary*)commentAttrs + commentHighlightedAttrs:(NSDictionary*)commentHighlightedAttrs + preeditAttrs:(NSDictionary*)preeditAttrs + preeditHighlightedAttrs:(NSDictionary*)preeditHighlightedAttrs; -- (void) setParagraphStyle:(NSParagraphStyle *)paragraphStyle - preeditParagraphStyle:(NSParagraphStyle *)preeditParagraphStyle; +- (void)setParagraphStyle:(NSParagraphStyle*)paragraphStyle + preeditParagraphStyle:(NSParagraphStyle*)preeditParagraphStyle; @end @implementation SquirrelTheme -- (void)setCandidateFormat:(NSString *)candidateFormat { - // in the candiate format, everything other than '%@' is considered part of the label +- (void)setCandidateFormat:(NSString*)candidateFormat { + // in the candiate format, everything other than '%@' is considered part of + // the label NSRange candidateRange = [candidateFormat rangeOfString:@"%@"]; if (candidateRange.location == NSNotFound) { _prefixLabelFormat = candidateFormat; @@ -110,8 +112,9 @@ - (void)setCandidateFormat:(NSString *)candidateFormat { } if (NSMaxRange(candidateRange) < candidateFormat.length) { // everything after '%@' is suffix label - NSRange suffixLabelRange = NSMakeRange(NSMaxRange(candidateRange), - candidateFormat.length - NSMaxRange(candidateRange)); + NSRange suffixLabelRange = + NSMakeRange(NSMaxRange(candidateRange), + candidateFormat.length - NSMaxRange(candidateRange)); _suffixLabelFormat = [candidateFormat substringWithRange:suffixLabelRange]; } else { // '%@' is at the end, so suffix label does not exist @@ -119,20 +122,21 @@ - (void)setCandidateFormat:(NSString *)candidateFormat { } } -- (void)setStatusMessageType:(NSString *)type { - if ([type isEqualToString: @"long"] || [type isEqualToString: @"short"] || [type isEqualToString: @"mix"]) { +- (void)setStatusMessageType:(NSString*)type { + if ([type isEqualToString:@"long"] || [type isEqualToString:@"short"] || + [type isEqualToString:@"mix"]) { _statusMessageType = type; } else { _statusMessageType = @"mix"; } } -- (void)setBackgroundColor:(NSColor *)backgroundColor - highlightedBackColor:(NSColor *)highlightedBackColor - candidateBackColor:(NSColor *)candidateBackColor - highlightedPreeditColor:(NSColor *)highlightedPreeditColor - preeditBackgroundColor:(NSColor *)preeditBackgroundColor - borderColor:(NSColor *)borderColor { +- (void)setBackgroundColor:(NSColor*)backgroundColor + highlightedBackColor:(NSColor*)highlightedBackColor + candidateBackColor:(NSColor*)candidateBackColor + highlightedPreeditColor:(NSColor*)highlightedPreeditColor + preeditBackgroundColor:(NSColor*)preeditBackgroundColor + borderColor:(NSColor*)borderColor { _backgroundColor = backgroundColor; _highlightedBackColor = highlightedBackColor; _candidateBackColor = candidateBackColor; @@ -141,15 +145,15 @@ - (void)setBackgroundColor:(NSColor *)backgroundColor _borderColor = borderColor; } -- (void)setCornerRadius:(double)cornerRadius - hilitedCornerRadius:(double)hilitedCornerRadius - srdExtraExpansion:(double)surroundingExtraExpansion - shadowSize:(double)shadowSize +- (void)setCornerRadius:(CGFloat)cornerRadius + hilitedCornerRadius:(CGFloat)hilitedCornerRadius + srdExtraExpansion:(CGFloat)surroundingExtraExpansion + shadowSize:(CGFloat)shadowSize edgeInset:(NSSize)edgeInset - borderWidth:(double)borderWidth - linespace:(double)linespace - preeditLinespace:(double)preeditLinespace - alpha:(double)alpha + borderWidth:(CGFloat)borderWidth + linespace:(CGFloat)linespace + preeditLinespace:(CGFloat)preeditLinespace + alpha:(CGFloat)alpha translucency:(BOOL)translucency mutualExclusive:(BOOL)mutualExclusive linear:(BOOL)linear @@ -173,14 +177,14 @@ - (void)setCornerRadius:(double)cornerRadius _inlineCandidate = inlineCandidate; } -- (void) setAttrs:(NSMutableDictionary *)attrs - highlightedAttrs:(NSMutableDictionary *)highlightedAttrs - labelAttrs:(NSMutableDictionary *)labelAttrs - labelHighlightedAttrs:(NSMutableDictionary *)labelHighlightedAttrs - commentAttrs:(NSMutableDictionary *)commentAttrs - commentHighlightedAttrs:(NSMutableDictionary *)commentHighlightedAttrs - preeditAttrs:(NSMutableDictionary *)preeditAttrs - preeditHighlightedAttrs:(NSMutableDictionary *)preeditHighlightedAttrs { +- (void)setAttrs:(NSDictionary*)attrs + highlightedAttrs:(NSDictionary*)highlightedAttrs + labelAttrs:(NSDictionary*)labelAttrs + labelHighlightedAttrs:(NSDictionary*)labelHighlightedAttrs + commentAttrs:(NSDictionary*)commentAttrs + commentHighlightedAttrs:(NSDictionary*)commentHighlightedAttrs + preeditAttrs:(NSDictionary*)preeditAttrs + preeditHighlightedAttrs:(NSDictionary*)preeditHighlightedAttrs { _attrs = attrs; _highlightedAttrs = highlightedAttrs; _labelAttrs = labelAttrs; @@ -191,8 +195,8 @@ - (void) setAttrs:(NSMutableDictionary *)attrs _preeditHighlightedAttrs = preeditHighlightedAttrs; } -- (void) setParagraphStyle:(NSParagraphStyle *)paragraphStyle - preeditParagraphStyle:(NSParagraphStyle *)preeditParagraphStyle { +- (void)setParagraphStyle:(NSParagraphStyle*)paragraphStyle + preeditParagraphStyle:(NSParagraphStyle*)preeditParagraphStyle { _paragraphStyle = paragraphStyle; _preeditParagraphStyle = preeditParagraphStyle; } @@ -201,29 +205,29 @@ - (void) setParagraphStyle:(NSParagraphStyle *)paragraphStyle @interface SquirrelView : NSView -@property(nonatomic, readonly) NSTextView *textView; -@property(nonatomic, readonly) NSArray *candidateRanges; +@property(nonatomic, readonly) NSTextView* textView; +@property(nonatomic, readonly) NSArray* candidateRanges; @property(nonatomic, readonly) NSInteger hilightedIndex; @property(nonatomic, readonly) NSRange preeditRange; @property(nonatomic, readonly) NSRange highlightedPreeditRange; @property(nonatomic, readonly) NSRect contentRect; @property(nonatomic, readonly) BOOL isDark; -@property(nonatomic, strong, readonly) SquirrelTheme *currentTheme; -@property(nonatomic, readonly) NSTextLayoutManager *layoutManager; +@property(nonatomic, strong, readonly) SquirrelTheme* currentTheme; +@property(nonatomic, readonly) NSTextLayoutManager* layoutManager; @property(nonatomic, assign) CGFloat seperatorWidth; -@property(nonatomic, readonly) CAShapeLayer *shape; +@property(nonatomic, readonly) CAShapeLayer* shape; -- (void) drawViewWith:(NSArray *)candidateRanges - hilightedIndex:(NSInteger)hilightedIndex - preeditRange:(NSRange)preeditRange - highlightedPreeditRange:(NSRange)highlightedPreeditRange; -- (NSRect)contentRectForRange:(NSTextRange *)range; +- (void)drawViewWith:(NSArray*)candidateRanges + hilightedIndex:(NSInteger)hilightedIndex + preeditRange:(NSRange)preeditRange + highlightedPreeditRange:(NSRange)highlightedPreeditRange; +- (NSRect)contentRectForRange:(NSTextRange*)range; @end @implementation SquirrelView -SquirrelTheme *_defaultTheme; -SquirrelTheme *_darkTheme; +SquirrelTheme* _defaultTheme; +SquirrelTheme* _darkTheme; // Need flipped coordinate system, as required by textStorage - (BOOL)isFlipped { @@ -231,21 +235,23 @@ - (BOOL)isFlipped { } - (BOOL)isDark { - if ([NSApp.effectiveAppearance bestMatchFromAppearancesWithNames:@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]] == NSAppearanceNameDarkAqua) { + if ([NSApp.effectiveAppearance bestMatchFromAppearancesWithNames:@[ + NSAppearanceNameAqua, NSAppearanceNameDarkAqua + ]] == NSAppearanceNameDarkAqua) { return YES; } return NO; } -- (SquirrelTheme *)selectTheme:(BOOL)isDark { +- (SquirrelTheme*)selectTheme:(BOOL)isDark { return isDark ? _darkTheme : _defaultTheme; } -- (SquirrelTheme *)currentTheme { +- (SquirrelTheme*)currentTheme { return [self selectTheme:self.isDark]; } -- (NSTextLayoutManager *)layoutManager { +- (NSTextLayoutManager*)layoutManager { return _textView.textLayoutManager; } @@ -266,19 +272,24 @@ - (instancetype)initWithFrame:(NSRect)frameRect { return self; } -- (NSTextRange *)convertRange:(NSRange)range { +- (NSTextRange*)convertRange:(NSRange)range { if (range.location == NSNotFound) { return nil; } else { - id startLocation = [self.layoutManager locationFromLocation:[self.layoutManager documentRange].location withOffset:range.location]; - id endLocation = [self.layoutManager locationFromLocation:startLocation withOffset:range.length]; - return [[NSTextRange alloc] initWithLocation:startLocation endLocation:endLocation]; + id startLocation = [self.layoutManager + locationFromLocation:[self.layoutManager documentRange].location + withOffset:range.location]; + id endLocation = + [self.layoutManager locationFromLocation:startLocation + withOffset:range.length]; + return [[NSTextRange alloc] initWithLocation:startLocation + endLocation:endLocation]; } } // Get the rectangle containing entire contents, expensive to calculate - (NSRect)contentRect { - NSMutableArray *ranges = [_candidateRanges mutableCopy]; + NSMutableArray* ranges = [_candidateRanges mutableCopy]; if (_preeditRange.length > 0) { [ranges addObject:[NSValue valueWithRange:_preeditRange]]; } @@ -288,36 +299,44 @@ - (NSRect)contentRect { CGFloat y1 = CGFLOAT_MIN; for (NSUInteger i = 0; i < ranges.count; i += 1) { NSRange range = [ranges[i] rangeValue]; - NSRect rect = [self contentRectForRange:[self convertRange: range]]; + NSRect rect = [self contentRectForRange:[self convertRange:range]]; x0 = MIN(NSMinX(rect), x0); x1 = MAX(NSMaxX(rect), x1); y0 = MIN(NSMinY(rect), y0); y1 = MAX(NSMaxY(rect), y1); } - return NSMakeRect(x0, y0, x1-x0, y1-y0); + return NSMakeRect(x0, y0, x1 - x0, y1 - y0); } -// Get the rectangle containing the range of text, will first convert to glyph range, expensive to calculate -- (NSRect)contentRectForRange:(NSTextRange *)range { +// Get the rectangle containing the range of text, will first convert to glyph +// range, expensive to calculate +- (NSRect)contentRectForRange:(NSTextRange*)range { __block CGFloat x0 = CGFLOAT_MAX; __block CGFloat x1 = CGFLOAT_MIN; __block CGFloat y0 = CGFLOAT_MAX; __block CGFloat y1 = CGFLOAT_MIN; - [self.layoutManager enumerateTextSegmentsInRange:range type:NSTextLayoutManagerSegmentTypeStandard options:NSTextLayoutManagerSegmentOptionsRangeNotRequired usingBlock:^(NSTextRange *_, CGRect rect, CGFloat baseline, NSTextContainer *tectContainer) { - x0 = MIN(NSMinX(rect), x0); - x1 = MAX(NSMaxX(rect), x1); - y0 = MIN(NSMinY(rect), y0); - y1 = MAX(NSMaxY(rect), y1); - return YES; - }]; - return NSMakeRect(x0, y0, x1-x0, y1-y0); + [self.layoutManager + enumerateTextSegmentsInRange:range + type:NSTextLayoutManagerSegmentTypeStandard + options: + NSTextLayoutManagerSegmentOptionsRangeNotRequired + usingBlock:^(NSTextRange* _, CGRect rect, + CGFloat baseline, + NSTextContainer* tectContainer) { + x0 = MIN(NSMinX(rect), x0); + x1 = MAX(NSMaxX(rect), x1); + y0 = MIN(NSMinY(rect), y0); + y1 = MAX(NSMaxY(rect), y1); + return YES; + }]; + return NSMakeRect(x0, y0, x1 - x0, y1 - y0); } // Will triger - (void)drawRect:(NSRect)dirtyRect -- (void) drawViewWith:(NSArray *)candidateRanges - hilightedIndex:(NSInteger)hilightedIndex - preeditRange:(NSRange)preeditRange - highlightedPreeditRange:(NSRange)highlightedPreeditRange { +- (void)drawViewWith:(NSArray*)candidateRanges + hilightedIndex:(NSInteger)hilightedIndex + preeditRange:(NSRange)preeditRange + highlightedPreeditRange:(NSRange)highlightedPreeditRange { _candidateRanges = candidateRanges; _hilightedIndex = hilightedIndex; _preeditRange = preeditRange; @@ -337,60 +356,71 @@ - (void) drawViewWith:(NSArray *)candidateRanges } // Bezier cubic curve, which has continuous roundness -CGMutablePathRef drawSmoothLines(NSArray *vertex, NSSet * __nullable straightCorner, CGFloat alpha, CGFloat beta) { +CGMutablePathRef drawSmoothLines(NSArray* vertex, + NSSet* __nullable straightCorner, + CGFloat alpha, + CGFloat beta) { beta = MAX(0.00001, beta); CGMutablePathRef path = CGPathCreateMutable(); if (vertex.count < 1) return path; - NSPoint previousPoint = [vertex[vertex.count-1] pointValue]; + NSPoint previousPoint = [vertex[vertex.count - 1] pointValue]; NSPoint point = [vertex[0] pointValue]; NSPoint nextPoint; NSPoint control1; NSPoint control2; NSPoint target = previousPoint; - NSPoint diff = NSMakePoint(point.x - previousPoint.x, point.y - previousPoint.y); - if (!straightCorner || ![straightCorner containsObject:[NSNumber numberWithUnsignedInteger:vertex.count - 1]]) { - target.x += sign(diff.x/beta)*beta; - target.y += sign(diff.y/beta)*beta; + NSPoint diff = + NSMakePoint(point.x - previousPoint.x, point.y - previousPoint.y); + if (!straightCorner || + ![straightCorner + containsObject:[NSNumber + numberWithUnsignedInteger:vertex.count - 1]]) { + target.x += sign(diff.x / beta) * beta; + target.y += sign(diff.y / beta) * beta; } CGPathMoveToPoint(path, NULL, target.x, target.y); for (NSUInteger i = 0; i < vertex.count; i += 1) { - previousPoint = [vertex[(vertex.count+i-1)%vertex.count] pointValue]; + previousPoint = [vertex[(vertex.count + i - 1) % vertex.count] pointValue]; point = [vertex[i] pointValue]; - nextPoint = [vertex[(i+1)%vertex.count] pointValue]; + nextPoint = [vertex[(i + 1) % vertex.count] pointValue]; target = point; - if (straightCorner && [straightCorner containsObject:[NSNumber numberWithUnsignedInteger:i]]) { + if (straightCorner && + [straightCorner + containsObject:[NSNumber numberWithUnsignedInteger:i]]) { CGPathAddLineToPoint(path, NULL, target.x, target.y); } else { control1 = point; diff = NSMakePoint(point.x - previousPoint.x, point.y - previousPoint.y); - target.x -= sign(diff.x/beta)*beta; - control1.x -= sign(diff.x/beta)*alpha; - target.y -= sign(diff.y/beta)*beta; - control1.y -= sign(diff.y/beta)*alpha; - + target.x -= sign(diff.x / beta) * beta; + control1.x -= sign(diff.x / beta) * alpha; + target.y -= sign(diff.y / beta) * beta; + control1.y -= sign(diff.y / beta) * alpha; + CGPathAddLineToPoint(path, NULL, target.x, target.y); target = point; control2 = point; diff = NSMakePoint(nextPoint.x - point.x, nextPoint.y - point.y); - control2.x += sign(diff.x/beta)*alpha; - target.x += sign(diff.x/beta)*beta; - control2.y += sign(diff.y/beta)*alpha; - target.y += sign(diff.y/beta)*beta; + control2.x += sign(diff.x / beta) * alpha; + target.x += sign(diff.x / beta) * beta; + control2.y += sign(diff.y / beta) * alpha; + target.y += sign(diff.y / beta) * beta; - CGPathAddCurveToPoint(path, NULL, control1.x, control1.y, control2.x, control2.y, target.x, target.y); + CGPathAddCurveToPoint(path, NULL, control1.x, control1.y, control2.x, + control2.y, target.x, target.y); } } CGPathCloseSubpath(path); return path; } -NSArray *rectVertex(NSRect rect) { +NSArray* rectVertex(NSRect rect) { return @[ @(rect.origin), - @(NSMakePoint(rect.origin.x, rect.origin.y+rect.size.height)), - @(NSMakePoint(rect.origin.x+rect.size.width, rect.origin.y+rect.size.height)), - @(NSMakePoint(rect.origin.x+rect.size.width, rect.origin.y)) + @(NSMakePoint(rect.origin.x, rect.origin.y + rect.size.height)), + @(NSMakePoint(rect.origin.x + rect.size.width, + rect.origin.y + rect.size.height)), + @(NSMakePoint(rect.origin.x + rect.size.width, rect.origin.y)) ]; } @@ -398,23 +428,36 @@ BOOL nearEmptyRect(NSRect rect) { return rect.size.height * rect.size.width < 1; } -// Calculate 3 boxes containing the text in range. leadingRect and trailingRect are incomplete line rectangle -// bodyRect is complete lines in the middle -- (void)multilineRectForRange:(NSTextRange *)range leadingRect:(NSRect *)leadingRect bodyRect:(NSRect *)bodyRect trailingRect:(NSRect *)trailingRect extraSurounding:(CGFloat)extraSurounding bounds:(NSRect)bounds { +// Calculate 3 boxes containing the text in range. leadingRect and trailingRect +// are incomplete line rectangle bodyRect is complete lines in the middle +- (void)multilineRectForRange:(NSTextRange*)range + leadingRect:(NSRect*)leadingRect + bodyRect:(NSRect*)bodyRect + trailingRect:(NSRect*)trailingRect + extraSurounding:(CGFloat)extraSurounding + bounds:(NSRect)bounds { NSSize edgeInset = self.currentTheme.edgeInset; - NSMutableArray *lineRects = [[NSMutableArray alloc] init]; - [self.layoutManager enumerateTextSegmentsInRange:range type:NSTextLayoutManagerSegmentTypeStandard options:NSTextLayoutManagerSegmentOptionsRangeNotRequired usingBlock:^(NSTextRange *_, CGRect rect, CGFloat baseline, NSTextContainer *tectContainer) { - if (!nearEmptyRect(rect)) { - NSRect newRect = rect; - newRect.origin.x += edgeInset.width; - newRect.origin.y += edgeInset.height; - newRect.size.height += self.currentTheme.linespace; - newRect.origin.y -= self.currentTheme.linespace / 2; - [lineRects addObject:[NSValue valueWithRect:newRect]]; - } - return YES; - }]; - + NSMutableArray* lineRects = [[NSMutableArray alloc] init]; + [self.layoutManager + enumerateTextSegmentsInRange:range + type:NSTextLayoutManagerSegmentTypeStandard + options: + NSTextLayoutManagerSegmentOptionsRangeNotRequired + usingBlock:^(NSTextRange* _, CGRect rect, + CGFloat baseline, + NSTextContainer* tectContainer) { + if (!nearEmptyRect(rect)) { + NSRect newRect = rect; + newRect.origin.x += edgeInset.width; + newRect.origin.y += edgeInset.height; + newRect.size.height += self.currentTheme.linespace; + newRect.origin.y -= self.currentTheme.linespace / 2; + [lineRects + addObject:[NSValue valueWithRect:newRect]]; + } + return YES; + }]; + *leadingRect = NSZeroRect; *bodyRect = NSZeroRect; *trailingRect = NSZeroRect; @@ -426,12 +469,12 @@ - (void)multilineRectForRange:(NSTextRange *)range leadingRect:(NSRect *)leading *trailingRect = [lineRects[1] rectValue]; } else if (lineRects.count > 2) { *leadingRect = [lineRects[0] rectValue]; - *trailingRect = [lineRects[lineRects.count-1] rectValue]; + *trailingRect = [lineRects[lineRects.count - 1] rectValue]; CGFloat x0 = CGFLOAT_MAX; CGFloat x1 = CGFLOAT_MIN; CGFloat y0 = CGFLOAT_MAX; CGFloat y1 = CGFLOAT_MIN; - for (NSUInteger i = 1; i < lineRects.count-1; i += 1) { + for (NSUInteger i = 1; i < lineRects.count - 1; i += 1) { NSRect rect = [lineRects[i] rectValue]; x0 = MIN(NSMinX(rect), x0); x1 = MAX(NSMaxX(rect), x1); @@ -440,9 +483,9 @@ - (void)multilineRectForRange:(NSTextRange *)range leadingRect:(NSRect *)leading } y0 = MIN(NSMaxY(*leadingRect), y0); y1 = MAX(NSMinY(*trailingRect), y1); - *bodyRect = NSMakeRect(x0, y0, x1-x0, y1-y0); + *bodyRect = NSMakeRect(x0, y0, x1 - x0, y1 - y0); } - + if (extraSurounding > 0) { if (nearEmptyRect(*leadingRect) && nearEmptyRect(*trailingRect)) { expandHighlightWidth(bodyRect, extraSurounding); @@ -455,7 +498,7 @@ - (void)multilineRectForRange:(NSTextRange *)range leadingRect:(NSRect *)leading } } } - + if (!nearEmptyRect(*leadingRect) && !nearEmptyRect(*trailingRect)) { leadingRect->size.width = NSMaxX(bounds) - leadingRect->origin.x; trailingRect->size.width = NSMaxX(*trailingRect) - NSMinX(bounds); @@ -472,115 +515,146 @@ - (void)multilineRectForRange:(NSTextRange *)range leadingRect:(NSRect *)leading } } -// Based on the 3 boxes from multilineRectForRange, calculate the vertex of the polygon containing the text in range -NSArray * multilineRectVertex(NSRect leadingRect, NSRect bodyRect, NSRect trailingRect) { - if (nearEmptyRect(bodyRect) && !nearEmptyRect(leadingRect) && nearEmptyRect(trailingRect)) { +// Based on the 3 boxes from multilineRectForRange, calculate the vertex of the +// polygon containing the text in range +NSArray* multilineRectVertex(NSRect leadingRect, + NSRect bodyRect, + NSRect trailingRect) { + if (nearEmptyRect(bodyRect) && !nearEmptyRect(leadingRect) && + nearEmptyRect(trailingRect)) { return rectVertex(leadingRect); - } else if (nearEmptyRect(bodyRect) && nearEmptyRect(leadingRect) && !nearEmptyRect(trailingRect)) { + } else if (nearEmptyRect(bodyRect) && nearEmptyRect(leadingRect) && + !nearEmptyRect(trailingRect)) { return rectVertex(trailingRect); - } else if (nearEmptyRect(leadingRect) && nearEmptyRect(trailingRect) && !nearEmptyRect(bodyRect)) { + } else if (nearEmptyRect(leadingRect) && nearEmptyRect(trailingRect) && + !nearEmptyRect(bodyRect)) { return rectVertex(bodyRect); } else if (nearEmptyRect(trailingRect) && !nearEmptyRect(bodyRect)) { - NSArray * leadingVertex = rectVertex(leadingRect); - NSArray * bodyVertex = rectVertex(bodyRect); - return @[bodyVertex[0], bodyVertex[1], bodyVertex[2], leadingVertex[3], leadingVertex[0], leadingVertex[1]]; + NSArray* leadingVertex = rectVertex(leadingRect); + NSArray* bodyVertex = rectVertex(bodyRect); + return @[ + bodyVertex[0], bodyVertex[1], bodyVertex[2], leadingVertex[3], + leadingVertex[0], leadingVertex[1] + ]; } else if (nearEmptyRect(leadingRect) && !nearEmptyRect(bodyRect)) { - NSArray * trailingVertex = rectVertex(trailingRect); - NSArray * bodyVertex = rectVertex(bodyRect); - return @[trailingVertex[1], trailingVertex[2], trailingVertex[3], bodyVertex[2], bodyVertex[3], bodyVertex[0]]; - } else if (!nearEmptyRect(leadingRect) && !nearEmptyRect(trailingRect) && nearEmptyRect(bodyRect) && NSMaxX(leadingRect)>NSMinX(trailingRect)) { - NSArray * leadingVertex = rectVertex(leadingRect); - NSArray * trailingVertex = rectVertex(trailingRect); - return @[trailingVertex[0], trailingVertex[1], trailingVertex[2], trailingVertex[3], leadingVertex[2], leadingVertex[3], leadingVertex[0], leadingVertex[1]]; - } else if (!nearEmptyRect(leadingRect) && !nearEmptyRect(trailingRect) && !nearEmptyRect(bodyRect)) { - NSArray * leadingVertex = rectVertex(leadingRect); - NSArray * bodyVertex = rectVertex(bodyRect); - NSArray * trailingVertex = rectVertex(trailingRect); - return @[trailingVertex[1], trailingVertex[2], trailingVertex[3], bodyVertex[2], leadingVertex[3], leadingVertex[0], leadingVertex[1], bodyVertex[0]]; + NSArray* trailingVertex = rectVertex(trailingRect); + NSArray* bodyVertex = rectVertex(bodyRect); + return @[ + trailingVertex[1], trailingVertex[2], trailingVertex[3], bodyVertex[2], + bodyVertex[3], bodyVertex[0] + ]; + } else if (!nearEmptyRect(leadingRect) && !nearEmptyRect(trailingRect) && + nearEmptyRect(bodyRect) && + NSMaxX(leadingRect) > NSMinX(trailingRect)) { + NSArray* leadingVertex = rectVertex(leadingRect); + NSArray* trailingVertex = rectVertex(trailingRect); + return @[ + trailingVertex[0], trailingVertex[1], trailingVertex[2], + trailingVertex[3], leadingVertex[2], leadingVertex[3], leadingVertex[0], + leadingVertex[1] + ]; + } else if (!nearEmptyRect(leadingRect) && !nearEmptyRect(trailingRect) && + !nearEmptyRect(bodyRect)) { + NSArray* leadingVertex = rectVertex(leadingRect); + NSArray* bodyVertex = rectVertex(bodyRect); + NSArray* trailingVertex = rectVertex(trailingRect); + return @[ + trailingVertex[1], trailingVertex[2], trailingVertex[3], bodyVertex[2], + leadingVertex[3], leadingVertex[0], leadingVertex[1], bodyVertex[0] + ]; } else { return @[]; } } // If the point is outside the innerBox, will extend to reach the outerBox -void expand(NSMutableArray *vertex, NSRect innerBorder, NSRect outerBorder) { - for (NSUInteger i = 0; i < vertex.count; i += 1){ +void expand(NSMutableArray* vertex, + NSRect innerBorder, + NSRect outerBorder) { + for (NSUInteger i = 0; i < vertex.count; i += 1) { NSPoint point = [vertex[i] pointValue]; if (point.x < innerBorder.origin.x) { point.x = outerBorder.origin.x; - } else if (point.x > innerBorder.origin.x+innerBorder.size.width) { - point.x = outerBorder.origin.x+outerBorder.size.width; + } else if (point.x > innerBorder.origin.x + innerBorder.size.width) { + point.x = outerBorder.origin.x + outerBorder.size.width; } if (point.y < innerBorder.origin.y) { point.y = outerBorder.origin.y; - } else if (point.y > innerBorder.origin.y+innerBorder.size.height) { - point.y = outerBorder.origin.y+outerBorder.size.height; + } else if (point.y > innerBorder.origin.y + innerBorder.size.height) { + point.y = outerBorder.origin.y + outerBorder.size.height; } [vertex replaceObjectAtIndex:i withObject:@(point)]; } } -CGPoint direction(CGPoint diff) { - if (diff.y == 0 && diff.x > 0) { - return NSMakePoint(0, 1); - } else if (diff.y == 0 && diff.x < 0) { - return NSMakePoint(0, -1); - } else if (diff.x == 0 && diff.y > 0) { - return NSMakePoint(-1, 0); - } else if (diff.x == 0 && diff.y < 0) { - return NSMakePoint(1, 0); +CGVector direction(CGVector diff) { + if (diff.dy == 0 && diff.dx > 0) { + return CGVectorMake(0, 1); + } else if (diff.dy == 0 && diff.dx < 0) { + return CGVectorMake(0, -1); + } else if (diff.dx == 0 && diff.dy > 0) { + return CGVectorMake(-1, 0); + } else if (diff.dx == 0 && diff.dy < 0) { + return CGVectorMake(1, 0); } else { - return NSMakePoint(0, 0); + return CGVectorMake(0, 0); } } -CAShapeLayer *shapeFromPath(CGPathRef path) { - CAShapeLayer *layer = [CAShapeLayer layer]; +CAShapeLayer* shapeFromPath(CGPathRef path) { + CAShapeLayer* layer = [CAShapeLayer layer]; layer.path = path; layer.fillRule = kCAFillRuleEvenOdd; return layer; } // Assumes clockwise iteration -void enlarge(NSMutableArray *vertex, CGFloat by) { +void enlarge(NSMutableArray* vertex, CGFloat by) { if (by != 0) { NSPoint previousPoint; NSPoint point; NSPoint nextPoint; - NSArray *original = [[NSArray alloc] initWithArray:vertex]; + NSArray* original = [[NSArray alloc] initWithArray:vertex]; NSPoint newPoint; - NSPoint displacement; - for (NSUInteger i = 0; i < original.count; i += 1){ - previousPoint = [original[(original.count+i-1)%original.count] pointValue]; + CGVector displacement; + for (NSUInteger i = 0; i < original.count; i += 1) { + previousPoint = + [original[(original.count + i - 1) % original.count] pointValue]; point = [original[i] pointValue]; - nextPoint = [original[(i+1)%original.count] pointValue]; + nextPoint = [original[(i + 1) % original.count] pointValue]; newPoint = point; - displacement = direction(NSMakePoint(point.x - previousPoint.x, point.y - previousPoint.y)); - newPoint.x += by * displacement.x; - newPoint.y += by * displacement.y; - displacement = direction(NSMakePoint(nextPoint.x - point.x, nextPoint.y - point.y)); - newPoint.x += by * displacement.x; - newPoint.y += by * displacement.y; + displacement = direction( + CGVectorMake(point.x - previousPoint.x, point.y - previousPoint.y)); + newPoint.x += by * displacement.dx; + newPoint.y += by * displacement.dy; + displacement = + direction(CGVectorMake(nextPoint.x - point.x, nextPoint.y - point.y)); + newPoint.x += by * displacement.dx; + newPoint.y += by * displacement.dy; [vertex replaceObjectAtIndex:i withObject:@(newPoint)]; } } } // Add gap between horizontal candidates -void expandHighlightWidth(NSRect *rect, CGFloat extraSurrounding) { +void expandHighlightWidth(NSRect* rect, CGFloat extraSurrounding) { if (!nearEmptyRect(*rect)) { rect->size.width += extraSurrounding; rect->origin.x -= extraSurrounding / 2; } } -void removeCorner(NSMutableArray *highlightedPoints, NSMutableSet *rightCorners, NSRect containingRect) { +void removeCorner(NSMutableArray* highlightedPoints, + NSMutableSet* rightCorners, + NSRect containingRect) { if (highlightedPoints && rightCorners) { - NSSet *originalRightCorners = [[NSSet alloc] initWithSet:rightCorners]; - for (NSNumber *cornerIndex in originalRightCorners) { + NSSet* originalRightCorners = + [[NSSet alloc] initWithSet:rightCorners]; + for (NSNumber* cornerIndex in originalRightCorners) { NSUInteger index = cornerIndex.unsignedIntegerValue; NSPoint corner = [highlightedPoints[index] pointValue]; - CGFloat dist = MIN(NSMaxY(containingRect) - corner.y, corner.y - NSMinY(containingRect)); + CGFloat dist = MIN(NSMaxY(containingRect) - corner.y, + corner.y - NSMinY(containingRect)); if (dist < 1e-2) { [rightCorners removeObject:cornerIndex]; } @@ -588,25 +662,41 @@ void removeCorner(NSMutableArray *highlightedPoints, NSMutableSet **)highlightedPoints points2:(NSMutableArray **)highlightedPoints2 rightCorners:(NSMutableSet **)rightCorners rightCorners2:(NSMutableSet **)rightCorners2 { +- (void)linearMultilineForRect:(NSRect)bodyRect + leadingRect:(NSRect)leadingRect + trailingRect:(NSRect)trailingRect + points1:(NSMutableArray**)highlightedPoints + points2:(NSMutableArray**)highlightedPoints2 + rightCorners:(NSMutableSet**)rightCorners + rightCorners2:(NSMutableSet**)rightCorners2 { // Handles the special case where containing boxes are separated - if (nearEmptyRect(bodyRect) && !nearEmptyRect(leadingRect) && !nearEmptyRect(trailingRect) && NSMaxX(trailingRect) < NSMinX(leadingRect)) { + if (nearEmptyRect(bodyRect) && !nearEmptyRect(leadingRect) && + !nearEmptyRect(trailingRect) && + NSMaxX(trailingRect) < NSMinX(leadingRect)) { *highlightedPoints = [rectVertex(leadingRect) mutableCopy]; *highlightedPoints2 = [rectVertex(trailingRect) mutableCopy]; - *rightCorners = [[NSMutableSet alloc] initWithObjects:@(2), @(3), nil]; - *rightCorners2 = [[NSMutableSet alloc] initWithObjects:@(0), @(1), nil]; + *rightCorners = + [[NSMutableSet alloc] initWithObjects:@(2), @(3), nil]; + *rightCorners2 = + [[NSMutableSet alloc] initWithObjects:@(0), @(1), nil]; } else { - *highlightedPoints = [multilineRectVertex(leadingRect, bodyRect, trailingRect) mutableCopy]; + *highlightedPoints = + [multilineRectVertex(leadingRect, bodyRect, trailingRect) mutableCopy]; } } -- (CGPathRef)drawHighlightedWith:(SquirrelTheme *)theme highlightedRange:(NSRange)highlightedRange backgroundRect:(NSRect)backgroundRect preeditRect:(NSRect)preeditRect containingRect:(NSRect)containingRect extraExpansion:(CGFloat)extraExpansion { +- (CGPathRef)drawHighlightedWith:(SquirrelTheme*)theme + highlightedRange:(NSRange)highlightedRange + backgroundRect:(NSRect)backgroundRect + preeditRect:(NSRect)preeditRect + containingRect:(NSRect)containingRect + extraExpansion:(CGFloat)extraExpansion { NSRect currentContainingRect = containingRect; currentContainingRect.size.width += extraExpansion * 2; currentContainingRect.size.height += extraExpansion * 2; currentContainingRect.origin.x -= extraExpansion; currentContainingRect.origin.y -= extraExpansion; - + CGFloat halfLinespace = theme.linespace / 2; NSRect innerBox = backgroundRect; innerBox.size.width -= (theme.edgeInset.width + 1) * 2 - 2 * extraExpansion; @@ -617,55 +707,91 @@ - (CGPathRef)drawHighlightedWith:(SquirrelTheme *)theme highlightedRange:(NSRang innerBox.origin.y += theme.edgeInset.height + 1; innerBox.size.height -= (theme.edgeInset.height + 1) * 2; } else { - innerBox.origin.y += preeditRect.size.height + theme.preeditLinespace / 2 + theme.hilitedCornerRadius / 2 + 1; - innerBox.size.height -= theme.edgeInset.height + preeditRect.size.height + theme.preeditLinespace / 2 + theme.hilitedCornerRadius / 2 + 2; + innerBox.origin.y += preeditRect.size.height + theme.preeditLinespace / 2 + + theme.hilitedCornerRadius / 2 + 1; + innerBox.size.height -= theme.edgeInset.height + preeditRect.size.height + + theme.preeditLinespace / 2 + + theme.hilitedCornerRadius / 2 + 2; } innerBox.size.height -= theme.linespace; innerBox.origin.y += halfLinespace; NSRect outerBox = backgroundRect; - outerBox.size.height -= preeditRect.size.height + MAX(0, theme.hilitedCornerRadius + theme.borderWidth) - 2 * extraExpansion; - outerBox.size.width -= MAX(0, theme.hilitedCornerRadius + theme.borderWidth) - 2 * extraExpansion; - outerBox.origin.x += MAX(0, theme.hilitedCornerRadius + theme.borderWidth) / 2 - extraExpansion; - outerBox.origin.y += preeditRect.size.height + MAX(0, theme.hilitedCornerRadius + theme.borderWidth) / 2 - extraExpansion; - - double effectiveRadius = MAX(0, theme.hilitedCornerRadius + 2 * extraExpansion / theme.hilitedCornerRadius * MAX(0, theme.cornerRadius - theme.hilitedCornerRadius)); + outerBox.size.height -= + preeditRect.size.height + + MAX(0, theme.hilitedCornerRadius + theme.borderWidth) - + 2 * extraExpansion; + outerBox.size.width -= MAX(0, theme.hilitedCornerRadius + theme.borderWidth) - + 2 * extraExpansion; + outerBox.origin.x += + MAX(0, theme.hilitedCornerRadius + theme.borderWidth) / 2 - + extraExpansion; + outerBox.origin.y += + preeditRect.size.height + + MAX(0, theme.hilitedCornerRadius + theme.borderWidth) / 2 - + extraExpansion; + + double effectiveRadius = + MAX(0, theme.hilitedCornerRadius + + 2 * extraExpansion / theme.hilitedCornerRadius * + MAX(0, theme.cornerRadius - theme.hilitedCornerRadius)); CGMutablePathRef path = CGPathCreateMutable(); - - if (theme.linear){ + + if (theme.linear) { NSRect leadingRect; NSRect bodyRect; NSRect trailingRect; - [self multilineRectForRange:[self convertRange:highlightedRange] leadingRect:&leadingRect bodyRect:&bodyRect trailingRect:&trailingRect extraSurounding:_seperatorWidth bounds:outerBox]; - - NSMutableArray *highlightedPoints; - NSMutableArray *highlightedPoints2; - NSMutableSet *rightCorners; - NSMutableSet *rightCorners2; - [self linearMultilineForRect:bodyRect leadingRect:leadingRect trailingRect:trailingRect points1:&highlightedPoints points2:&highlightedPoints2 rightCorners:&rightCorners rightCorners2:&rightCorners2]; + [self multilineRectForRange:[self convertRange:highlightedRange] + leadingRect:&leadingRect + bodyRect:&bodyRect + trailingRect:&trailingRect + extraSurounding:_seperatorWidth + bounds:outerBox]; + + NSMutableArray* highlightedPoints; + NSMutableArray* highlightedPoints2; + NSMutableSet* rightCorners; + NSMutableSet* rightCorners2; + [self linearMultilineForRect:bodyRect + leadingRect:leadingRect + trailingRect:trailingRect + points1:&highlightedPoints + points2:&highlightedPoints2 + rightCorners:&rightCorners + rightCorners2:&rightCorners2]; // Expand the boxes to reach proper border enlarge(highlightedPoints, extraExpansion); expand(highlightedPoints, innerBox, outerBox); removeCorner(highlightedPoints, rightCorners, currentContainingRect); - path = drawSmoothLines(highlightedPoints, rightCorners, 0.3*effectiveRadius, 1.4*effectiveRadius); + path = drawSmoothLines(highlightedPoints, rightCorners, + 0.3 * effectiveRadius, 1.4 * effectiveRadius); if (highlightedPoints2.count > 0) { enlarge(highlightedPoints2, extraExpansion); expand(highlightedPoints2, innerBox, outerBox); removeCorner(highlightedPoints2, rightCorners2, currentContainingRect); - CGPathRef path2 = drawSmoothLines(highlightedPoints2, rightCorners2, 0.3*effectiveRadius, 1.4*effectiveRadius); + CGPathRef path2 = + drawSmoothLines(highlightedPoints2, rightCorners2, + 0.3 * effectiveRadius, 1.4 * effectiveRadius); CGPathAddPath(path, NULL, path2); } } else { - NSRect highlightedRect = [self contentRectForRange:[self convertRange:highlightedRange]]; + NSRect highlightedRect = + [self contentRectForRange:[self convertRange:highlightedRange]]; if (!nearEmptyRect(highlightedRect)) { highlightedRect.size.width = backgroundRect.size.width; highlightedRect.size.height += theme.linespace; - highlightedRect.origin = NSMakePoint(backgroundRect.origin.x, highlightedRect.origin.y + theme.edgeInset.height - halfLinespace); + highlightedRect.origin = NSMakePoint( + backgroundRect.origin.x, + highlightedRect.origin.y + theme.edgeInset.height - halfLinespace); if (NSMaxRange(highlightedRange) == _textView.string.length) { highlightedRect.size.height += theme.edgeInset.height - halfLinespace; } - if (highlightedRange.location - ((_preeditRange.location == NSNotFound ? 0 : _preeditRange.location)+_preeditRange.length) <= 1) { + if (highlightedRange.location - + ((_preeditRange.location == NSNotFound ? 0 + : _preeditRange.location) + + _preeditRange.length) <= + 1) { if (_preeditRange.length == 0) { highlightedRect.size.height += theme.edgeInset.height - halfLinespace; highlightedRect.origin.y -= theme.edgeInset.height - halfLinespace; @@ -674,16 +800,18 @@ - (CGPathRef)drawHighlightedWith:(SquirrelTheme *)theme highlightedRange:(NSRang highlightedRect.origin.y -= theme.hilitedCornerRadius / 2; } } - NSMutableArray *highlightedPoints = [rectVertex(highlightedRect) mutableCopy]; + NSMutableArray* highlightedPoints = + [rectVertex(highlightedRect) mutableCopy]; enlarge(highlightedPoints, extraExpansion); expand(highlightedPoints, innerBox, outerBox); - path = drawSmoothLines(highlightedPoints, nil, 0.3*effectiveRadius, 1.4*effectiveRadius); + path = drawSmoothLines(highlightedPoints, nil, 0.3 * effectiveRadius, + 1.4 * effectiveRadius); } } return path; } -- (NSRect)carveInset:(NSRect)rect theme:(SquirrelTheme *)theme { +- (NSRect)carveInset:(NSRect)rect theme:(SquirrelTheme*)theme { NSRect newRect = rect; newRect.size.height -= (theme.hilitedCornerRadius + theme.borderWidth) * 2; newRect.size.width -= (theme.hilitedCornerRadius + theme.borderWidth) * 2; @@ -699,7 +827,7 @@ - (void)drawRect:(NSRect)dirtyRect { CGMutablePathRef candidatePaths = CGPathCreateMutable(); CGMutablePathRef highlightedPreeditPath = CGPathCreateMutable(); CGPathRef preeditPath = CGPathCreateMutable(); - SquirrelTheme * theme = self.currentTheme; + SquirrelTheme* theme = self.currentTheme; NSPoint textFieldOrigin = dirtyRect.origin; textFieldOrigin.y += theme.edgeInset.height; @@ -715,10 +843,14 @@ - (void)drawRect:(NSRect)dirtyRect { preeditRect = [self contentRectForRange:[self convertRange:_preeditRange]]; if (!nearEmptyRect(preeditRect)) { preeditRect.size.width = backgroundRect.size.width; - preeditRect.size.height += theme.edgeInset.height + theme.preeditLinespace / 2 + theme.hilitedCornerRadius / 2; + preeditRect.size.height += theme.edgeInset.height + + theme.preeditLinespace / 2 + + theme.hilitedCornerRadius / 2; preeditRect.origin = backgroundRect.origin; if (_candidateRanges.count == 0) { - preeditRect.size.height += theme.edgeInset.height - theme.preeditLinespace / 2 - theme.hilitedCornerRadius / 2; + preeditRect.size.height += theme.edgeInset.height - + theme.preeditLinespace / 2 - + theme.hilitedCornerRadius / 2; } containingRect.size.height -= preeditRect.size.height; containingRect.origin.y += preeditRect.size.height; @@ -735,19 +867,31 @@ - (void)drawRect:(NSRect)dirtyRect { if (i == _hilightedIndex) { // Draw highlighted Rect if (candidateRange.length > 0 && theme.highlightedBackColor != nil) { - highlightedPath = [self drawHighlightedWith:theme highlightedRange:candidateRange backgroundRect:backgroundRect preeditRect:preeditRect containingRect:containingRect extraExpansion:0]; + highlightedPath = [self drawHighlightedWith:theme + highlightedRange:candidateRange + backgroundRect:backgroundRect + preeditRect:preeditRect + containingRect:containingRect + extraExpansion:0]; } } else { // Draw other highlighted Rect if (candidateRange.length > 0 && theme.candidateBackColor != nil) { - CGPathRef candidatePath = [self drawHighlightedWith:theme highlightedRange:candidateRange backgroundRect:backgroundRect preeditRect:preeditRect containingRect:containingRect extraExpansion:theme.surroundingExtraExpansion]; + CGPathRef candidatePath = + [self drawHighlightedWith:theme + highlightedRange:candidateRange + backgroundRect:backgroundRect + preeditRect:preeditRect + containingRect:containingRect + extraExpansion:theme.surroundingExtraExpansion]; CGPathAddPath(candidatePaths, NULL, candidatePath); } } } // Draw highlighted part of preedit text - if (_highlightedPreeditRange.length > 0 && theme.highlightedPreeditColor != nil) { + if (_highlightedPreeditRange.length > 0 && + theme.highlightedPreeditColor != nil) { NSRect innerBox = preeditRect; innerBox.size.width -= (theme.edgeInset.width + 1) * 2; innerBox.origin.x += theme.edgeInset.width + 1; @@ -755,42 +899,65 @@ - (void)drawRect:(NSRect)dirtyRect { if (_candidateRanges.count == 0) { innerBox.size.height -= (theme.edgeInset.height + 1) * 2; } else { - innerBox.size.height -= theme.edgeInset.height + theme.preeditLinespace / 2 + theme.hilitedCornerRadius / 2 + 2; + innerBox.size.height -= theme.edgeInset.height + + theme.preeditLinespace / 2 + + theme.hilitedCornerRadius / 2 + 2; } NSRect outerBox = preeditRect; - outerBox.size.height -= MAX(0, theme.hilitedCornerRadius + theme.borderWidth); - outerBox.size.width -= MAX(0, theme.hilitedCornerRadius + theme.borderWidth); - outerBox.origin.x += MAX(0, theme.hilitedCornerRadius + theme.borderWidth) / 2; - outerBox.origin.y += MAX(0, theme.hilitedCornerRadius + theme.borderWidth) / 2; - + outerBox.size.height -= + MAX(0, theme.hilitedCornerRadius + theme.borderWidth); + outerBox.size.width -= + MAX(0, theme.hilitedCornerRadius + theme.borderWidth); + outerBox.origin.x += + MAX(0, theme.hilitedCornerRadius + theme.borderWidth) / 2; + outerBox.origin.y += + MAX(0, theme.hilitedCornerRadius + theme.borderWidth) / 2; + NSRect leadingRect; NSRect bodyRect; NSRect trailingRect; - [self multilineRectForRange:[self convertRange:_highlightedPreeditRange] leadingRect:&leadingRect bodyRect:&bodyRect trailingRect:&trailingRect extraSurounding:0 bounds:outerBox]; - - NSMutableArray *highlightedPreeditPoints; - NSMutableArray *highlightedPreeditPoints2; - NSMutableSet *rightCorners; - NSMutableSet *rightCorners2; - [self linearMultilineForRect:bodyRect leadingRect:leadingRect trailingRect:trailingRect points1:&highlightedPreeditPoints points2:&highlightedPreeditPoints2 rightCorners:&rightCorners rightCorners2:&rightCorners2]; - + [self multilineRectForRange:[self convertRange:_highlightedPreeditRange] + leadingRect:&leadingRect + bodyRect:&bodyRect + trailingRect:&trailingRect + extraSurounding:0 + bounds:outerBox]; + + NSMutableArray* highlightedPreeditPoints; + NSMutableArray* highlightedPreeditPoints2; + NSMutableSet* rightCorners; + NSMutableSet* rightCorners2; + [self linearMultilineForRect:bodyRect + leadingRect:leadingRect + trailingRect:trailingRect + points1:&highlightedPreeditPoints + points2:&highlightedPreeditPoints2 + rightCorners:&rightCorners + rightCorners2:&rightCorners2]; + containingRect = [self carveInset:preeditRect theme:theme]; expand(highlightedPreeditPoints, innerBox, outerBox); removeCorner(highlightedPreeditPoints, rightCorners, containingRect); - highlightedPreeditPath = drawSmoothLines(highlightedPreeditPoints, rightCorners, 0.3*theme.hilitedCornerRadius, 1.4*theme.hilitedCornerRadius); + highlightedPreeditPath = drawSmoothLines( + highlightedPreeditPoints, rightCorners, 0.3 * theme.hilitedCornerRadius, + 1.4 * theme.hilitedCornerRadius); if (highlightedPreeditPoints2.count > 0) { expand(highlightedPreeditPoints2, innerBox, outerBox); removeCorner(highlightedPreeditPoints2, rightCorners2, containingRect); - CGPathRef highlightedPreeditPath2 = drawSmoothLines(highlightedPreeditPoints2, rightCorners2, 0.3*theme.hilitedCornerRadius, 1.4*theme.hilitedCornerRadius); + CGPathRef highlightedPreeditPath2 = drawSmoothLines( + highlightedPreeditPoints2, rightCorners2, + 0.3 * theme.hilitedCornerRadius, 1.4 * theme.hilitedCornerRadius); CGPathAddPath(highlightedPreeditPath, NULL, highlightedPreeditPath2); } } [NSBezierPath setDefaultLineWidth:0]; - backgroundPath = drawSmoothLines(rectVertex(backgroundRect), nil, theme.cornerRadius*0.3, theme.cornerRadius*1.4); + backgroundPath = + drawSmoothLines(rectVertex(backgroundRect), nil, theme.cornerRadius * 0.3, + theme.cornerRadius * 1.4); _shape.path = CGPathCreateMutableCopy(backgroundPath); - [self.layer setSublayers: NULL]; + [self.layer setSublayers:NULL]; CGMutablePathRef backPath = CGPathCreateMutableCopy(backgroundPath); if (!CGPathIsEmpty(preeditPath)) { CGPathAddPath(backPath, NULL, preeditPath); @@ -803,47 +970,49 @@ - (void)drawRect:(NSRect)dirtyRect { CGPathAddPath(backPath, NULL, candidatePaths); } } - CAShapeLayer *panelLayer = shapeFromPath(backPath); + CAShapeLayer* panelLayer = shapeFromPath(backPath); panelLayer.fillColor = theme.backgroundColor.CGColor; - CAShapeLayer *panelLayerMask = shapeFromPath(backgroundPath); + CAShapeLayer* panelLayerMask = shapeFromPath(backgroundPath); panelLayer.mask = panelLayerMask; - [self.layer addSublayer: panelLayer]; + [self.layer addSublayer:panelLayer]; if (theme.preeditBackgroundColor && !CGPathIsEmpty(preeditPath)) { - CAShapeLayer *layer = shapeFromPath(preeditPath); + CAShapeLayer* layer = shapeFromPath(preeditPath); layer.fillColor = theme.preeditBackgroundColor.CGColor; CGMutablePathRef maskPath = CGPathCreateMutableCopy(backgroundPath); if (theme.mutualExclusive && !CGPathIsEmpty(highlightedPreeditPath)) { CGPathAddPath(maskPath, NULL, highlightedPreeditPath); } - CAShapeLayer *mask = shapeFromPath(maskPath); + CAShapeLayer* mask = shapeFromPath(maskPath); layer.mask = mask; - [panelLayer addSublayer: layer]; + [panelLayer addSublayer:layer]; } if (theme.borderWidth > 0 && theme.borderColor) { - CAShapeLayer *borderLayer = shapeFromPath(backgroundPath); + CAShapeLayer* borderLayer = shapeFromPath(backgroundPath); borderLayer.lineWidth = theme.borderWidth * 2; borderLayer.strokeColor = theme.borderColor.CGColor; borderLayer.fillColor = NULL; - [panelLayer addSublayer: borderLayer]; + [panelLayer addSublayer:borderLayer]; } if (theme.highlightedPreeditColor && !CGPathIsEmpty(highlightedPreeditPath)) { - CAShapeLayer *layer = shapeFromPath(highlightedPreeditPath); + CAShapeLayer* layer = shapeFromPath(highlightedPreeditPath); layer.fillColor = theme.highlightedPreeditColor.CGColor; - [panelLayer addSublayer: layer]; + [panelLayer addSublayer:layer]; } if (theme.candidateBackColor && !CGPathIsEmpty(candidatePaths)) { - CAShapeLayer *layer = shapeFromPath(candidatePaths); + CAShapeLayer* layer = shapeFromPath(candidatePaths); layer.fillColor = theme.candidateBackColor.CGColor; - [panelLayer addSublayer: layer]; + [panelLayer addSublayer:layer]; } if (theme.highlightedBackColor && !CGPathIsEmpty(highlightedPath)) { - CAShapeLayer *layer = shapeFromPath(highlightedPath); + CAShapeLayer* layer = shapeFromPath(highlightedPath); layer.fillColor = theme.highlightedBackColor.CGColor; if (theme.shadowSize > 0) { - CAShapeLayer *shadowLayer = [CAShapeLayer layer]; + CAShapeLayer* shadowLayer = [CAShapeLayer layer]; shadowLayer.shadowColor = NSColor.blackColor.CGColor; - shadowLayer.shadowOffset = NSMakeSize(theme.shadowSize/2, (theme.vertical ? -1 : 1) * theme.shadowSize/2); + shadowLayer.shadowOffset = + NSMakeSize(theme.shadowSize / 2, + (theme.vertical ? -1 : 1) * theme.shadowSize / 2); shadowLayer.shadowPath = highlightedPath; shadowLayer.shadowRadius = theme.shadowSize; shadowLayer.shadowOpacity = 0.2; @@ -852,28 +1021,34 @@ - (void)drawRect:(NSRect)dirtyRect { if (!CGPathIsEmpty(preeditPath)) { CGPathAddPath(maskPath, NULL, preeditPath); } - CAShapeLayer *shadowLayerMask = shapeFromPath(maskPath); + CAShapeLayer* shadowLayerMask = shapeFromPath(maskPath); shadowLayer.mask = shadowLayerMask; - layer.strokeColor = [NSColor.blackColor colorWithAlphaComponent:0.15].CGColor; + layer.strokeColor = + [NSColor.blackColor colorWithAlphaComponent:0.15].CGColor; layer.lineWidth = 0.5; - [layer addSublayer: shadowLayer]; + [layer addSublayer:shadowLayer]; } - [panelLayer addSublayer: layer]; + [panelLayer addSublayer:layer]; } - [_textView setTextContainerInset:NSMakeSize(textFieldOrigin.x, textFieldOrigin.y)]; + [_textView + setTextContainerInset:NSMakeSize(textFieldOrigin.x, textFieldOrigin.y)]; } -- (BOOL)clickAtPoint:(NSPoint)_point index:(NSInteger *)_index { +- (BOOL)clickAtPoint:(NSPoint)_point index:(NSInteger*)_index { if (CGPathContainsPoint(_shape.path, nil, _point, NO)) { - NSPoint point = NSMakePoint(_point.x - self.textView.textContainerInset.width, - _point.y - self.textView.textContainerInset.height); - NSTextLayoutFragment *fragment = [self.layoutManager textLayoutFragmentForPosition:point]; + NSPoint point = + NSMakePoint(_point.x - self.textView.textContainerInset.width, + _point.y - self.textView.textContainerInset.height); + NSTextLayoutFragment* fragment = + [self.layoutManager textLayoutFragmentForPosition:point]; if (fragment) { point = NSMakePoint(point.x - NSMinX(fragment.layoutFragmentFrame), point.y - NSMinY(fragment.layoutFragmentFrame)); - NSInteger index = [self.layoutManager offsetFromLocation: self.layoutManager.documentRange.location toLocation: fragment.rangeInElement.location]; + NSInteger index = [self.layoutManager + offsetFromLocation:self.layoutManager.documentRange.location + toLocation:fragment.rangeInElement.location]; for (NSUInteger i = 0; i < fragment.textLineFragments.count; i += 1) { - NSTextLineFragment *lineFragment = fragment.textLineFragments[i]; + NSTextLineFragment* lineFragment = fragment.textLineFragments[i]; if (CGRectContainsPoint(lineFragment.typographicBounds, point)) { point = NSMakePoint(point.x - NSMinX(lineFragment.typographicBounds), point.y - NSMinY(lineFragment.typographicBounds)); @@ -898,25 +1073,25 @@ - (BOOL)clickAtPoint:(NSPoint)_point index:(NSInteger *)_index { @end @implementation SquirrelPanel { - SquirrelView *_view; - NSVisualEffectView *_back; + SquirrelView* _view; + NSVisualEffectView* _back; NSRect _screenRect; CGFloat _maxHeight; - NSString *_statusMessage; - NSTimer *_statusTimer; - - NSString *_preedit; + NSString* _statusMessage; + NSTimer* _statusTimer; + + NSString* _preedit; NSRange _selRange; NSUInteger _caretPos; - NSArray *_candidates; - NSArray *_comments; - NSArray *_labels; + NSArray* _candidates; + NSArray* _comments; + NSArray* _labels; NSUInteger _index; NSUInteger _cursorIndex; NSPoint _scrollDirection; - NSDate *_scrollTime; + NSDate* _scrollTime; } - (BOOL)linear { @@ -935,74 +1110,90 @@ - (BOOL)inlineCandidate { return _view.currentTheme.inlineCandidate; } -NSAttributedString *insert(NSString *separator, NSAttributedString *betweenText) { - NSRange range = [betweenText.string rangeOfComposedCharacterSequenceAtIndex:0]; - NSAttributedString *attributedSeperator = [[NSAttributedString alloc] initWithString:separator attributes:[betweenText attributesAtIndex:0 effectiveRange:nil]]; +NSAttributedString* insert(NSString* separator, + NSAttributedString* betweenText) { + NSRange range = + [betweenText.string rangeOfComposedCharacterSequenceAtIndex:0]; + NSAttributedString* attributedSeperator = [[NSAttributedString alloc] + initWithString:separator + attributes:[betweenText attributesAtIndex:0 effectiveRange:nil]]; NSUInteger i = NSMaxRange(range); - NSMutableAttributedString *workingString = [[betweenText attributedSubstringFromRange:range] mutableCopy]; + NSMutableAttributedString* workingString = + [[betweenText attributedSubstringFromRange:range] mutableCopy]; while (i < betweenText.length) { range = [betweenText.string rangeOfComposedCharacterSequenceAtIndex:i]; [workingString appendAttributedString:attributedSeperator]; - [workingString appendAttributedString:[betweenText attributedSubstringFromRange:range]]; + [workingString + appendAttributedString:[betweenText + attributedSubstringFromRange:range]]; i = NSMaxRange(range); } return workingString; } -+ (NSColor *)secondaryTextColor { ++ (NSColor*)secondaryTextColor { return [NSColor secondaryLabelColor]; } - (void)initializeUIStyleForDarkMode:(BOOL)isDark { - SquirrelTheme *theme = [_view selectTheme:isDark]; + SquirrelTheme* theme = [_view selectTheme:isDark]; theme.native = YES; theme.memorizeSize = YES; theme.candidateFormat = kDefaultCandidateFormat; - NSColor *secondaryTextColor = [[self class] secondaryTextColor]; + NSColor* secondaryTextColor = [[self class] secondaryTextColor]; - NSMutableDictionary *attrs = [[NSMutableDictionary alloc] init]; + NSMutableDictionary* attrs = [[NSMutableDictionary alloc] init]; attrs[NSForegroundColorAttributeName] = [NSColor controlTextColor]; attrs[NSFontAttributeName] = [NSFont userFontOfSize:kDefaultFontSize]; - NSMutableDictionary *highlightedAttrs = [[NSMutableDictionary alloc] init]; - highlightedAttrs[NSForegroundColorAttributeName] = [NSColor selectedControlTextColor]; - highlightedAttrs[NSFontAttributeName] = [NSFont userFontOfSize:kDefaultFontSize]; + NSMutableDictionary* highlightedAttrs = [[NSMutableDictionary alloc] init]; + highlightedAttrs[NSForegroundColorAttributeName] = + [NSColor selectedControlTextColor]; + highlightedAttrs[NSFontAttributeName] = + [NSFont userFontOfSize:kDefaultFontSize]; - NSMutableDictionary *labelAttrs = [attrs mutableCopy]; - NSMutableDictionary *labelHighlightedAttrs = [highlightedAttrs mutableCopy]; + NSMutableDictionary* labelAttrs = [attrs mutableCopy]; + NSMutableDictionary* labelHighlightedAttrs = [highlightedAttrs mutableCopy]; - NSMutableDictionary *commentAttrs = [[NSMutableDictionary alloc] init]; + NSMutableDictionary* commentAttrs = [[NSMutableDictionary alloc] init]; commentAttrs[NSForegroundColorAttributeName] = secondaryTextColor; commentAttrs[NSFontAttributeName] = [NSFont userFontOfSize:kDefaultFontSize]; - NSMutableDictionary *commentHighlightedAttrs = [commentAttrs mutableCopy]; + NSMutableDictionary* commentHighlightedAttrs = [commentAttrs mutableCopy]; - NSMutableDictionary *preeditAttrs = [[NSMutableDictionary alloc] init]; + NSMutableDictionary* preeditAttrs = [[NSMutableDictionary alloc] init]; preeditAttrs[NSForegroundColorAttributeName] = secondaryTextColor; preeditAttrs[NSFontAttributeName] = [NSFont userFontOfSize:kDefaultFontSize]; - NSMutableDictionary *preeditHighlightedAttrs = [[NSMutableDictionary alloc] init]; - preeditHighlightedAttrs[NSForegroundColorAttributeName] = [NSColor controlTextColor]; - preeditHighlightedAttrs[NSFontAttributeName] = [NSFont userFontOfSize:kDefaultFontSize]; - - NSParagraphStyle *paragraphStyle = [NSParagraphStyle defaultParagraphStyle]; - NSParagraphStyle *preeditParagraphStyle = [NSParagraphStyle defaultParagraphStyle]; - - [theme setAttrs:attrs - highlightedAttrs:highlightedAttrs - labelAttrs:labelAttrs - labelHighlightedAttrs:labelHighlightedAttrs - commentAttrs:commentAttrs - commentHighlightedAttrs:commentHighlightedAttrs - preeditAttrs:preeditAttrs - preeditHighlightedAttrs:preeditHighlightedAttrs]; + NSMutableDictionary* preeditHighlightedAttrs = + [[NSMutableDictionary alloc] init]; + preeditHighlightedAttrs[NSForegroundColorAttributeName] = + [NSColor controlTextColor]; + preeditHighlightedAttrs[NSFontAttributeName] = + [NSFont userFontOfSize:kDefaultFontSize]; + + NSParagraphStyle* paragraphStyle = [NSParagraphStyle defaultParagraphStyle]; + NSParagraphStyle* preeditParagraphStyle = + [NSParagraphStyle defaultParagraphStyle]; + + [theme setAttrs:attrs + highlightedAttrs:highlightedAttrs + labelAttrs:labelAttrs + labelHighlightedAttrs:labelHighlightedAttrs + commentAttrs:commentAttrs + commentHighlightedAttrs:commentHighlightedAttrs + preeditAttrs:preeditAttrs + preeditHighlightedAttrs:preeditHighlightedAttrs]; [theme setParagraphStyle:paragraphStyle - preeditParagraphStyle:preeditParagraphStyle]; + preeditParagraphStyle:preeditParagraphStyle]; } - (instancetype)init { - self = [super initWithContentRect:_position styleMask:NSWindowStyleMaskNonactivatingPanel backing:NSBackingStoreBuffered defer:YES]; + self = [super initWithContentRect:_position + styleMask:NSWindowStyleMaskNonactivatingPanel + backing:NSBackingStoreBuffered + defer:YES]; if (self) { self.alphaValue = 1.0; // _window.level = NSScreenSaverWindowLevel + 1; @@ -1011,7 +1202,7 @@ - (instancetype)init { self.hasShadow = YES; self.opaque = NO; self.backgroundColor = [NSColor clearColor]; - NSView *contentView = [[NSView alloc] init]; + NSView* contentView = [[NSView alloc] init]; _view = [[SquirrelView alloc] initWithFrame:self.contentView.frame]; _back = [[NSVisualEffectView alloc] init]; _back.blendingMode = NSVisualEffectBlendingModeBehindWindow; @@ -1022,7 +1213,7 @@ - (instancetype)init { [contentView addSubview:_back]; [contentView addSubview:_view]; [contentView addSubview:_view.textView]; - + self.contentView = contentView; [self initializeUIStyleForDarkMode:NO]; [self initializeUIStyleForDarkMode:YES]; @@ -1037,12 +1228,12 @@ - (NSPoint)mousePosition { return [_view convertPoint:point fromView:nil]; } -- (void)sendEvent:(NSEvent *)event { +- (void)sendEvent:(NSEvent*)event { switch (event.type) { case NSEventTypeLeftMouseDown: { NSPoint point = [self mousePosition]; NSInteger index = -1; - if ([_view clickAtPoint: point index:&index]) { + if ([_view clickAtPoint:point index:&index]) { if (index >= 0 && index < _candidates.count) { _index = index; } @@ -1051,7 +1242,7 @@ - (void)sendEvent:(NSEvent *)event { case NSEventTypeLeftMouseUp: { NSPoint point = [self mousePosition]; NSInteger index = -1; - if ([_view clickAtPoint: point index:&index]) { + if ([_view clickAtPoint:point index:&index]) { if (index >= 0 && index < _candidates.count && index == _index) { [_inputController selectCandidate:index]; } @@ -1063,48 +1254,68 @@ - (void)sendEvent:(NSEvent *)event { case NSEventTypeMouseExited: { self.acceptsMouseMovedEvents = NO; if (_cursorIndex != _index) { - [self showPreedit:_preedit selRange:_selRange caretPos:_caretPos candidates:_candidates comments:_comments labels:_labels - highlighted:_index update:NO]; + [self showPreedit:_preedit + selRange:_selRange + caretPos:_caretPos + candidates:_candidates + comments:_comments + labels:_labels + highlighted:_index + update:NO]; } } break; case NSEventTypeMouseMoved: { NSPoint point = [self mousePosition]; NSInteger index = -1; - if ([_view clickAtPoint: point index:&index]) { + if ([_view clickAtPoint:point index:&index]) { if (index >= 0 && index < _candidates.count && _cursorIndex != index) { - [self showPreedit:_preedit selRange:_selRange caretPos:_caretPos candidates:_candidates comments:_comments labels:_labels - highlighted:index update:NO]; + [self showPreedit:_preedit + selRange:_selRange + caretPos:_caretPos + candidates:_candidates + comments:_comments + labels:_labels + highlighted:index + update:NO]; } } } break; case NSEventTypeScrollWheel: { if (event.phase == NSEventPhaseBegan) { _scrollDirection = NSMakePoint(0, 0); - } else if (event.phase == NSEventPhaseEnded || (event.phase == NSEventPhaseNone && event.momentumPhase != NSEventPhaseNone)) { - if (_scrollDirection.x > 10 && ABS(_scrollDirection.x) > ABS(_scrollDirection.y)) { + } else if (event.phase == NSEventPhaseEnded || + (event.phase == NSEventPhaseNone && + event.momentumPhase != NSEventPhaseNone)) { + if (_scrollDirection.x > 10 && + ABS(_scrollDirection.x) > ABS(_scrollDirection.y)) { if (_view.currentTheme.vertical) { [self.inputController pageUp:NO]; } else { [self.inputController pageUp:YES]; } - } else if (_scrollDirection.x < -10 && ABS(_scrollDirection.x) > ABS(_scrollDirection.y)) { + } else if (_scrollDirection.x < -10 && + ABS(_scrollDirection.x) > ABS(_scrollDirection.y)) { if (_view.currentTheme.vertical) { [self.inputController pageUp:YES]; } else { [self.inputController pageUp:NO]; } - } else if (_scrollDirection.y > 10 && ABS(_scrollDirection.x) < ABS(_scrollDirection.y)) { + } else if (_scrollDirection.y > 10 && + ABS(_scrollDirection.x) < ABS(_scrollDirection.y)) { [self.inputController pageUp:YES]; - } else if (_scrollDirection.y < -10 && ABS(_scrollDirection.x) < ABS(_scrollDirection.y)) { + } else if (_scrollDirection.y < -10 && + ABS(_scrollDirection.x) < ABS(_scrollDirection.y)) { [self.inputController pageUp:NO]; } _scrollDirection = NSMakePoint(0, 0); - } else if (event.phase == NSEventPhaseNone && event.momentumPhase == NSEventPhaseNone) { + } else if (event.phase == NSEventPhaseNone && + event.momentumPhase == NSEventPhaseNone) { if (_scrollTime && [_scrollTime timeIntervalSinceNow] > 1.0) { _scrollDirection = NSMakePoint(0, 0); } _scrollTime = [NSDate now]; - if ((_scrollDirection.y >= 0 && event.scrollingDeltaY > 0) || (_scrollDirection.y <= 0 && event.scrollingDeltaY < 0)) { + if ((_scrollDirection.y >= 0 && event.scrollingDeltaY > 0) || + (_scrollDirection.y <= 0 && event.scrollingDeltaY < 0)) { _scrollDirection.y += event.scrollingDeltaY; } else { _scrollDirection = NSMakePoint(0, 0); @@ -1131,7 +1342,7 @@ - (void)sendEvent:(NSEvent *)event { - (void)getCurrentScreen { // get current screen _screenRect = [NSScreen mainScreen].frame; - NSArray *screens = [NSScreen screens]; + NSArray* screens = [NSScreen screens]; NSUInteger i; for (i = 0; i < screens.count; ++i) { @@ -1143,63 +1354,83 @@ - (void)getCurrentScreen { } } -- (CGFloat)getMaxTextWidth:(SquirrelTheme *)theme { - NSFont *currentFont = theme.attrs[NSFontAttributeName]; +- (CGFloat)getMaxTextWidth:(SquirrelTheme*)theme { + NSFont* currentFont = theme.attrs[NSFontAttributeName]; CGFloat fontScale = currentFont.pointSize / 12; - CGFloat textWidthRatio = MIN(1.0, 1.0 / (theme.vertical ? 4 : 3) + fontScale / 12); - return theme.vertical - ? NSHeight(_screenRect) * textWidthRatio - theme.edgeInset.height * 2 - : NSWidth(_screenRect) * textWidthRatio - theme.edgeInset.width * 2; + CGFloat textWidthRatio = + MIN(1.0, 1.0 / (theme.vertical ? 4 : 3) + fontScale / 12); + return theme.vertical ? NSHeight(_screenRect) * textWidthRatio - + theme.edgeInset.height * 2 + : NSWidth(_screenRect) * textWidthRatio - + theme.edgeInset.width * 2; } -// Get the window size, the windows will be the dirtyRect in SquirrelView.drawRect +// Get the window size, the windows will be the dirtyRect in +// SquirrelView.drawRect - (void)show { [self getCurrentScreen]; - SquirrelTheme *theme = _view.currentTheme; + SquirrelTheme* theme = _view.currentTheme; - NSAppearance *requestedAppearance = theme.native ? nil : [NSAppearance appearanceNamed:NSAppearanceNameAqua]; + NSAppearance* requestedAppearance = + theme.native ? nil : [NSAppearance appearanceNamed:NSAppearanceNameAqua]; if (self.appearance != requestedAppearance) { self.appearance = requestedAppearance; } - //Break line if the text is too long, based on screen size. + // Break line if the text is too long, based on screen size. CGFloat textWidth = [self getMaxTextWidth:theme]; - CGFloat maxTextHeight = theme.vertical ? _screenRect.size.width - theme.edgeInset.width * 2 : _screenRect.size.height - theme.edgeInset.height * 2; - _view.textView.textContainer.containerSize = NSMakeSize(textWidth, maxTextHeight); + CGFloat maxTextHeight = + theme.vertical ? _screenRect.size.width - theme.edgeInset.width * 2 + : _screenRect.size.height - theme.edgeInset.height * 2; + _view.textView.textContainer.containerSize = + NSMakeSize(textWidth, maxTextHeight); NSRect windowRect; // in vertical mode, the width and height are interchanged NSRect contentRect = _view.contentRect; - if (theme.memorizeSize && ((theme.vertical && NSMidY(_position) / NSHeight(_screenRect) < 0.5) || - (!theme.vertical && NSMinX(_position)+MAX(contentRect.size.width, _maxHeight)+theme.edgeInset.width*2 > NSMaxX(_screenRect)))) { + if (theme.memorizeSize && + ((theme.vertical && NSMidY(_position) / NSHeight(_screenRect) < 0.5) || + (!theme.vertical && NSMinX(_position) + + MAX(contentRect.size.width, _maxHeight) + + theme.edgeInset.width * 2 > + NSMaxX(_screenRect)))) { if (contentRect.size.width >= _maxHeight) { _maxHeight = contentRect.size.width; } else { contentRect.size.width = _maxHeight; - _view.textView.textContainer.containerSize = NSMakeSize(_maxHeight, maxTextHeight); + _view.textView.textContainer.containerSize = + NSMakeSize(_maxHeight, maxTextHeight); } } if (theme.vertical) { - windowRect.size = NSMakeSize(contentRect.size.height + theme.edgeInset.height * 2, - contentRect.size.width + theme.edgeInset.width * 2); - // To avoid jumping up and down while typing, use the lower screen when typing on upper, and vice versa + windowRect.size = + NSMakeSize(contentRect.size.height + theme.edgeInset.height * 2, + contentRect.size.width + theme.edgeInset.width * 2); + // To avoid jumping up and down while typing, use the lower screen when + // typing on upper, and vice versa if (NSMidY(_position) / NSHeight(_screenRect) >= 0.5) { - windowRect.origin.y = NSMinY(_position) - kOffsetHeight - NSHeight(windowRect); + windowRect.origin.y = + NSMinY(_position) - kOffsetHeight - NSHeight(windowRect); } else { windowRect.origin.y = NSMaxY(_position) + kOffsetHeight; } // Make the first candidate fixed at the left of cursor - windowRect.origin.x = NSMinX(_position) - windowRect.size.width - kOffsetHeight; + windowRect.origin.x = + NSMinX(_position) - windowRect.size.width - kOffsetHeight; if (_view.preeditRange.length > 0) { - NSSize preeditSize = [_view contentRectForRange:[_view convertRange:_view.preeditRange]].size; + NSSize preeditSize = + [_view contentRectForRange:[_view convertRange:_view.preeditRange]] + .size; windowRect.origin.x += preeditSize.height + theme.edgeInset.width; } } else { - windowRect.size = NSMakeSize(contentRect.size.width + theme.edgeInset.width * 2, - contentRect.size.height + theme.edgeInset.height * 2); - windowRect.origin = NSMakePoint(NSMinX(_position), - NSMinY(_position) - kOffsetHeight - NSHeight(windowRect)); + windowRect.size = + NSMakeSize(contentRect.size.width + theme.edgeInset.width * 2, + contentRect.size.height + theme.edgeInset.height * 2); + windowRect.origin = + NSMakePoint(NSMinX(_position), + NSMinY(_position) - kOffsetHeight - NSHeight(windowRect)); } if (NSMaxX(windowRect) > NSMaxX(_screenRect)) { @@ -1260,15 +1491,14 @@ - (void)hide { } // Main function to add attributes to text output from librime -- (void)showPreedit:(NSString *)preedit +- (void)showPreedit:(NSString*)preedit selRange:(NSRange)selRange caretPos:(NSUInteger)caretPos - candidates:(NSArray *)candidates - comments:(NSArray *)comments - labels:(NSArray *)labels + candidates:(NSArray*)candidates + comments:(NSArray*)comments + labels:(NSArray*)labels highlighted:(NSUInteger)index update:(BOOL)update { - if (update) { _preedit = preedit; _selRange = selRange; @@ -1279,7 +1509,7 @@ - (void)showPreedit:(NSString *)preedit _index = index; } _cursorIndex = index; - + NSUInteger numCandidates = candidates.count; if (numCandidates || (preedit && preedit.length)) { _statusMessage = nil; @@ -1297,37 +1527,38 @@ - (void)showPreedit:(NSString *)preedit return; } - SquirrelTheme *theme = _view.currentTheme; + SquirrelTheme* theme = _view.currentTheme; [self getCurrentScreen]; CGFloat maxTextWidth = [self getMaxTextWidth:theme]; - NSMutableAttributedString *text = [[NSMutableAttributedString alloc] init]; + NSMutableAttributedString* text = [[NSMutableAttributedString alloc] init]; NSUInteger candidateStartPos = 0; NSRange preeditRange = NSMakeRange(NSNotFound, 0); NSRange highlightedPreeditRange = NSMakeRange(NSNotFound, 0); // preedit if (preedit) { - NSMutableAttributedString *line = [[NSMutableAttributedString alloc] init]; + NSMutableAttributedString* line = [[NSMutableAttributedString alloc] init]; if (selRange.location > 0) { [line appendAttributedString: [[NSAttributedString alloc] - initWithString:[preedit substringToIndex:selRange.location] - attributes:theme.preeditAttrs]]; + initWithString:[preedit substringToIndex:selRange.location] + attributes:theme.preeditAttrs]]; } if (selRange.length > 0) { NSUInteger highlightedPreeditStart = line.length; [line appendAttributedString: [[NSAttributedString alloc] initWithString:[preedit substringWithRange:selRange] - attributes:theme.preeditHighlightedAttrs]]; - highlightedPreeditRange = NSMakeRange(highlightedPreeditStart, line.length - highlightedPreeditStart); + attributes:theme.preeditHighlightedAttrs]]; + highlightedPreeditRange = NSMakeRange( + highlightedPreeditStart, line.length - highlightedPreeditStart); } if (NSMaxRange(selRange) < preedit.length) { - [line - appendAttributedString: - [[NSAttributedString alloc] - initWithString:[preedit substringFromIndex:NSMaxRange(selRange)] - attributes:theme.preeditAttrs]]; + [line appendAttributedString: + [[NSAttributedString alloc] + initWithString:[preedit + substringFromIndex:NSMaxRange(selRange)] + attributes:theme.preeditAttrs]]; } [text appendAttributedString:line]; @@ -1338,21 +1569,21 @@ - (void)showPreedit:(NSString *)preedit preeditRange = NSMakeRange(0, text.length); if (numCandidates) { [text appendAttributedString:[[NSAttributedString alloc] - initWithString:@"\n" - attributes:theme.preeditAttrs]]; + initWithString:@"\n" + attributes:theme.preeditAttrs]]; } candidateStartPos = text.length; } - NSMutableArray *candidateRanges = [[NSMutableArray alloc] init]; + NSMutableArray* candidateRanges = [[NSMutableArray alloc] init]; // candidates NSUInteger i; for (i = 0; i < candidates.count; ++i) { - NSMutableAttributedString *line = [[NSMutableAttributedString alloc] init]; + NSMutableAttributedString* line = [[NSMutableAttributedString alloc] init]; - NSDictionary *attrs; - NSDictionary *labelAttrs; - NSDictionary *commentAttrs; + NSDictionary* attrs; + NSDictionary* labelAttrs; + NSDictionary* commentAttrs; if (i == index) { attrs = theme.highlightedAttrs; labelAttrs = theme.labelHighlightedAttrs; @@ -1366,84 +1597,110 @@ - (void)showPreedit:(NSString *)preedit CGFloat labelWidth = 0.0; if (theme.prefixLabelFormat != nil) { - NSString *labelString; + NSString* labelString; if (labels.count > 1 && i < labels.count) { - NSString *labelFormat = [theme.prefixLabelFormat stringByReplacingOccurrencesOfString:@"%c" withString:@"%@"]; + NSString* labelFormat = [theme.prefixLabelFormat + stringByReplacingOccurrencesOfString:@"%c" + withString:@"%@"]; labelString = [NSString stringWithFormat:labelFormat, labels[i]]; } else if (labels.count == 1 && i < [labels[0] length]) { // custom: A. B. C... char labelCharacter = [labels[0] characterAtIndex:i]; - labelString = [NSString stringWithFormat:theme.prefixLabelFormat, labelCharacter]; + labelString = + [NSString stringWithFormat:theme.prefixLabelFormat, labelCharacter]; } else { // default: 1. 2. 3... - NSString *labelFormat = [theme.prefixLabelFormat stringByReplacingOccurrencesOfString:@"%c" withString:@"%lu"]; - labelString = [NSString stringWithFormat:labelFormat, i+1]; + NSString* labelFormat = [theme.prefixLabelFormat + stringByReplacingOccurrencesOfString:@"%c" + withString:@"%lu"]; + labelString = [NSString stringWithFormat:labelFormat, i + 1]; } - [line appendAttributedString: - [[NSAttributedString alloc] - initWithString:labelString - attributes:labelAttrs]]; + [line appendAttributedString:[[NSAttributedString alloc] + initWithString:labelString + attributes:labelAttrs]]; // get the label size for indent if (!theme.linear) { - NSMutableAttributedString *str = [line mutableCopy]; + NSMutableAttributedString* str = [line mutableCopy]; if (theme.vertical) { - [str addAttribute:NSVerticalGlyphFormAttributeName value:@(1) range:NSMakeRange(0, str.length)]; + [str addAttribute:NSVerticalGlyphFormAttributeName + value:@(1) + range:NSMakeRange(0, str.length)]; } - labelWidth = [str boundingRectWithSize:NSZeroSize options:NSStringDrawingUsesLineFragmentOrigin].size.width; + labelWidth = + [str boundingRectWithSize:NSZeroSize + options:NSStringDrawingUsesLineFragmentOrigin] + .size.width; } } NSUInteger candidateStart = line.length; - NSString *candidate = candidates[i]; - NSAttributedString *candidateAttributedString = [[NSAttributedString alloc] - initWithString:candidate - attributes:attrs]; - CGFloat candidateWidth = [candidateAttributedString boundingRectWithSize:NSZeroSize options:NSStringDrawingUsesLineFragmentOrigin].size.width; + NSString* candidate = candidates[i]; + NSAttributedString* candidateAttributedString = + [[NSAttributedString alloc] initWithString:candidate attributes:attrs]; + CGFloat candidateWidth = + [candidateAttributedString + boundingRectWithSize:NSZeroSize + options:NSStringDrawingUsesLineFragmentOrigin] + .size.width; if (candidateWidth <= maxTextWidth * 0.2) { // Unicode Word Joiner candidateAttributedString = insert(@"\u2060", candidateAttributedString); } - + [line appendAttributedString:candidateAttributedString]; - + // Use left-to-right marks to prevent right-to-left text from changing the // layout of non-candidate text. - [line addAttribute:NSWritingDirectionAttributeName value:@[@0] range:NSMakeRange(candidateStart, line.length-candidateStart)]; + [line + addAttribute:NSWritingDirectionAttributeName + value:@[ @0 ] + range:NSMakeRange(candidateStart, line.length - candidateStart)]; if (theme.suffixLabelFormat != nil) { - NSString *labelString; + NSString* labelString; if (labels.count > 1 && i < labels.count) { - NSString *labelFormat = [theme.suffixLabelFormat stringByReplacingOccurrencesOfString:@"%c" withString:@"%@"]; + NSString* labelFormat = [theme.suffixLabelFormat + stringByReplacingOccurrencesOfString:@"%c" + withString:@"%@"]; labelString = [NSString stringWithFormat:labelFormat, labels[i]]; } else if (labels.count == 1 && i < [labels[0] length]) { // custom: A. B. C... char labelCharacter = [labels[0] characterAtIndex:i]; - labelString = [NSString stringWithFormat:theme.suffixLabelFormat, labelCharacter]; + labelString = + [NSString stringWithFormat:theme.suffixLabelFormat, labelCharacter]; } else { // default: 1. 2. 3... - NSString *labelFormat = [theme.suffixLabelFormat stringByReplacingOccurrencesOfString:@"%c" withString:@"%lu"]; - labelString = [NSString stringWithFormat:labelFormat, i+1]; + NSString* labelFormat = [theme.suffixLabelFormat + stringByReplacingOccurrencesOfString:@"%c" + withString:@"%lu"]; + labelString = [NSString stringWithFormat:labelFormat, i + 1]; } - [line appendAttributedString: - [[NSAttributedString alloc] - initWithString:labelString - attributes:labelAttrs]]; + [line appendAttributedString:[[NSAttributedString alloc] + initWithString:labelString + attributes:labelAttrs]]; } if (i < comments.count && [comments[i] length] != 0) { - CGFloat candidateAndLabelWidth = [line boundingRectWithSize:NSZeroSize options:NSStringDrawingUsesLineFragmentOrigin].size.width; - NSString *comment = comments[i]; - NSAttributedString *commentAttributedString = [[NSAttributedString alloc] - initWithString:comment - attributes:commentAttrs]; - CGFloat commentWidth = [commentAttributedString boundingRectWithSize:NSZeroSize options:NSStringDrawingUsesLineFragmentOrigin].size.width; + CGFloat candidateAndLabelWidth = + [line boundingRectWithSize:NSZeroSize + options:NSStringDrawingUsesLineFragmentOrigin] + .size.width; + NSString* comment = comments[i]; + NSAttributedString* commentAttributedString = + [[NSAttributedString alloc] initWithString:comment + attributes:commentAttrs]; + CGFloat commentWidth = + [commentAttributedString + boundingRectWithSize:NSZeroSize + options:NSStringDrawingUsesLineFragmentOrigin] + .size.width; if (commentWidth <= maxTextWidth * 0.2) { // Unicode Word Joiner commentAttributedString = insert(@"\u2060", commentAttributedString); } - - NSString *commentSeparator; + + NSString* commentSeparator; if (candidateAndLabelWidth + commentWidth <= maxTextWidth * 0.3) { // Non-Breaking White Space commentSeparator = @"\u00A0"; @@ -1456,19 +1713,24 @@ - (void)showPreedit:(NSString *)preedit [line appendAttributedString:commentAttributedString]; } - NSAttributedString *separator = [[NSMutableAttributedString alloc] - initWithString:(theme.linear ? @" " : @"\n") - attributes:attrs]; - - NSMutableAttributedString *str = [separator mutableCopy]; + NSAttributedString* separator = [[NSMutableAttributedString alloc] + initWithString:(theme.linear ? @" " : @"\n") + attributes:attrs]; + + NSMutableAttributedString* str = [separator mutableCopy]; if (theme.vertical) { - [str addAttribute:NSVerticalGlyphFormAttributeName value:@(1) range:NSMakeRange(0, str.length)]; + [str addAttribute:NSVerticalGlyphFormAttributeName + value:@(1) + range:NSMakeRange(0, str.length)]; } - _view.seperatorWidth = [str boundingRectWithSize:NSZeroSize options:0].size.width; + _view.seperatorWidth = + [str boundingRectWithSize:NSZeroSize options:0].size.width; - NSMutableParagraphStyle *paragraphStyleCandidate = [theme.paragraphStyle mutableCopy]; + NSMutableParagraphStyle* paragraphStyleCandidate = + [theme.paragraphStyle mutableCopy]; if (i == 0) { - paragraphStyleCandidate.paragraphSpacingBefore = theme.preeditLinespace / 2 + theme.hilitedCornerRadius / 2; + paragraphStyleCandidate.paragraphSpacingBefore = + theme.preeditLinespace / 2 + theme.hilitedCornerRadius / 2; } else { [text appendAttributedString:separator]; } @@ -1481,7 +1743,7 @@ - (void)showPreedit:(NSString *)preedit range:NSMakeRange(0, line.length)]; NSRange candidateRange = NSMakeRange(text.length, line.length); - [candidateRanges addObject: [NSValue valueWithRange:candidateRange]]; + [candidateRanges addObject:[NSValue valueWithRange:candidateRange]]; [text appendAttributedString:line]; } @@ -1492,12 +1754,16 @@ - (void)showPreedit:(NSString *)preedit } else { _view.textView.layoutOrientation = NSTextLayoutOrientationHorizontal; } - [_view drawViewWith:candidateRanges hilightedIndex:index preeditRange:preeditRange highlightedPreeditRange:highlightedPreeditRange]; + [_view drawViewWith:candidateRanges + hilightedIndex:index + preeditRange:preeditRange + highlightedPreeditRange:highlightedPreeditRange]; [self show]; } -- (void)updateStatusLong:(NSString *)messageLong statusShort:(NSString *)messageShort { - SquirrelTheme *theme = _view.currentTheme; +- (void)updateStatusLong:(NSString*)messageLong + statusShort:(NSString*)messageShort { + SquirrelTheme* theme = _view.currentTheme; if ([theme.statusMessageType isEqualToString:@"mix"]) { if (messageShort) { _statusMessage = messageShort; @@ -1510,14 +1776,18 @@ - (void)updateStatusLong:(NSString *)messageLong statusShort:(NSString *)message if (messageShort) { _statusMessage = messageShort; } else if (messageLong) { - _statusMessage = [messageLong substringWithRange:[messageLong rangeOfComposedCharacterSequenceAtIndex:0]]; + _statusMessage = [messageLong + substringWithRange:[messageLong + rangeOfComposedCharacterSequenceAtIndex:0]]; } } } -- (void)showStatus:(NSString *)message { - SquirrelTheme *theme = _view.currentTheme; - NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:message attributes:theme.attrs]; +- (void)showStatus:(NSString*)message { + SquirrelTheme* theme = _view.currentTheme; + NSMutableAttributedString* text = + [[NSMutableAttributedString alloc] initWithString:message + attributes:theme.attrs]; [text addAttribute:NSParagraphStyleAttributeName value:theme.paragraphStyle range:NSMakeRange(0, text.length)]; @@ -1529,8 +1799,12 @@ - (void)showStatus:(NSString *)message { _view.textView.layoutOrientation = NSTextLayoutOrientationHorizontal; } NSRange emptyRange = NSMakeRange(NSNotFound, 0); - NSArray *candidateRanges = @[[NSValue valueWithRange: NSMakeRange(0, text.length)]]; - [_view drawViewWith:candidateRanges hilightedIndex:-1 preeditRange:emptyRange highlightedPreeditRange:emptyRange]; + NSArray* candidateRanges = + @[ [NSValue valueWithRange:NSMakeRange(0, text.length)] ]; + [_view drawViewWith:candidateRanges + hilightedIndex:-1 + preeditRange:emptyRange + highlightedPreeditRange:emptyRange]; [self show]; if (_statusTimer) { @@ -1543,35 +1817,41 @@ - (void)showStatus:(NSString *)message { repeats:NO]; } -- (void)hideStatus:(NSTimer *)timer { +- (void)hideStatus:(NSTimer*)timer { [self hide]; } -static inline NSColor *blendColors(NSColor *foregroundColor, - NSColor *backgroundColor) { +static inline NSColor* blendColors(NSColor* foregroundColor, + NSColor* backgroundColor) { if (!backgroundColor) { // return foregroundColor; backgroundColor = [NSColor lightGrayColor]; } - return [[foregroundColor blendedColorWithFraction:kBlendedBackgroundColorFraction ofColor:backgroundColor] + return + [[foregroundColor blendedColorWithFraction:kBlendedBackgroundColorFraction + ofColor:backgroundColor] colorWithAlphaComponent:foregroundColor.alphaComponent]; } -static NSFontDescriptor *getFontDescriptor(NSString *fullname) { +static NSFontDescriptor* getFontDescriptor(NSString* fullname) { if (fullname == nil) { return nil; } - NSArray *fontNames = [fullname componentsSeparatedByString:@","]; - NSMutableArray *validFontDescriptors = [NSMutableArray arrayWithCapacity:fontNames.count]; - for (__strong NSString *fontName in fontNames) { - fontName = [fontName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + NSArray* fontNames = [fullname componentsSeparatedByString:@","]; + NSMutableArray* validFontDescriptors = + [NSMutableArray arrayWithCapacity:fontNames.count]; + for (__strong NSString* fontName in fontNames) { + fontName = + [fontName stringByTrimmingCharactersInSet:[NSCharacterSet + whitespaceCharacterSet]]; if ([NSFont fontWithName:fontName size:0.0] != nil) { - // If the font name is not valid, NSFontDescriptor will still create something for us. - // However, when we draw the actual text, Squirrel will crash if there is any font descriptor - // with invalid font name. - [validFontDescriptors addObject:[NSFontDescriptor fontDescriptorWithName:fontName - size:0.0]]; + // If the font name is not valid, NSFontDescriptor will still create + // something for us. However, when we draw the actual text, Squirrel will + // crash if there is any font descriptor with invalid font name. + [validFontDescriptors + addObject:[NSFontDescriptor fontDescriptorWithName:fontName + size:0.0]]; } } if (validFontDescriptors.count == 0) { @@ -1580,48 +1860,59 @@ - (void)hideStatus:(NSTimer *)timer { return validFontDescriptors[0]; } - NSFontDescriptor *initialFontDescriptor = validFontDescriptors[0]; - NSArray *fallbackDescriptors = [validFontDescriptors + NSFontDescriptor* initialFontDescriptor = validFontDescriptors[0]; + NSArray* fallbackDescriptors = [validFontDescriptors subarrayWithRange:NSMakeRange(1, validFontDescriptors.count - 1)]; - NSDictionary *attributes = @{NSFontCascadeListAttribute : fallbackDescriptors}; + NSDictionary* attributes = + @{NSFontCascadeListAttribute : fallbackDescriptors}; return [initialFontDescriptor fontDescriptorByAddingAttributes:attributes]; } -static void updateCandidateListLayout(BOOL *isLinearCandidateList, SquirrelConfig *config, NSString *prefix) { - NSString* candidateListLayout = [config getString:[prefix stringByAppendingString:@"/candidate_list_layout"]]; +static void updateCandidateListLayout(BOOL* isLinearCandidateList, + SquirrelConfig* config, + NSString* prefix) { + NSString* candidateListLayout = [config + getString:[prefix stringByAppendingString:@"/candidate_list_layout"]]; if ([candidateListLayout isEqualToString:@"stacked"]) { *isLinearCandidateList = false; } else if ([candidateListLayout isEqualToString:@"linear"]) { *isLinearCandidateList = true; } else { // Deprecated. Not to be confused with text_orientation: horizontal - NSNumber *horizontal = [config getOptionalBool:[prefix stringByAppendingString:@"/horizontal"]]; + NSNumber* horizontal = [config + getOptionalBool:[prefix stringByAppendingString:@"/horizontal"]]; if (horizontal) { *isLinearCandidateList = horizontal.boolValue; } } } -static void updateTextOrientation(BOOL *isVerticalText, SquirrelConfig *config, NSString *prefix) { - NSString* textOrientation = [config getString:[prefix stringByAppendingString:@"/text_orientation"]]; +static void updateTextOrientation(BOOL* isVerticalText, + SquirrelConfig* config, + NSString* prefix) { + NSString* textOrientation = + [config getString:[prefix stringByAppendingString:@"/text_orientation"]]; if ([textOrientation isEqualToString:@"horizontal"]) { *isVerticalText = false; } else if ([textOrientation isEqualToString:@"vertical"]) { *isVerticalText = true; } else { - NSNumber *vertical = [config getOptionalBool:[prefix stringByAppendingString:@"/vertical"]]; + NSNumber* vertical = + [config getOptionalBool:[prefix stringByAppendingString:@"/vertical"]]; if (vertical) { *isVerticalText = vertical.boolValue; } } } --(void)loadConfig:(SquirrelConfig *)config forDarkMode:(BOOL)isDark { - SquirrelTheme *theme = [_view selectTheme:isDark]; +- (void)loadConfig:(SquirrelConfig*)config forDarkMode:(BOOL)isDark { + SquirrelTheme* theme = [_view selectTheme:isDark]; [[self class] updateTheme:theme withConfig:config forDarkMode:isDark]; } -+(void)updateTheme:(SquirrelTheme *)theme withConfig:(SquirrelConfig *)config forDarkMode:(BOOL)isDark { ++ (void)updateTheme:(SquirrelTheme*)theme + withConfig:(SquirrelConfig*)config + forDarkMode:(BOOL)isDark { BOOL linear = NO; BOOL vertical = NO; updateCandidateListLayout(&linear, config, @"style"); @@ -1630,47 +1921,51 @@ +(void)updateTheme:(SquirrelTheme *)theme withConfig:(SquirrelConfig *)config fo BOOL inlineCandidate = [config getBool:@"style/inline_candidate"]; BOOL translucency = [config getBool:@"style/translucency"]; BOOL mutualExclusive = [config getBool:@"style/mutual_exclusive"]; - NSNumber *memorizeSizeConfig = [config getOptionalBool:@"style/memorize_size"]; + NSNumber* memorizeSizeConfig = + [config getOptionalBool:@"style/memorize_size"]; if (memorizeSizeConfig) { theme.memorizeSize = memorizeSizeConfig.boolValue; } - - NSString *statusMessageType = [config getString:@"style/status_message_type"]; - NSString *candidateFormat = [config getString:@"style/candidate_format"]; - NSString *fontName = [config getString:@"style/font_face"]; + + NSString* statusMessageType = [config getString:@"style/status_message_type"]; + NSString* candidateFormat = [config getString:@"style/candidate_format"]; + NSString* fontName = [config getString:@"style/font_face"]; CGFloat fontSize = [config getDouble:@"style/font_point"]; - NSString *labelFontName = [config getString:@"style/label_font_face"]; + NSString* labelFontName = [config getString:@"style/label_font_face"]; CGFloat labelFontSize = [config getDouble:@"style/label_font_point"]; - NSString *commentFontName = [config getString:@"style/comment_font_face"]; + NSString* commentFontName = [config getString:@"style/comment_font_face"]; CGFloat commentFontSize = [config getDouble:@"style/comment_font_point"]; - NSNumber *alphaValue = [config getOptionalDouble:@"style/alpha"]; - CGFloat alpha = alphaValue ? fmin(fmax(alphaValue.doubleValue, 0.0), 1.0) : 1.0; + NSNumber* alphaValue = [config getOptionalDouble:@"style/alpha"]; + CGFloat alpha = + alphaValue ? fmin(fmax(alphaValue.doubleValue, 0.0), 1.0) : 1.0; CGFloat cornerRadius = [config getDouble:@"style/corner_radius"]; - CGFloat hilitedCornerRadius = [config getDouble:@"style/hilited_corner_radius"]; - CGFloat surroundingExtraExpansion = [config getDouble:@"style/surrounding_extra_expansion"]; + CGFloat hilitedCornerRadius = + [config getDouble:@"style/hilited_corner_radius"]; + CGFloat surroundingExtraExpansion = + [config getDouble:@"style/surrounding_extra_expansion"]; CGFloat borderHeight = [config getDouble:@"style/border_height"]; CGFloat borderWidth = [config getDouble:@"style/border_width"]; CGFloat lineSpacing = [config getDouble:@"style/line_spacing"]; CGFloat spacing = [config getDouble:@"style/spacing"]; CGFloat baseOffset = [config getDouble:@"style/base_offset"]; - CGFloat shadowSize = fmax(0,[config getDouble:@"style/shadow_size"]); - - NSColor *backgroundColor; - NSColor *borderColor; - NSColor *preeditBackgroundColor; - NSColor *candidateLabelColor; - NSColor *highlightedCandidateLabelColor; - NSColor *textColor; - NSColor *highlightedTextColor; - NSColor *highlightedBackColor; - NSColor *candidateTextColor; - NSColor *highlightedCandidateTextColor; - NSColor *highlightedCandidateBackColor; - NSColor *candidateBackColor; - NSColor *commentTextColor; - NSColor *highlightedCommentTextColor; - - NSString *colorScheme; + CGFloat shadowSize = fmax(0, [config getDouble:@"style/shadow_size"]); + + NSColor* backgroundColor; + NSColor* borderColor; + NSColor* preeditBackgroundColor; + NSColor* candidateLabelColor; + NSColor* highlightedCandidateLabelColor; + NSColor* textColor; + NSColor* highlightedTextColor; + NSColor* highlightedBackColor; + NSColor* candidateTextColor; + NSColor* highlightedCandidateTextColor; + NSColor* highlightedCandidateBackColor; + NSColor* candidateBackColor; + NSColor* commentTextColor; + NSColor* highlightedCommentTextColor; + + NSString* colorScheme; if (isDark) { colorScheme = [config getString:@"style/color_scheme_dark"]; } @@ -1679,168 +1974,185 @@ +(void)updateTheme:(SquirrelTheme *)theme withConfig:(SquirrelConfig *)config fo } BOOL isNative = !colorScheme || [colorScheme isEqualToString:@"native"]; if (!isNative) { - NSString *prefix = [@"preset_color_schemes/" stringByAppendingString:colorScheme]; - config.colorSpace = [config getString:[prefix stringByAppendingString:@"/color_space"]]; - backgroundColor = [config getColor:[prefix stringByAppendingString:@"/back_color"]]; - borderColor = [config getColor:[prefix stringByAppendingString:@"/border_color"]]; - preeditBackgroundColor = [config getColor:[prefix stringByAppendingString:@"/preedit_back_color"]]; - textColor = [config getColor:[prefix stringByAppendingString:@"/text_color"]]; - highlightedTextColor = - [config getColor:[prefix stringByAppendingString:@"/hilited_text_color"]]; + NSString* prefix = + [@"preset_color_schemes/" stringByAppendingString:colorScheme]; + config.colorSpace = + [config getString:[prefix stringByAppendingString:@"/color_space"]]; + backgroundColor = + [config getColor:[prefix stringByAppendingString:@"/back_color"]]; + borderColor = + [config getColor:[prefix stringByAppendingString:@"/border_color"]]; + preeditBackgroundColor = [config + getColor:[prefix stringByAppendingString:@"/preedit_back_color"]]; + textColor = + [config getColor:[prefix stringByAppendingString:@"/text_color"]]; + highlightedTextColor = [config + getColor:[prefix stringByAppendingString:@"/hilited_text_color"]]; if (highlightedTextColor == nil) { highlightedTextColor = textColor; } - highlightedBackColor = - [config getColor:[prefix stringByAppendingString:@"/hilited_back_color"]]; - candidateTextColor = - [config getColor:[prefix stringByAppendingString:@"/candidate_text_color"]]; + highlightedBackColor = [config + getColor:[prefix stringByAppendingString:@"/hilited_back_color"]]; + candidateTextColor = [config + getColor:[prefix stringByAppendingString:@"/candidate_text_color"]]; if (candidateTextColor == nil) { // in non-inline mode, 'text_color' is for rendering preedit text. - // if not otherwise specified, candidate text is also rendered in this color. + // if not otherwise specified, candidate text is also rendered in this + // color. candidateTextColor = textColor; } candidateLabelColor = [config getColor:[prefix stringByAppendingString:@"/label_color"]]; - highlightedCandidateLabelColor = - [config getColor:[prefix stringByAppendingString:@"/label_hilited_color"]]; + highlightedCandidateLabelColor = [config + getColor:[prefix stringByAppendingString:@"/label_hilited_color"]]; if (!highlightedCandidateLabelColor) { - // for backward compatibility, 'label_hilited_color' and 'hilited_candidate_label_color' - // are both valid + // for backward compatibility, 'label_hilited_color' and + // 'hilited_candidate_label_color' are both valid highlightedCandidateLabelColor = - [config getColor:[prefix stringByAppendingString:@"/hilited_candidate_label_color"]]; + [config getColor:[prefix stringByAppendingString: + @"/hilited_candidate_label_color"]]; } - highlightedCandidateTextColor = - [config getColor:[prefix stringByAppendingString:@"/hilited_candidate_text_color"]]; + highlightedCandidateTextColor = [config + getColor:[prefix + stringByAppendingString:@"/hilited_candidate_text_color"]]; if (highlightedCandidateTextColor == nil) { highlightedCandidateTextColor = highlightedTextColor; } - highlightedCandidateBackColor = - [config getColor:[prefix stringByAppendingString:@"/hilited_candidate_back_color"]]; + highlightedCandidateBackColor = [config + getColor:[prefix + stringByAppendingString:@"/hilited_candidate_back_color"]]; if (highlightedCandidateBackColor == nil) { highlightedCandidateBackColor = highlightedBackColor; } - candidateBackColor = - [config getColor:[prefix stringByAppendingString:@"/candidate_back_color"]]; - commentTextColor = - [config getColor:[prefix stringByAppendingString:@"/comment_text_color"]]; - highlightedCommentTextColor = - [config getColor:[prefix stringByAppendingString:@"/hilited_comment_text_color"]]; + candidateBackColor = [config + getColor:[prefix stringByAppendingString:@"/candidate_back_color"]]; + commentTextColor = [config + getColor:[prefix stringByAppendingString:@"/comment_text_color"]]; + highlightedCommentTextColor = [config + getColor:[prefix + stringByAppendingString:@"/hilited_comment_text_color"]]; // the following per-color-scheme configurations, if exist, will - // override configurations with the same name under the global 'style' section + // override configurations with the same name under the global 'style' + // section updateCandidateListLayout(&linear, config, prefix); updateTextOrientation(&vertical, config, prefix); - NSNumber *inlinePreeditOverridden = - [config getOptionalBool:[prefix stringByAppendingString:@"/inline_preedit"]]; + NSNumber* inlinePreeditOverridden = [config + getOptionalBool:[prefix stringByAppendingString:@"/inline_preedit"]]; if (inlinePreeditOverridden) { inlinePreedit = inlinePreeditOverridden.boolValue; } - NSNumber *inlineCandidateOverridden = - [config getOptionalBool:[prefix stringByAppendingString:@"/inline_candidate"]]; + NSNumber* inlineCandidateOverridden = [config + getOptionalBool:[prefix stringByAppendingString:@"/inline_candidate"]]; if (inlineCandidateOverridden) { inlineCandidate = inlineCandidateOverridden.boolValue; } - NSNumber *translucencyOverridden = - [config getOptionalBool:[prefix stringByAppendingString:@"/translucency"]]; + NSNumber* translucencyOverridden = [config + getOptionalBool:[prefix stringByAppendingString:@"/translucency"]]; if (translucencyOverridden) { translucency = translucencyOverridden.boolValue; } - NSNumber *mutualExclusiveOverridden = - [config getOptionalBool:[prefix stringByAppendingString:@"/mutual_exclusive"]]; + NSNumber* mutualExclusiveOverridden = [config + getOptionalBool:[prefix stringByAppendingString:@"/mutual_exclusive"]]; if (mutualExclusiveOverridden) { mutualExclusive = mutualExclusiveOverridden.boolValue; } - NSString *candidateFormatOverridden = - [config getString:[prefix stringByAppendingString:@"/candidate_format"]]; + NSString* candidateFormatOverridden = [config + getString:[prefix stringByAppendingString:@"/candidate_format"]]; if (candidateFormatOverridden) { candidateFormat = candidateFormatOverridden; } - NSString *fontNameOverridden = + NSString* fontNameOverridden = [config getString:[prefix stringByAppendingString:@"/font_face"]]; if (fontNameOverridden) { fontName = fontNameOverridden; } - NSNumber *fontSizeOverridden = - [config getOptionalDouble:[prefix stringByAppendingString:@"/font_point"]]; + NSNumber* fontSizeOverridden = [config + getOptionalDouble:[prefix stringByAppendingString:@"/font_point"]]; if (fontSizeOverridden) { fontSize = fontSizeOverridden.integerValue; } - NSString *labelFontNameOverridden = + NSString* labelFontNameOverridden = [config getString:[prefix stringByAppendingString:@"/label_font_face"]]; if (labelFontNameOverridden) { labelFontName = labelFontNameOverridden; } - NSNumber *labelFontSizeOverridden = - [config getOptionalDouble:[prefix stringByAppendingString:@"/label_font_point"]]; + NSNumber* labelFontSizeOverridden = [config + getOptionalDouble:[prefix + stringByAppendingString:@"/label_font_point"]]; if (labelFontSizeOverridden) { labelFontSize = labelFontSizeOverridden.integerValue; } - NSString *commentFontNameOverridden = - [config getString:[prefix stringByAppendingString:@"/comment_font_face"]]; + NSString* commentFontNameOverridden = [config + getString:[prefix stringByAppendingString:@"/comment_font_face"]]; if (commentFontNameOverridden) { commentFontName = commentFontNameOverridden; } - NSNumber *commentFontSizeOverridden = - [config getOptionalDouble:[prefix stringByAppendingString:@"/comment_font_point"]]; + NSNumber* commentFontSizeOverridden = [config + getOptionalDouble:[prefix + stringByAppendingString:@"/comment_font_point"]]; if (commentFontSizeOverridden) { commentFontSize = commentFontSizeOverridden.integerValue; } - NSNumber *alphaOverridden = + NSNumber* alphaOverridden = [config getOptionalDouble:[prefix stringByAppendingString:@"/alpha"]]; if (alphaOverridden) { alpha = fmin(fmax(alphaOverridden.doubleValue, 0.0), 1.0); } - NSNumber *cornerRadiusOverridden = - [config getOptionalDouble:[prefix stringByAppendingString:@"/corner_radius"]]; + NSNumber* cornerRadiusOverridden = [config + getOptionalDouble:[prefix stringByAppendingString:@"/corner_radius"]]; if (cornerRadiusOverridden) { cornerRadius = cornerRadiusOverridden.doubleValue; } - NSNumber *hilitedCornerRadiusOverridden = - [config getOptionalDouble:[prefix stringByAppendingString:@"/hilited_corner_radius"]]; + NSNumber* hilitedCornerRadiusOverridden = + [config getOptionalDouble: + [prefix stringByAppendingString:@"/hilited_corner_radius"]]; if (hilitedCornerRadiusOverridden) { hilitedCornerRadius = hilitedCornerRadiusOverridden.doubleValue; } - NSNumber *surroundingExtraExpansionOverridden = - [config getOptionalDouble:[prefix stringByAppendingString:@"/surrounding_extra_expansion"]]; + NSNumber* surroundingExtraExpansionOverridden = [config + getOptionalDouble: + [prefix stringByAppendingString:@"/surrounding_extra_expansion"]]; if (surroundingExtraExpansionOverridden) { - surroundingExtraExpansion = surroundingExtraExpansionOverridden.doubleValue; + surroundingExtraExpansion = + surroundingExtraExpansionOverridden.doubleValue; } - NSNumber *borderHeightOverridden = - [config getOptionalDouble:[prefix stringByAppendingString:@"/border_height"]]; + NSNumber* borderHeightOverridden = [config + getOptionalDouble:[prefix stringByAppendingString:@"/border_height"]]; if (borderHeightOverridden) { borderHeight = borderHeightOverridden.doubleValue; } - NSNumber *borderWidthOverridden = - [config getOptionalDouble:[prefix stringByAppendingString:@"/border_width"]]; + NSNumber* borderWidthOverridden = [config + getOptionalDouble:[prefix stringByAppendingString:@"/border_width"]]; if (borderWidthOverridden) { borderWidth = borderWidthOverridden.doubleValue; } - NSNumber *lineSpacingOverridden = - [config getOptionalDouble:[prefix stringByAppendingString:@"/line_spacing"]]; + NSNumber* lineSpacingOverridden = [config + getOptionalDouble:[prefix stringByAppendingString:@"/line_spacing"]]; if (lineSpacingOverridden) { lineSpacing = lineSpacingOverridden.doubleValue; } - NSNumber *spacingOverridden = + NSNumber* spacingOverridden = [config getOptionalDouble:[prefix stringByAppendingString:@"/spacing"]]; if (spacingOverridden) { spacing = spacingOverridden.doubleValue; } - NSNumber *baseOffsetOverridden = - [config getOptionalDouble:[prefix stringByAppendingString:@"/base_offset"]]; + NSNumber* baseOffsetOverridden = [config + getOptionalDouble:[prefix stringByAppendingString:@"/base_offset"]]; if (baseOffsetOverridden) { baseOffset = baseOffsetOverridden.doubleValue; } - NSNumber *shadowSizeOverridden = - [config getOptionalDouble:[prefix stringByAppendingString:@"/shadow_size"]]; + NSNumber* shadowSizeOverridden = [config + getOptionalDouble:[prefix stringByAppendingString:@"/shadow_size"]]; if (shadowSizeOverridden) { shadowSize = shadowSizeOverridden.doubleValue; } } - if (fontSize == 0) { // default size + if (fontSize == 0) { // default size fontSize = kDefaultFontSize; } if (labelFontSize == 0) { @@ -1849,8 +2161,8 @@ +(void)updateTheme:(SquirrelTheme *)theme withConfig:(SquirrelConfig *)config fo if (commentFontSize == 0) { commentFontSize = fontSize; } - NSFontDescriptor *fontDescriptor = nil; - NSFont *font = nil; + NSFontDescriptor* fontDescriptor = nil; + NSFont* font = nil; if (fontName != nil) { fontDescriptor = getFontDescriptor(fontName); if (fontDescriptor != nil) { @@ -1861,15 +2173,16 @@ +(void)updateTheme:(SquirrelTheme *)theme withConfig:(SquirrelConfig *)config fo // use default font font = [NSFont userFontOfSize:fontSize]; } - NSFontDescriptor *labelFontDescriptor = nil; - NSFont *labelFont = nil; + NSFontDescriptor* labelFontDescriptor = nil; + NSFont* labelFont = nil; if (labelFontName != nil) { labelFontDescriptor = getFontDescriptor(labelFontName); if (labelFontDescriptor == nil) { labelFontDescriptor = fontDescriptor; } if (labelFontDescriptor != nil) { - labelFont = [NSFont fontWithDescriptor:labelFontDescriptor size:labelFontSize]; + labelFont = [NSFont fontWithDescriptor:labelFontDescriptor + size:labelFontSize]; } } if (labelFont == nil) { @@ -1879,42 +2192,48 @@ +(void)updateTheme:(SquirrelTheme *)theme withConfig:(SquirrelConfig *)config fo labelFont = [NSFont fontWithName:font.fontName size:labelFontSize]; } } - NSFontDescriptor *commentFontDescriptor = nil; - NSFont *commentFont = nil; + NSFontDescriptor* commentFontDescriptor = nil; + NSFont* commentFont = nil; if (commentFontName != nil) { commentFontDescriptor = getFontDescriptor(commentFontName); if (commentFontDescriptor == nil) { commentFontDescriptor = fontDescriptor; } if (commentFontDescriptor != nil) { - commentFont = [NSFont fontWithDescriptor:commentFontDescriptor size:commentFontSize]; + commentFont = [NSFont fontWithDescriptor:commentFontDescriptor + size:commentFontSize]; } } if (commentFont == nil) { if (fontDescriptor != nil) { - commentFont = [NSFont fontWithDescriptor:fontDescriptor size:commentFontSize]; + commentFont = [NSFont fontWithDescriptor:fontDescriptor + size:commentFontSize]; } else { commentFont = [NSFont fontWithName:font.fontName size:commentFontSize]; } } - NSMutableParagraphStyle *paragraphStyle = + NSMutableParagraphStyle* paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; paragraphStyle.paragraphSpacing = lineSpacing / 2; paragraphStyle.paragraphSpacingBefore = lineSpacing / 2; - NSMutableParagraphStyle *preeditParagraphStyle = + NSMutableParagraphStyle* preeditParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; - preeditParagraphStyle.paragraphSpacing = spacing / 2 + hilitedCornerRadius / 2; - - NSMutableDictionary *attrs = [theme.attrs mutableCopy]; - NSMutableDictionary *highlightedAttrs = [theme.highlightedAttrs mutableCopy]; - NSMutableDictionary *labelAttrs = [theme.labelAttrs mutableCopy]; - NSMutableDictionary *labelHighlightedAttrs = [theme.labelHighlightedAttrs mutableCopy]; - NSMutableDictionary *commentAttrs = [theme.commentAttrs mutableCopy]; - NSMutableDictionary *commentHighlightedAttrs = [theme.commentHighlightedAttrs mutableCopy]; - NSMutableDictionary *preeditAttrs = [theme.preeditAttrs mutableCopy]; - NSMutableDictionary *preeditHighlightedAttrs = [theme.preeditHighlightedAttrs mutableCopy]; + preeditParagraphStyle.paragraphSpacing = + spacing / 2 + hilitedCornerRadius / 2; + + NSMutableDictionary* attrs = [theme.attrs mutableCopy]; + NSMutableDictionary* highlightedAttrs = [theme.highlightedAttrs mutableCopy]; + NSMutableDictionary* labelAttrs = [theme.labelAttrs mutableCopy]; + NSMutableDictionary* labelHighlightedAttrs = + [theme.labelHighlightedAttrs mutableCopy]; + NSMutableDictionary* commentAttrs = [theme.commentAttrs mutableCopy]; + NSMutableDictionary* commentHighlightedAttrs = + [theme.commentHighlightedAttrs mutableCopy]; + NSMutableDictionary* preeditAttrs = [theme.preeditAttrs mutableCopy]; + NSMutableDictionary* preeditHighlightedAttrs = + [theme.preeditHighlightedAttrs mutableCopy]; attrs[NSFontAttributeName] = font; highlightedAttrs[NSFontAttributeName] = font; @@ -1933,75 +2252,96 @@ +(void)updateTheme:(SquirrelTheme *)theme withConfig:(SquirrelConfig *)config fo preeditAttrs[NSBaselineOffsetAttributeName] = @(baseOffset); preeditHighlightedAttrs[NSBaselineOffsetAttributeName] = @(baseOffset); - NSColor *secondaryTextColor = [[self class] secondaryTextColor]; - - backgroundColor = backgroundColor ? backgroundColor : [NSColor windowBackgroundColor]; - candidateTextColor = candidateTextColor ? candidateTextColor : [NSColor controlTextColor]; - candidateLabelColor = candidateLabelColor ? candidateLabelColor : - isNative ? secondaryTextColor : blendColors(candidateTextColor, backgroundColor); - highlightedCandidateTextColor = highlightedCandidateTextColor ? highlightedCandidateTextColor : [NSColor selectedControlTextColor]; - highlightedCandidateBackColor = highlightedCandidateBackColor ? highlightedCandidateBackColor : [NSColor selectedTextBackgroundColor]; - highlightedCandidateLabelColor = highlightedCandidateLabelColor ? highlightedCandidateLabelColor : - isNative ? secondaryTextColor : blendColors(highlightedCandidateTextColor, highlightedCandidateBackColor); + NSColor* secondaryTextColor = [[self class] secondaryTextColor]; + + backgroundColor = + backgroundColor ? backgroundColor : [NSColor windowBackgroundColor]; + candidateTextColor = + candidateTextColor ? candidateTextColor : [NSColor controlTextColor]; + candidateLabelColor = candidateLabelColor ? candidateLabelColor + : isNative + ? secondaryTextColor + : blendColors(candidateTextColor, backgroundColor); + highlightedCandidateTextColor = highlightedCandidateTextColor + ? highlightedCandidateTextColor + : [NSColor selectedControlTextColor]; + highlightedCandidateBackColor = highlightedCandidateBackColor + ? highlightedCandidateBackColor + : [NSColor selectedTextBackgroundColor]; + highlightedCandidateLabelColor = + highlightedCandidateLabelColor ? highlightedCandidateLabelColor + : isNative ? secondaryTextColor + : blendColors(highlightedCandidateTextColor, + highlightedCandidateBackColor); commentTextColor = commentTextColor ? commentTextColor : secondaryTextColor; - highlightedCommentTextColor = highlightedCommentTextColor ? highlightedCommentTextColor : commentTextColor; + highlightedCommentTextColor = highlightedCommentTextColor + ? highlightedCommentTextColor + : commentTextColor; textColor = textColor ? textColor : secondaryTextColor; - highlightedTextColor = highlightedTextColor ? highlightedTextColor : [NSColor controlTextColor]; + highlightedTextColor = + highlightedTextColor ? highlightedTextColor : [NSColor controlTextColor]; attrs[NSForegroundColorAttributeName] = candidateTextColor; - highlightedAttrs[NSForegroundColorAttributeName] = highlightedCandidateTextColor; + highlightedAttrs[NSForegroundColorAttributeName] = + highlightedCandidateTextColor; labelAttrs[NSForegroundColorAttributeName] = candidateLabelColor; - labelHighlightedAttrs[NSForegroundColorAttributeName] = highlightedCandidateLabelColor; + labelHighlightedAttrs[NSForegroundColorAttributeName] = + highlightedCandidateLabelColor; commentAttrs[NSForegroundColorAttributeName] = commentTextColor; - commentHighlightedAttrs[NSForegroundColorAttributeName] = highlightedCommentTextColor; + commentHighlightedAttrs[NSForegroundColorAttributeName] = + highlightedCommentTextColor; preeditAttrs[NSForegroundColorAttributeName] = textColor; - preeditHighlightedAttrs[NSForegroundColorAttributeName] = highlightedTextColor; + preeditHighlightedAttrs[NSForegroundColorAttributeName] = + highlightedTextColor; [theme setStatusMessageType:statusMessageType]; - - [theme setAttrs:attrs - highlightedAttrs:highlightedAttrs - labelAttrs:labelAttrs - labelHighlightedAttrs:labelHighlightedAttrs - commentAttrs:commentAttrs - commentHighlightedAttrs:commentHighlightedAttrs - preeditAttrs:preeditAttrs - preeditHighlightedAttrs:preeditHighlightedAttrs]; + + [theme setAttrs:attrs + highlightedAttrs:highlightedAttrs + labelAttrs:labelAttrs + labelHighlightedAttrs:labelHighlightedAttrs + commentAttrs:commentAttrs + commentHighlightedAttrs:commentHighlightedAttrs + preeditAttrs:preeditAttrs + preeditHighlightedAttrs:preeditHighlightedAttrs]; [theme setParagraphStyle:paragraphStyle - preeditParagraphStyle:preeditParagraphStyle]; + preeditParagraphStyle:preeditParagraphStyle]; [theme setBackgroundColor:backgroundColor - highlightedBackColor:highlightedCandidateBackColor - candidateBackColor:candidateBackColor - highlightedPreeditColor:highlightedBackColor - preeditBackgroundColor:preeditBackgroundColor - borderColor:borderColor]; + highlightedBackColor:highlightedCandidateBackColor + candidateBackColor:candidateBackColor + highlightedPreeditColor:highlightedBackColor + preeditBackgroundColor:preeditBackgroundColor + borderColor:borderColor]; NSSize edgeInset; if (vertical) { - edgeInset = NSMakeSize(borderHeight + cornerRadius, borderWidth + cornerRadius); + edgeInset = + NSMakeSize(borderHeight + cornerRadius, borderWidth + cornerRadius); } else { - edgeInset = NSMakeSize(borderWidth + cornerRadius, borderHeight + cornerRadius); + edgeInset = + NSMakeSize(borderWidth + cornerRadius, borderHeight + cornerRadius); } [theme setCornerRadius:cornerRadius - hilitedCornerRadius:hilitedCornerRadius - srdExtraExpansion:surroundingExtraExpansion - shadowSize:shadowSize - edgeInset:edgeInset - borderWidth:MIN(borderHeight, borderWidth) - linespace:lineSpacing - preeditLinespace:spacing - alpha:alpha - translucency:translucency - mutualExclusive:mutualExclusive - linear:linear - vertical:vertical - inlinePreedit:inlinePreedit - inlineCandidate:inlineCandidate]; + hilitedCornerRadius:hilitedCornerRadius + srdExtraExpansion:surroundingExtraExpansion + shadowSize:shadowSize + edgeInset:edgeInset + borderWidth:MIN(borderHeight, borderWidth) + linespace:lineSpacing + preeditLinespace:spacing + alpha:alpha + translucency:translucency + mutualExclusive:mutualExclusive + linear:linear + vertical:vertical + inlinePreedit:inlinePreedit + inlineCandidate:inlineCandidate]; theme.native = isNative; - theme.candidateFormat = (candidateFormat ? candidateFormat : kDefaultCandidateFormat); + theme.candidateFormat = + (candidateFormat ? candidateFormat : kDefaultCandidateFormat); } @end diff --git a/input_source.m b/input_source.m index 9118fe62f..6b00be271 100644 --- a/input_source.m +++ b/input_source.m @@ -1,18 +1,17 @@ #import -static const unsigned char kInstallLocation[] = - "/Library/Input Methods/Squirrel.app"; -static NSString *const kHansInputModeID = - @"im.rime.inputmethod.Squirrel.Hans"; -static NSString *const kHantInputModeID = - @"im.rime.inputmethod.Squirrel.Hant"; +static const char kInstallLocation[] = "/Library/Input Methods/Squirrel.app"; +static const CFStringRef kHansInputModeID = + CFSTR("im.rime.inputmethod.Squirrel.Hans"); +static const CFStringRef kHantInputModeID = + CFSTR("im.rime.inputmethod.Squirrel.Hant"); #define HANS_INPUT_MODE (1 << 0) #define HANT_INPUT_MODE (1 << 1) void RegisterInputSource(void) { CFURLRef installedLocationURL = CFURLCreateFromFileSystemRepresentation( - NULL, kInstallLocation, strlen((const char *)kInstallLocation), NO); + NULL, (UInt8*)kInstallLocation, (CFIndex)strlen(kInstallLocation), false); if (installedLocationURL) { TISRegisterInputSource(installedLocationURL); CFRelease(installedLocationURL); @@ -23,15 +22,15 @@ void RegisterInputSource(void) { void ActivateInputSource(int enabled_modes) { CFArrayRef sourceList = TISCreateInputSourceList(NULL, true); for (CFIndex i = 0; i < CFArrayGetCount(sourceList); ++i) { - TISInputSourceRef inputSource = (TISInputSourceRef)(CFArrayGetValueAtIndex( - sourceList, i)); - NSString *sourceID = (__bridge NSString *)(TISGetInputSourceProperty( - inputSource, kTISPropertyInputSourceID)); - //NSLog(@"Examining input source: %@", sourceID); - if (([sourceID isEqualToString:kHansInputModeID] && - ((enabled_modes & HANS_INPUT_MODE) != 0)) || - ([sourceID isEqualToString:kHantInputModeID] && - ((enabled_modes & HANT_INPUT_MODE) != 0))) { + TISInputSourceRef inputSource = + (TISInputSourceRef)CFArrayGetValueAtIndex(sourceList, i); + CFStringRef sourceID = (CFStringRef)TISGetInputSourceProperty( + inputSource, kTISPropertyInputSourceID); + // NSLog(@"Examining input source: %@", sourceID); + if ((!CFStringCompare(sourceID, kHansInputModeID, 0) && + ((enabled_modes & HANS_INPUT_MODE) != 0)) || + (!CFStringCompare(sourceID, kHantInputModeID, 0) && + ((enabled_modes & HANT_INPUT_MODE) != 0))) { TISEnableInputSource(inputSource); NSLog(@"Enabled input source: %@", sourceID); CFBooleanRef isSelectable = (CFBooleanRef)TISGetInputSourceProperty( @@ -48,15 +47,15 @@ void ActivateInputSource(int enabled_modes) { void DeactivateInputSource(void) { CFArrayRef sourceList = TISCreateInputSourceList(NULL, true); for (CFIndex i = CFArrayGetCount(sourceList); i > 0; --i) { - TISInputSourceRef inputSource = (TISInputSourceRef)(CFArrayGetValueAtIndex( - sourceList, i - 1)); - NSString *sourceID = (__bridge NSString *)(TISGetInputSourceProperty( - inputSource, kTISPropertyInputSourceID)); - //NSLog(@"Examining input source: %@", sourceID); - if ([sourceID isEqualToString:kHansInputModeID] || - [sourceID isEqualToString:kHantInputModeID]) { - CFBooleanRef isEnabled = (CFBooleanRef)(TISGetInputSourceProperty( - inputSource, kTISPropertyInputSourceIsEnabled)); + TISInputSourceRef inputSource = + (TISInputSourceRef)CFArrayGetValueAtIndex(sourceList, i - 1); + CFStringRef sourceID = (CFStringRef)TISGetInputSourceProperty( + inputSource, kTISPropertyInputSourceID); + // NSLog(@"Examining input source: %@", sourceID); + if (!CFStringCompare(sourceID, kHansInputModeID, 0) || + !CFStringCompare(sourceID, kHantInputModeID, 0)) { + CFBooleanRef isEnabled = (CFBooleanRef)TISGetInputSourceProperty( + inputSource, kTISPropertyInputSourceIsEnabled); if (CFBooleanGetValue(isEnabled)) { TISDisableInputSource(inputSource); NSLog(@"Disabled input source: %@", sourceID); @@ -70,20 +69,21 @@ int GetEnabledInputModes(void) { int input_modes = 0; CFArrayRef sourceList = TISCreateInputSourceList(NULL, true); for (CFIndex i = 0; i < CFArrayGetCount(sourceList); ++i) { - TISInputSourceRef inputSource = (TISInputSourceRef)(CFArrayGetValueAtIndex( - sourceList, i)); - NSString *sourceID = (__bridge NSString *)(TISGetInputSourceProperty( - inputSource, kTISPropertyInputSourceID)); - //NSLog(@"Examining input source: %@", sourceID); - if ([sourceID isEqualToString:kHansInputModeID] || - [sourceID isEqualToString:kHantInputModeID]) { - CFBooleanRef isEnabled = (CFBooleanRef)(TISGetInputSourceProperty( - inputSource, kTISPropertyInputSourceIsEnabled)); + TISInputSourceRef inputSource = + (TISInputSourceRef)CFArrayGetValueAtIndex(sourceList, i); + CFStringRef sourceID = (CFStringRef)TISGetInputSourceProperty( + inputSource, kTISPropertyInputSourceID); + // NSLog(@"Examining input source: %@", sourceID); + if (!CFStringCompare(sourceID, kHansInputModeID, 0) || + !CFStringCompare(sourceID, kHantInputModeID, 0)) { + CFBooleanRef isEnabled = (CFBooleanRef)TISGetInputSourceProperty( + inputSource, kTISPropertyInputSourceIsEnabled); if (CFBooleanGetValue(isEnabled)) { - if ([sourceID isEqualToString:kHansInputModeID]) + if (!CFStringCompare(sourceID, kHansInputModeID, 0)) { input_modes |= HANS_INPUT_MODE; - else if ([sourceID isEqualToString:kHantInputModeID]) + } else if (!CFStringCompare(sourceID, kHantInputModeID, 0)) { input_modes |= HANT_INPUT_MODE; + } } } } diff --git a/librime b/librime index 872cecf7f..102d42174 160000 --- a/librime +++ b/librime @@ -1 +1 @@ -Subproject commit 872cecf7f92b6afab7618a4b01e2d8c8f7f7bd7c +Subproject commit 102d42174c2b2d793096621efa571328525c2ed3 diff --git a/macos_keycode.h b/macos_keycode.h index 839bc7605..ef2684da0 100644 --- a/macos_keycode.h +++ b/macos_keycode.h @@ -4,11 +4,11 @@ // masks -#define OSX_CAPITAL_MASK 1 << 16 -#define OSX_SHIFT_MASK 1 << 17 -#define OSX_CTRL_MASK 1 << 18 -#define OSX_ALT_MASK 1 << 19 -#define OSX_COMMAND_MASK 1 << 20 +#define OSX_CAPITAL_MASK 1 << 16 +#define OSX_SHIFT_MASK 1 << 17 +#define OSX_CTRL_MASK 1 << 18 +#define OSX_ALT_MASK 1 << 19 +#define OSX_COMMAND_MASK 1 << 20 // key codes // @@ -63,64 +63,64 @@ // symbol // BACKQUOTE is also known as grave accent or backtick. -#define OSX_VK_BACKQUOTE 0x32 -#define OSX_VK_BACKSLASH 0x2a -#define OSX_VK_BRACKET_LEFT 0x21 +#define OSX_VK_BACKQUOTE 0x32 +#define OSX_VK_BACKSLASH 0x2a +#define OSX_VK_BRACKET_LEFT 0x21 #define OSX_VK_BRACKET_RIGHT 0x1e -#define OSX_VK_COMMA 0x2b -#define OSX_VK_DOT 0x2f -#define OSX_VK_EQUAL 0x18 -#define OSX_VK_MINUS 0x1b -#define OSX_VK_QUOTE 0x27 -#define OSX_VK_SEMICOLON 0x29 -#define OSX_VK_SLASH 0x2c +#define OSX_VK_COMMA 0x2b +#define OSX_VK_DOT 0x2f +#define OSX_VK_EQUAL 0x18 +#define OSX_VK_MINUS 0x1b +#define OSX_VK_QUOTE 0x27 +#define OSX_VK_SEMICOLON 0x29 +#define OSX_VK_SLASH 0x2c // ---------------------------------------- // keypad -#define OSX_VK_KEYPAD_0 0x52 -#define OSX_VK_KEYPAD_1 0x53 -#define OSX_VK_KEYPAD_2 0x54 -#define OSX_VK_KEYPAD_3 0x55 -#define OSX_VK_KEYPAD_4 0x56 -#define OSX_VK_KEYPAD_5 0x57 -#define OSX_VK_KEYPAD_6 0x58 -#define OSX_VK_KEYPAD_7 0x59 -#define OSX_VK_KEYPAD_8 0x5b -#define OSX_VK_KEYPAD_9 0x5c -#define OSX_VK_KEYPAD_CLEAR 0x47 -#define OSX_VK_KEYPAD_COMMA 0x5f -#define OSX_VK_KEYPAD_DOT 0x41 -#define OSX_VK_KEYPAD_EQUAL 0x51 -#define OSX_VK_KEYPAD_MINUS 0x4e +#define OSX_VK_KEYPAD_0 0x52 +#define OSX_VK_KEYPAD_1 0x53 +#define OSX_VK_KEYPAD_2 0x54 +#define OSX_VK_KEYPAD_3 0x55 +#define OSX_VK_KEYPAD_4 0x56 +#define OSX_VK_KEYPAD_5 0x57 +#define OSX_VK_KEYPAD_6 0x58 +#define OSX_VK_KEYPAD_7 0x59 +#define OSX_VK_KEYPAD_8 0x5b +#define OSX_VK_KEYPAD_9 0x5c +#define OSX_VK_KEYPAD_CLEAR 0x47 +#define OSX_VK_KEYPAD_COMMA 0x5f +#define OSX_VK_KEYPAD_DOT 0x41 +#define OSX_VK_KEYPAD_EQUAL 0x51 +#define OSX_VK_KEYPAD_MINUS 0x4e #define OSX_VK_KEYPAD_MULTIPLY 0x43 -#define OSX_VK_KEYPAD_PLUS 0x45 -#define OSX_VK_KEYPAD_SLASH 0x4b +#define OSX_VK_KEYPAD_PLUS 0x45 +#define OSX_VK_KEYPAD_SLASH 0x4b // ---------------------------------------- // special -#define OSX_VK_DELETE 0x33 -#define OSX_VK_ENTER 0x4c +#define OSX_VK_DELETE 0x33 +#define OSX_VK_ENTER 0x4c #define OSX_VK_ENTER_POWERBOOK 0x34 -#define OSX_VK_ESCAPE 0x35 -#define OSX_VK_FORWARD_DELETE 0x75 -#define OSX_VK_HELP 0x72 -#define OSX_VK_RETURN 0x24 -#define OSX_VK_SPACE 0x31 -#define OSX_VK_TAB 0x30 +#define OSX_VK_ESCAPE 0x35 +#define OSX_VK_FORWARD_DELETE 0x75 +#define OSX_VK_HELP 0x72 +#define OSX_VK_RETURN 0x24 +#define OSX_VK_SPACE 0x31 +#define OSX_VK_TAB 0x30 // ---------------------------------------- // function -#define OSX_VK_F1 0x7a -#define OSX_VK_F2 0x78 -#define OSX_VK_F3 0x63 -#define OSX_VK_F4 0x76 -#define OSX_VK_F5 0x60 -#define OSX_VK_F6 0x61 -#define OSX_VK_F7 0x62 -#define OSX_VK_F8 0x64 -#define OSX_VK_F9 0x65 +#define OSX_VK_F1 0x7a +#define OSX_VK_F2 0x78 +#define OSX_VK_F3 0x63 +#define OSX_VK_F4 0x76 +#define OSX_VK_F5 0x60 +#define OSX_VK_F6 0x61 +#define OSX_VK_F7 0x62 +#define OSX_VK_F8 0x64 +#define OSX_VK_F9 0x65 #define OSX_VK_F10 0x6d #define OSX_VK_F11 0x67 #define OSX_VK_F12 0x6f @@ -136,50 +136,50 @@ // functional #define OSX_VK_BRIGHTNESS_DOWN 0x91 -#define OSX_VK_BRIGHTNESS_UP 0x90 -#define OSX_VK_DASHBOARD 0x82 -#define OSX_VK_EXPOSE_ALL 0xa0 -#define OSX_VK_LAUNCHPAD 0x83 +#define OSX_VK_BRIGHTNESS_UP 0x90 +#define OSX_VK_DASHBOARD 0x82 +#define OSX_VK_EXPOSE_ALL 0xa0 +#define OSX_VK_LAUNCHPAD 0x83 #define OSX_VK_MISSION_CONTROL 0xa0 // ---------------------------------------- // cursor -#define OSX_VK_CURSOR_UP 0x7e -#define OSX_VK_CURSOR_DOWN 0x7d -#define OSX_VK_CURSOR_LEFT 0x7b +#define OSX_VK_CURSOR_UP 0x7e +#define OSX_VK_CURSOR_DOWN 0x7d +#define OSX_VK_CURSOR_LEFT 0x7b #define OSX_VK_CURSOR_RIGHT 0x7c -#define OSX_VK_PAGEUP 0x74 +#define OSX_VK_PAGEUP 0x74 #define OSX_VK_PAGEDOWN 0x79 -#define OSX_VK_HOME 0x73 -#define OSX_VK_END 0x77 +#define OSX_VK_HOME 0x73 +#define OSX_VK_END 0x77 // ---------------------------------------- // modifiers -#define OSX_VK_CAPSLOCK 0x39 +#define OSX_VK_CAPSLOCK 0x39 #define OSX_VK_COMMAND_L 0x37 #define OSX_VK_COMMAND_R 0x36 #define OSX_VK_CONTROL_L 0x3b #define OSX_VK_CONTROL_R 0x3e -#define OSX_VK_FN 0x3f -#define OSX_VK_OPTION_L 0x3a -#define OSX_VK_OPTION_R 0x3d -#define OSX_VK_SHIFT_L 0x38 -#define OSX_VK_SHIFT_R 0x3c +#define OSX_VK_FN 0x3f +#define OSX_VK_OPTION_L 0x3a +#define OSX_VK_OPTION_R 0x3d +#define OSX_VK_SHIFT_L 0x38 +#define OSX_VK_SHIFT_R 0x3c // ---------------------------------------- // pc keyboard -#define OSX_VK_PC_APPLICATION 0x6e -#define OSX_VK_PC_BS 0x33 -#define OSX_VK_PC_DEL 0x75 -#define OSX_VK_PC_INSERT 0x72 +#define OSX_VK_PC_APPLICATION 0x6e +#define OSX_VK_PC_BS 0x33 +#define OSX_VK_PC_DEL 0x75 +#define OSX_VK_PC_INSERT 0x72 #define OSX_VK_PC_KEYPAD_NUMLOCK 0x47 -#define OSX_VK_PC_PAUSE 0x71 -#define OSX_VK_PC_POWER 0x7f -#define OSX_VK_PC_PRINTSCREEN 0x69 -#define OSX_VK_PC_SCROLLLOCK 0x6b +#define OSX_VK_PC_PAUSE 0x71 +#define OSX_VK_PC_POWER 0x7f +#define OSX_VK_PC_PRINTSCREEN 0x69 +#define OSX_VK_PC_SCROLLLOCK 0x6b // ---------------------------------------- // international @@ -187,47 +187,47 @@ #define OSX_VK_DANISH_DOLLAR 0xa #define OSX_VK_DANISH_LESS_THAN 0x32 -#define OSX_VK_FRENCH_DOLLAR 0x1e -#define OSX_VK_FRENCH_EQUAL 0x2c -#define OSX_VK_FRENCH_HAT 0x21 -#define OSX_VK_FRENCH_MINUS 0x18 +#define OSX_VK_FRENCH_DOLLAR 0x1e +#define OSX_VK_FRENCH_EQUAL 0x2c +#define OSX_VK_FRENCH_HAT 0x21 +#define OSX_VK_FRENCH_MINUS 0x18 #define OSX_VK_FRENCH_RIGHT_PAREN 0x1b -#define OSX_VK_GERMAN_CIRCUMFLEX 0xa -#define OSX_VK_GERMAN_LESS_THAN 0x32 +#define OSX_VK_GERMAN_CIRCUMFLEX 0xa +#define OSX_VK_GERMAN_LESS_THAN 0x32 #define OSX_VK_GERMAN_PC_LESS_THAN 0x80 -#define OSX_VK_GERMAN_QUOTE 0x18 -#define OSX_VK_GERMAN_A_UMLAUT 0x27 -#define OSX_VK_GERMAN_O_UMLAUT 0x29 -#define OSX_VK_GERMAN_U_UMLAUT 0x21 +#define OSX_VK_GERMAN_QUOTE 0x18 +#define OSX_VK_GERMAN_A_UMLAUT 0x27 +#define OSX_VK_GERMAN_O_UMLAUT 0x29 +#define OSX_VK_GERMAN_U_UMLAUT 0x21 #define OSX_VK_ITALIAN_BACKSLASH 0xa #define OSX_VK_ITALIAN_LESS_THAN 0x32 -#define OSX_VK_JIS_ATMARK 0x21 -#define OSX_VK_JIS_BRACKET_LEFT 0x1e +#define OSX_VK_JIS_ATMARK 0x21 +#define OSX_VK_JIS_BRACKET_LEFT 0x1e #define OSX_VK_JIS_BRACKET_RIGHT 0x2a -#define OSX_VK_JIS_COLON 0x27 -#define OSX_VK_JIS_DAKUON 0x21 -#define OSX_VK_JIS_EISUU 0x66 -#define OSX_VK_JIS_HANDAKUON 0x1e -#define OSX_VK_JIS_HAT 0x18 -#define OSX_VK_JIS_KANA 0x68 -#define OSX_VK_JIS_PC_HAN_ZEN 0x32 -#define OSX_VK_JIS_UNDERSCORE 0x5e -#define OSX_VK_JIS_YEN 0x5d +#define OSX_VK_JIS_COLON 0x27 +#define OSX_VK_JIS_DAKUON 0x21 +#define OSX_VK_JIS_EISUU 0x66 +#define OSX_VK_JIS_HANDAKUON 0x1e +#define OSX_VK_JIS_HAT 0x18 +#define OSX_VK_JIS_KANA 0x68 +#define OSX_VK_JIS_PC_HAN_ZEN 0x32 +#define OSX_VK_JIS_UNDERSCORE 0x5e +#define OSX_VK_JIS_YEN 0x5d #define OSX_VK_RUSSIAN_PARAGRAPH 0xa -#define OSX_VK_RUSSIAN_TILDE 0x32 +#define OSX_VK_RUSSIAN_TILDE 0x32 -#define OSX_VK_SPANISH_LESS_THAN 0x32 +#define OSX_VK_SPANISH_LESS_THAN 0x32 #define OSX_VK_SPANISH_ORDINAL_INDICATOR 0xa #define OSX_VK_SWEDISH_LESS_THAN 0x32 -#define OSX_VK_SWEDISH_SECTION 0xa +#define OSX_VK_SWEDISH_SECTION 0xa #define OSX_VK_SWISS_LESS_THAN 0x32 -#define OSX_VK_SWISS_SECTION 0xa +#define OSX_VK_SWISS_SECTION 0xa #define OSX_VK_UK_SECTION 0xa @@ -236,5 +236,4 @@ int osx_modifiers_to_rime_modifiers(unsigned long modifiers); int osx_keycode_to_rime_keycode(int keycode, int keychar, int shift, int caps); - #endif /* _MACOS_KEYCODE_H_ */ diff --git a/macos_keycode.m b/macos_keycode.m index 0e96d1fb6..2f498a8d1 100644 --- a/macos_keycode.m +++ b/macos_keycode.m @@ -2,11 +2,9 @@ #import "macos_keycode.h" #import - -int osx_modifiers_to_rime_modifiers(unsigned long modifiers) -{ +int osx_modifiers_to_rime_modifiers(unsigned long modifiers) { int ret = 0; - + if (modifiers & OSX_CAPITAL_MASK) ret |= kLockMask; if (modifiers & OSX_SHIFT_MASK) @@ -17,104 +15,101 @@ int osx_modifiers_to_rime_modifiers(unsigned long modifiers) ret |= kAltMask; if (modifiers & OSX_COMMAND_MASK) ret |= kSuperMask; - + return ret; } static struct keycode_mapping_t { int osx_keycode, rime_keycode; } keycode_mappings[] = { - // modifiers - {OSX_VK_CAPSLOCK, XK_Caps_Lock}, - {OSX_VK_COMMAND_L, XK_Super_L}, // XK_Meta_L? - {OSX_VK_COMMAND_R, XK_Super_R}, // XK_Meta_R? - {OSX_VK_CONTROL_L, XK_Control_L}, - {OSX_VK_CONTROL_R, XK_Control_R}, - {OSX_VK_FN, XK_Hyper_L}, - {OSX_VK_OPTION_L, XK_Alt_L}, - {OSX_VK_OPTION_R, XK_Alt_R}, - {OSX_VK_SHIFT_L, XK_Shift_L}, - {OSX_VK_SHIFT_R, XK_Shift_R}, + // modifiers + {OSX_VK_CAPSLOCK, XK_Caps_Lock}, + {OSX_VK_COMMAND_L, XK_Super_L}, // XK_Meta_L? + {OSX_VK_COMMAND_R, XK_Super_R}, // XK_Meta_R? + {OSX_VK_CONTROL_L, XK_Control_L}, + {OSX_VK_CONTROL_R, XK_Control_R}, + {OSX_VK_FN, XK_Hyper_L}, + {OSX_VK_OPTION_L, XK_Alt_L}, + {OSX_VK_OPTION_R, XK_Alt_R}, + {OSX_VK_SHIFT_L, XK_Shift_L}, + {OSX_VK_SHIFT_R, XK_Shift_R}, - // special - {OSX_VK_DELETE, XK_BackSpace}, - {OSX_VK_ENTER, XK_KP_Enter}, - //OSX_VK_ENTER_POWERBOOK -> ? - {OSX_VK_ESCAPE, XK_Escape}, - {OSX_VK_FORWARD_DELETE, XK_Delete}, - //{OSX_VK_HELP, XK_Help}, // the same keycode with OSX_VK_PC_INSERT - {OSX_VK_RETURN, XK_Return}, - {OSX_VK_SPACE, XK_space}, - {OSX_VK_TAB, XK_Tab}, + // special + {OSX_VK_DELETE, XK_BackSpace}, + {OSX_VK_ENTER, XK_KP_Enter}, + // OSX_VK_ENTER_POWERBOOK -> ? + {OSX_VK_ESCAPE, XK_Escape}, + {OSX_VK_FORWARD_DELETE, XK_Delete}, + //{OSX_VK_HELP, XK_Help}, // the same keycode with OSX_VK_PC_INSERT + {OSX_VK_RETURN, XK_Return}, + {OSX_VK_SPACE, XK_space}, + {OSX_VK_TAB, XK_Tab}, - // function - {OSX_VK_F1, XK_F1}, - {OSX_VK_F2, XK_F2}, - {OSX_VK_F3, XK_F3}, - {OSX_VK_F4, XK_F4}, - {OSX_VK_F5, XK_F5}, - {OSX_VK_F6, XK_F6}, - {OSX_VK_F7, XK_F7}, - {OSX_VK_F8, XK_F8}, - {OSX_VK_F9, XK_F9}, - {OSX_VK_F10, XK_F10}, - {OSX_VK_F11, XK_F11}, - {OSX_VK_F12, XK_F12}, - {OSX_VK_F13, XK_F13}, - {OSX_VK_F14, XK_F14}, - {OSX_VK_F15, XK_F15}, - {OSX_VK_F16, XK_F16}, - {OSX_VK_F17, XK_F17}, - {OSX_VK_F18, XK_F18}, - {OSX_VK_F19, XK_F19}, + // function + {OSX_VK_F1, XK_F1}, + {OSX_VK_F2, XK_F2}, + {OSX_VK_F3, XK_F3}, + {OSX_VK_F4, XK_F4}, + {OSX_VK_F5, XK_F5}, + {OSX_VK_F6, XK_F6}, + {OSX_VK_F7, XK_F7}, + {OSX_VK_F8, XK_F8}, + {OSX_VK_F9, XK_F9}, + {OSX_VK_F10, XK_F10}, + {OSX_VK_F11, XK_F11}, + {OSX_VK_F12, XK_F12}, + {OSX_VK_F13, XK_F13}, + {OSX_VK_F14, XK_F14}, + {OSX_VK_F15, XK_F15}, + {OSX_VK_F16, XK_F16}, + {OSX_VK_F17, XK_F17}, + {OSX_VK_F18, XK_F18}, + {OSX_VK_F19, XK_F19}, - // cursor - {OSX_VK_CURSOR_UP, XK_Up}, - {OSX_VK_CURSOR_DOWN, XK_Down}, - {OSX_VK_CURSOR_LEFT, XK_Left}, - {OSX_VK_CURSOR_RIGHT, XK_Right}, - {OSX_VK_PAGEUP, XK_Page_Up}, - {OSX_VK_PAGEDOWN, XK_Page_Down}, - {OSX_VK_HOME, XK_Home}, - {OSX_VK_END, XK_End}, + // cursor + {OSX_VK_CURSOR_UP, XK_Up}, + {OSX_VK_CURSOR_DOWN, XK_Down}, + {OSX_VK_CURSOR_LEFT, XK_Left}, + {OSX_VK_CURSOR_RIGHT, XK_Right}, + {OSX_VK_PAGEUP, XK_Page_Up}, + {OSX_VK_PAGEDOWN, XK_Page_Down}, + {OSX_VK_HOME, XK_Home}, + {OSX_VK_END, XK_End}, - // keypad - {OSX_VK_KEYPAD_0, XK_KP_0}, - {OSX_VK_KEYPAD_1, XK_KP_1}, - {OSX_VK_KEYPAD_2, XK_KP_2}, - {OSX_VK_KEYPAD_3, XK_KP_3}, - {OSX_VK_KEYPAD_4, XK_KP_4}, - {OSX_VK_KEYPAD_5, XK_KP_5}, - {OSX_VK_KEYPAD_6, XK_KP_6}, - {OSX_VK_KEYPAD_7, XK_KP_7}, - {OSX_VK_KEYPAD_8, XK_KP_8}, - {OSX_VK_KEYPAD_9, XK_KP_9}, - {OSX_VK_KEYPAD_CLEAR, XK_Clear}, - {OSX_VK_KEYPAD_COMMA, XK_KP_Separator}, - {OSX_VK_KEYPAD_DOT, XK_KP_Decimal}, - {OSX_VK_KEYPAD_EQUAL, XK_KP_Equal}, - {OSX_VK_KEYPAD_MINUS, XK_KP_Subtract}, - {OSX_VK_KEYPAD_MULTIPLY, XK_KP_Multiply}, - {OSX_VK_KEYPAD_PLUS, XK_KP_Add}, - {OSX_VK_KEYPAD_SLASH, XK_KP_Divide}, + // keypad + {OSX_VK_KEYPAD_0, XK_KP_0}, + {OSX_VK_KEYPAD_1, XK_KP_1}, + {OSX_VK_KEYPAD_2, XK_KP_2}, + {OSX_VK_KEYPAD_3, XK_KP_3}, + {OSX_VK_KEYPAD_4, XK_KP_4}, + {OSX_VK_KEYPAD_5, XK_KP_5}, + {OSX_VK_KEYPAD_6, XK_KP_6}, + {OSX_VK_KEYPAD_7, XK_KP_7}, + {OSX_VK_KEYPAD_8, XK_KP_8}, + {OSX_VK_KEYPAD_9, XK_KP_9}, + {OSX_VK_KEYPAD_CLEAR, XK_Clear}, + {OSX_VK_KEYPAD_COMMA, XK_KP_Separator}, + {OSX_VK_KEYPAD_DOT, XK_KP_Decimal}, + {OSX_VK_KEYPAD_EQUAL, XK_KP_Equal}, + {OSX_VK_KEYPAD_MINUS, XK_KP_Subtract}, + {OSX_VK_KEYPAD_MULTIPLY, XK_KP_Multiply}, + {OSX_VK_KEYPAD_PLUS, XK_KP_Add}, + {OSX_VK_KEYPAD_SLASH, XK_KP_Divide}, - // pc keyboard - {OSX_VK_PC_APPLICATION, XK_Menu}, - {OSX_VK_PC_INSERT, XK_Insert}, - {OSX_VK_PC_KEYPAD_NUMLOCK, XK_Num_Lock}, - {OSX_VK_PC_PAUSE, XK_Pause}, - //OSX_VK_PC_POWER -> ? - {OSX_VK_PC_PRINTSCREEN, XK_Print}, - {OSX_VK_PC_SCROLLLOCK, XK_Scroll_Lock}, + // pc keyboard + {OSX_VK_PC_APPLICATION, XK_Menu}, + {OSX_VK_PC_INSERT, XK_Insert}, + {OSX_VK_PC_KEYPAD_NUMLOCK, XK_Num_Lock}, + {OSX_VK_PC_PAUSE, XK_Pause}, + // OSX_VK_PC_POWER -> ? + {OSX_VK_PC_PRINTSCREEN, XK_Print}, + {OSX_VK_PC_SCROLLLOCK, XK_Scroll_Lock}, - {-1, -1} -}; + {-1, -1}}; -int osx_keycode_to_rime_keycode(int keycode, int keychar, int shift, int caps) -{ - for (struct keycode_mapping_t *mapping = keycode_mappings; - mapping->osx_keycode >= 0; - ++mapping) { +int osx_keycode_to_rime_keycode(int keycode, int keychar, int shift, int caps) { + for (struct keycode_mapping_t* mapping = keycode_mappings; + mapping->osx_keycode >= 0; ++mapping) { if (keycode == mapping->osx_keycode) { return mapping->rime_keycode; } @@ -128,20 +123,15 @@ int osx_keycode_to_rime_keycode(int keycode, int keychar, int shift, int caps) if (keychar >= 0x20 && keychar <= 0x7e) { return keychar; - } - else if (keychar == 0x1b) { // ^[ + } else if (keychar == 0x1b) { // ^[ return XK_bracketleft; - } - else if (keychar == 0x1c) { // ^\ + } else if (keychar == 0x1c) { // ^\ return XK_backslash; - } - else if (keychar == 0x1d) { // ^] + } else if (keychar == 0x1d) { // ^] return XK_bracketright; - } - else if (keychar == 0x1f) { // ^_ + } else if (keychar == 0x1f) { // ^_ return XK_minus; } return XK_VoidSymbol; } - diff --git a/main.m b/main.m index 2a1a556f3..53b6491c0 100644 --- a/main.m +++ b/main.m @@ -14,14 +14,14 @@ // Each input method needs a unique connection name. // Note that periods and spaces are not allowed in the connection name. -const NSString *kConnectionName = @"Squirrel_1_Connection"; +static NSString* const kConnectionName = @"Squirrel_1_Connection"; -int main(int argc, char *argv[]) { +int main(int argc, char* argv[]) { if (argc > 1 && !strcmp("--quit", argv[1])) { - NSString *bundleId = [NSBundle mainBundle].bundleIdentifier; - NSArray *runningSquirrels = + NSString* bundleId = [NSBundle mainBundle].bundleIdentifier; + NSArray* runningSquirrels = [NSRunningApplication runningApplicationsWithBundleIdentifier:bundleId]; - for (NSRunningApplication *squirrelApp in runningSquirrels) { + for (NSRunningApplication* squirrelApp in runningSquirrels) { [squirrelApp terminate]; } return 0; @@ -39,7 +39,7 @@ int main(int argc, char *argv[]) { RegisterInputSource(); int input_modes = GetEnabledInputModes(); DeactivateInputSource(); - ActivateInputSource(input_modes ? input_modes : DEFAULT_INPUT_MODE); + ActivateInputSource(input_modes ?: DEFAULT_INPUT_MODE); return 0; } @@ -63,14 +63,16 @@ int main(int argc, char *argv[]) { @autoreleasepool { // find the bundle identifier and then initialize the input method server - NSBundle *main = [NSBundle mainBundle]; - IMKServer *server __unused = - [[IMKServer alloc] initWithName:(NSString *)kConnectionName + NSBundle* main = [NSBundle mainBundle]; + IMKServer* server __unused = + [[IMKServer alloc] initWithName:kConnectionName bundleIdentifier:main.bundleIdentifier]; // load the bundle explicitly because in this case the input method is a // background only application - [main loadNibNamed:@"MainMenu" owner:[NSApplication sharedApplication] topLevelObjects:NULL]; + [main loadNibNamed:@"MainMenu" + owner:[NSApplication sharedApplication] + topLevelObjects:nil]; // opencc will be configured with relative dictionary paths [[NSFileManager defaultManager] @@ -78,15 +80,18 @@ int main(int argc, char *argv[]) { if (NSApp.squirrelAppDelegate.problematicLaunchDetected) { NSLog(@"Problematic launch detected!"); - NSArray *args = @[ - @"Problematic launch detected! \ + NSArray* args = @[ @"Problematic launch detected! \ Squirrel may be suffering a crash due to imporper configuration. \ - Revert previous modifications to see if the problem recurs." - ]; - [NSTask launchedTaskWithLaunchPath:@"/usr/bin/say" arguments:args]; + Revert previous modifications to see if the problem recurs." ]; + [NSTask + launchedTaskWithExecutableURL:[NSURL fileURLWithPath:@"/usr/bin/say" + isDirectory:NO] + arguments:args + error:nil + terminationHandler:nil]; } else { [NSApp.squirrelAppDelegate setupRime]; - [NSApp.squirrelAppDelegate startRimeWithFullCheck:NO]; + [NSApp.squirrelAppDelegate startRimeWithFullCheck:false]; [NSApp.squirrelAppDelegate loadSettings]; NSLog(@"Squirrel reporting!"); } diff --git a/plum b/plum index ff888cbb9..6f502ff6f 160000 --- a/plum +++ b/plum @@ -1 +1 @@ -Subproject commit ff888cbb9fce8c3f5b8b355baeb10685b2052b43 +Subproject commit 6f502ff6fa87789847fa18200415318e705bffa4