From a11e30daf478a4c05127f99b90acb6026e204e42 Mon Sep 17 00:00:00 2001 From: David Kamholz Date: Fri, 21 Jun 2019 20:09:01 -0700 Subject: [PATCH 01/11] fix CGEventTapCreate mask flags --- mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m index 335d2f2bed..befdc19fb4 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m @@ -81,7 +81,7 @@ id _lastServerWithOSKShowing = nil; forEventClass:kInternetEventClass andEventID:kAEGetURL]; - self.lowLevelEventTap = CGEventTapCreate(kCGAnnotatedSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, NSFlagsChangedMask | NSLeftMouseDown | NSLeftMouseUp, (CGEventTapCallBack)eventTapFunction, nil); + self.lowLevelEventTap = CGEventTapCreate(kCGAnnotatedSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, CGEventMaskBit(kCGEventFlagsChanged) | CGEventMaskBit(kCGEventLeftMouseDown) | CGEventMaskBit(kCGEventLeftMouseUp), (CGEventTapCallBack)eventTapFunction, nil); if (!self.lowLevelEventTap) { NSLog(@"Can't tap into low level events!"); From 109b5769b7a9705fa2d45e4cbf5f382822440d3a Mon Sep 17 00:00:00 2001 From: David Kamholz Date: Fri, 21 Jun 2019 20:20:05 -0700 Subject: [PATCH 02/11] refresh contextBuffer on flagsChanged --- mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m | 2 +- mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m index 7f06c529d2..c7708a4e52 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m @@ -41,7 +41,7 @@ NSMutableArray *servers; } - (NSUInteger)recognizedEvents:(id)sender { - return (NSEventMaskKeyDown); + return NSEventMaskKeyDown | NSEventMaskFlagsChanged; } - (BOOL)handleEvent:(NSEvent *)event client:(id)sender { diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m index cbaa1e1c06..ecd5ef8e8a 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m @@ -489,6 +489,11 @@ NSRange _previousSelRange; /*if (event.type == NSKeyDown) [self.AppDelegate handleKeyEvent:event];*/ + if (event.type == NSFlagsChanged) { + _contextOutOfDate = YES; + return NO; + } + if ((event.modifierFlags & NSEventModifierFlagCommand) == NSEventModifierFlagCommand) { [self handleCommand:event]; return NO; // We let the client app handle all Command-key events. From e8dc674f59dc8b26a37c92cdfb561b5bac6e9415 Mon Sep 17 00:00:00 2001 From: David Kamholz Date: Thu, 20 Jun 2019 22:01:24 -0700 Subject: [PATCH 03/11] fix multiple deadkey issue --- .../KeymanEngine4Mac/KME/Categories/NSArray+Action.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSArray+Action.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSArray+Action.m index c305b0da49..2d7c0c8fa3 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSArray+Action.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSArray+Action.m @@ -36,6 +36,9 @@ [self removeLastObject]; [self addObject:mAction]; } + else if ([preActionType isEqualToString:Q_DEADKEY]) { + [self addObject:newAction]; + } } else if ([preActionType isEqualToString:Q_STR] && [newActionType isEqualToString:Q_BACK]) { NSString *preStr = [preAction objectForKey:preActionType]; From 528fe590f2cf162a827a0eab0e6b0576716d0152 Mon Sep 17 00:00:00 2001 From: David Kamholz Date: Thu, 20 Jun 2019 23:34:48 -0700 Subject: [PATCH 04/11] fix issue with >10 deadkey --- .../KeymanEngine4Mac/KME/Categories/NSString+XString.m | 2 +- mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSString+XString.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSString+XString.m index d1f41104ba..61ddc70f66 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSString+XString.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSString+XString.m @@ -356,7 +356,7 @@ @implementation NSMutableString (XString) - (void)appendDeadkey:(NSUInteger)index { - NSString *dk = [NSString stringWithFormat:@"%C%C%lu", UC_SENTINEL, CODE_DEADKEY, index]; + NSString *dk = [NSString stringWithFormat:@"%C%C%C", UC_SENTINEL, CODE_DEADKEY, index]; [self appendString:dk]; } diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m index cca2bf0738..6df9c909ec 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m @@ -770,7 +770,7 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; DWORD index = [keyCtx characterAtIndex:i+2]; if ([ctx characterAtIndex:px] == UC_SENTINEL && [ctx characterAtIndex:px+1] == CODE_DEADKEY) { px+=2; - c = [[NSString stringWithFormat:@"%d", index] characterAtIndex:0]; + c = [[NSString stringWithFormat:@"%C", index] characterAtIndex:0]; unichar c2 = [ctx characterAtIndex:px]; if (c != c2) return 0; From e12de50af6b391759521354e417815bc301523cd Mon Sep 17 00:00:00 2001 From: David Kamholz Date: Fri, 21 Jun 2019 11:20:49 -0700 Subject: [PATCH 05/11] remove obsolete code --- .../KeymanEngine4Mac/KME/Categories/NSArray+Action.m | 3 --- 1 file changed, 3 deletions(-) diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSArray+Action.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSArray+Action.m index 2d7c0c8fa3..c305b0da49 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSArray+Action.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSArray+Action.m @@ -36,9 +36,6 @@ [self removeLastObject]; [self addObject:mAction]; } - else if ([preActionType isEqualToString:Q_DEADKEY]) { - [self addObject:newAction]; - } } else if ([preActionType isEqualToString:Q_STR] && [newActionType isEqualToString:Q_BACK]) { NSString *preStr = [preAction objectForKey:preActionType]; From 46a2c981c8d67cfade54ffd967dd64025901f00c Mon Sep 17 00:00:00 2001 From: David Kamholz Date: Thu, 20 Jun 2019 01:51:49 -0700 Subject: [PATCH 06/11] add support for if(), set(), reset(), save() --- .../KeymanEngine4Mac/KME/KMCompStore.h | 1 + .../KeymanEngine4Mac/KME/KMCompStore.m | 12 +++++ .../KeymanEngine4Mac/KME/KMEngine.m | 47 ++++++++++++++++--- .../KeymanEngine4Mac/KME/KMXFile.h | 1 + .../KeymanEngine4Mac/KME/KMXFile.m | 1 + 5 files changed, 56 insertions(+), 6 deletions(-) diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMCompStore.h b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMCompStore.h index 1d391eddd3..251b89d04b 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMCompStore.h +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMCompStore.h @@ -20,6 +20,7 @@ @property (strong, nonatomic) NSString *string; - (void)setDwSystemID:(DWORD)dwID; +- (id)copyWithZone:(NSZone *)zone; @end diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMCompStore.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMCompStore.m index b260980b9d..9f7c6dc9c6 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMCompStore.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMCompStore.m @@ -21,6 +21,18 @@ return self; } +- (id)copyWithZone:(NSZone *)zone { + KMCompStore *newStore = [[[self class] allocWithZone:zone] init]; + + if (newStore) { + [newStore setDwSystemID:[self dwSystemID]]; + if ([self name]) newStore.name = [[NSString alloc] initWithString:[self name]]; + if ([self string]) newStore.string = [[NSString alloc] initWithString:[self string]]; + } + + return newStore; +} + - (NSString *)description { NSString *format = @"<%@:%p ID:0x%X DN:%@ N:%@ S:%@>"; NSString *str = [NSString stringWithFormat:format, diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m index 6df9c909ec..1e73e8dcce 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m @@ -517,6 +517,33 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; i+=2; break; } + case CODE_SETOPT: { + DWORD x1 = [outKey characterAtIndex:i+2]-1; + DWORD x2 = [outKey characterAtIndex:i+3]-1; + KMCompStore *store1 = [self.kmx.store objectAtIndex:x1]; + KMCompStore *store2 = [self.kmx.store objectAtIndex:x2]; + store1.string = [[NSString alloc] initWithString:store2.string]; + + i+=4; + break; + } + case CODE_RESETOPT: { + DWORD x1 = [outKey characterAtIndex:i+2]-1; + KMCompStore *store = [self.kmx.store objectAtIndex:x1]; + KMCompStore *storeSaved = [self.kmx.storeSaved objectAtIndex:x1]; + + store.string = [[NSString alloc] initWithString:storeSaved.string]; + i+=3; + break; + } + case CODE_SAVEOPT: { + DWORD x1 = [outKey characterAtIndex:i+2]-1; + KMCompStore *store = [self.kmx.store objectAtIndex:x1]; + KMCompStore *storeSaved = [self.kmx.storeSaved objectAtIndex:x1]; + storeSaved.string = [[NSString alloc] initWithString:store.string]; + i+=3; + break; + } default: i+=2; break; @@ -784,13 +811,21 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; break; } case CODE_IFOPT: { - //DWORD x1 = [keyCtx characterAtIndex:i+2]-1; - //DWORD x2 = [keyCtx characterAtIndex:i+3]-1; - //DWORD x3 = [keyCtx characterAtIndex:i+4]-1; - //KMCompStore *store = [self.kmx.store objectAtIndex:x3]; - //i+=5; + DWORD x1 = [keyCtx characterAtIndex:i+2]-1; + DWORD x2 = [keyCtx characterAtIndex:i+3]-1; + DWORD x3 = [keyCtx characterAtIndex:i+4]-1; + KMCompStore *store1 = [self.kmx.store objectAtIndex:x1]; + KMCompStore *store2 = [self.kmx.store objectAtIndex:x3]; + + BOOL match = [store1.string isEqualToString:store2.string]; + if ((match && x2 == EQUAL) || (!match && x2 == NOT_EQUAL)) { + cx+=1000; + } + else { + return 0; + } - return 0; // CODE_IFOPT is not supported + i+=5; break; } case CODE_IFSYSTEMSTORE: { diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMXFile.h b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMXFile.h index 287f4400e0..b94c8aab86 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMXFile.h +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMXFile.h @@ -29,6 +29,7 @@ extern NSString *const kKMVisualKeyboardKey; @property (assign, nonatomic, readonly) BOOL isMnemonic; @property (assign, nonatomic, readonly) DWORD version; @property (strong, nonatomic, readonly) NSArray *store; +@property (strong, nonatomic, readonly) NSArray *storeSaved; @property (strong, nonatomic, readonly) NSArray *group; @property (strong, nonatomic, readonly) NSArray *startGroup; @property (assign, nonatomic, readonly) DWORD flags; diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMXFile.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMXFile.m index e25dc2d813..a467309a11 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMXFile.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMXFile.m @@ -95,6 +95,7 @@ NSString *const kKMVisualKeyboardKey = @"KMVisualKeyboardKey"; } _store = [[NSArray alloc] initWithArray:mStore]; + _storeSaved = [[NSArray alloc] initWithArray:mStore copyItems:YES]; struct COMP_GROUP cmp_grp[cmp_kb.cxGroupArray]; [file seekToFileOffset:cmp_kb.dpGroupArray]; From 786e0e1223f8f562b7e4018171d8a22eb8fac354 Mon Sep 17 00:00:00 2001 From: David Kamholz Date: Thu, 20 Jun 2019 23:51:58 -0700 Subject: [PATCH 07/11] make set/reset/save work when only statement on rhs --- mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m index 1e73e8dcce..7d4c274c75 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m @@ -408,6 +408,8 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; if (!outKey || !outKey.length) return nil; + BOOL handled = NO; + for (int i = 0; i < outKey.length;) { unichar c = [outKey characterAtIndex:i]; if (c == UC_SENTINEL) { @@ -523,6 +525,7 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; KMCompStore *store1 = [self.kmx.store objectAtIndex:x1]; KMCompStore *store2 = [self.kmx.store objectAtIndex:x2]; store1.string = [[NSString alloc] initWithString:store2.string]; + handled = YES; i+=4; break; @@ -531,8 +534,8 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; DWORD x1 = [outKey characterAtIndex:i+2]-1; KMCompStore *store = [self.kmx.store objectAtIndex:x1]; KMCompStore *storeSaved = [self.kmx.storeSaved objectAtIndex:x1]; - store.string = [[NSString alloc] initWithString:storeSaved.string]; + handled = YES; i+=3; break; } @@ -541,6 +544,7 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; KMCompStore *store = [self.kmx.store objectAtIndex:x1]; KMCompStore *storeSaved = [self.kmx.storeSaved objectAtIndex:x1]; storeSaved.string = [[NSString alloc] initWithString:store.string]; + handled = YES; i+=3; break; } @@ -565,6 +569,11 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; NSLog(@"tmpCtxBuf = \"%@\"", [self.tmpCtxBuf codeString]); } + if (!actions && handled) { + NSDictionary *action = [[NSDictionary alloc] initWithObjectsAndKeys:@"", Q_NUL, nil]; + actions = [[NSMutableArray alloc] initWithObjects:action, nil]; + } + return actions; } From 8a44d048e3f1cf3a79a2ee1d287dfc3da71113c5 Mon Sep 17 00:00:00 2001 From: David Kamholz Date: Fri, 21 Jun 2019 11:18:58 -0700 Subject: [PATCH 08/11] persist save() values across sessions --- .../Keyman4MacIM/KMInputController.m | 1 + .../Keyman4MacIM/KMInputMethodAppDelegate.h | 2 + .../Keyman4MacIM/KMInputMethodAppDelegate.m | 50 +++++++++++++++++++ .../Keyman4MacIM/KMInputMethodEventHandler.m | 6 +++ .../KME/Categories/NSArray+Action.m | 3 ++ .../KeymanEngine4Mac/KME/KMEngine.h | 2 + .../KeymanEngine4Mac/KME/KMEngine.m | 24 +++++++-- 7 files changed, 83 insertions(+), 5 deletions(-) diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m index c7708a4e52..b6f6521b43 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputController.m @@ -223,6 +223,7 @@ NSMutableArray *servers; [self.AppDelegate setKeyboardIcon:[kmxInfo objectForKey:kKMKeyboardIconKey]]; [self.AppDelegate setContextBuffer:nil]; [self.AppDelegate setSelectedKeyboard:path]; + [self.AppDelegate loadSavedStores]; if (kvk != nil && self.AppDelegate.alwaysShowOSK) [self.AppDelegate showOSK]; } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.h b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.h index 4fc27105ea..a7a2d63f34 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.h +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.h @@ -89,6 +89,8 @@ extern NSString *const kWebSite; - (NSMenu *)menu; - (void)saveActiveKeyboards; +- (void)loadSavedStores; +- (void)saveStore:(NSNumber *)storeKey withValue:(NSString* )value; - (void)showAboutWindow; - (void)showOSK; - (void)showConfigurationWindow; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m index befdc19fb4..3d157512a1 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m @@ -24,6 +24,7 @@ NSString *const kKMSelectedKeyboardKey = @"KMSelectedKeyboardKey"; NSString *const kKMActiveKeyboardsKey = @"KMActiveKeyboardsKey"; +NSString *const kKMSavedStoresKey = @"KMSavedStoresKey"; NSString *const kKMAlwaysShowOSKKey = @"KMAlwaysShowOSKKey"; NSString *const kKMUseVerboseLogging = @"KMUseVerboseLogging"; NSString *const kKeymanKeyboardDownloadCompletedNotification = @"kKeymanKeyboardDownloadCompletedNotification"; @@ -308,6 +309,53 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef [_oskWindow.window setTitle:self.oskWindowTitle]; } +- (void)loadSavedStores { + NSUserDefaults *userData = [NSUserDefaults standardUserDefaults]; + NSDictionary *allSavedStores = [userData dictionaryForKey:kKMSavedStoresKey]; + if (!allSavedStores) return; + NSDictionary *savedStores = [allSavedStores objectForKey:_selectedKeyboard]; + if (!savedStores) return; + + NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init]; + fmt.numberStyle = NSNumberFormatterDecimalStyle; + + for (NSString *key in savedStores) { + NSString *value = [savedStores objectForKey:key]; + NSUInteger storeID = [[fmt numberFromString:key] unsignedIntegerValue]; + [self.kme setStore:(DWORD)storeID withValue:value]; + } +} + +- (void)saveStore:(NSNumber *)storeKey withValue:(NSString* )value { + NSString *storeKeyStr = [storeKey stringValue]; + NSUserDefaults *userData = [NSUserDefaults standardUserDefaults]; + NSDictionary *allSavedStores = [userData dictionaryForKey:kKMSavedStoresKey]; + NSDictionary *savedStores; + + if (allSavedStores) { + savedStores = [allSavedStores objectForKey:_selectedKeyboard]; + } + + if (savedStores) { + NSMutableDictionary *newSavedStores = [savedStores mutableCopy]; + [newSavedStores setObject:value forKey:storeKeyStr]; + savedStores = newSavedStores; + } else { + savedStores = [[NSDictionary alloc] initWithObjectsAndKeys:value, storeKeyStr, nil]; + } + + if (allSavedStores) { + NSMutableDictionary *newAllSavedStores = [allSavedStores mutableCopy]; + [newAllSavedStores setObject:savedStores forKey:_selectedKeyboard]; + allSavedStores = newAllSavedStores; + } else { + allSavedStores = [[NSDictionary alloc] initWithObjectsAndKeys:savedStores, _selectedKeyboard, nil]; + } + + [userData setObject:allSavedStores forKey:kKMSavedStoresKey]; + [userData synchronize]; +} + - (NSString *)oskWindowTitle { if (_keyboardName == nil || !_keyboardName.length) return [NSString stringWithFormat:@"Keyman"]; @@ -765,6 +813,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef [self setKvk:kvk]; [self setKeyboardName:[kmxInfo objectForKey:kKMKeyboardNameKey]]; [self setKeyboardIcon:[kmxInfo objectForKey:kKMKeyboardIconKey]]; + [self loadSavedStores]; didSetKeyboard = YES; } @@ -800,6 +849,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef [self setKeyboardName:[kmxInfo objectForKey:kKMKeyboardNameKey]]; [self setKeyboardIcon:[kmxInfo objectForKey:kKMKeyboardIconKey]]; [self setContextBuffer:nil]; + [self loadSavedStores]; [self setSelectedKeyboard:path]; } } diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m index ecd5ef8e8a..01d9bb818c 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodEventHandler.m @@ -425,6 +425,12 @@ NSRange _previousSelRange; else if ([actionType isEqualToString:Q_BEEP]) { [[NSSound soundNamed:@"Tink"] play]; } + else if ([actionType isEqualToString:Q_SAVEOPT]) { + NSDictionary *save = [action objectForKey:actionType]; + NSNumber *storeKey = [save allKeys][0]; + NSString *value = [save objectForKey:storeKey]; + [self.AppDelegate saveStore:storeKey withValue:value]; + } } return YES; } diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSArray+Action.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSArray+Action.m index c305b0da49..b87ecbf4ba 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSArray+Action.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/Categories/NSArray+Action.m @@ -36,6 +36,9 @@ [self removeLastObject]; [self addObject:mAction]; } + else { + [self addObject:newAction]; + } } else if ([preActionType isEqualToString:Q_STR] && [newActionType isEqualToString:Q_BACK]) { NSString *preStr = [preAction objectForKey:preActionType]; diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.h b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.h index e1fd6ec2dd..4e81fbcb56 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.h +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.h @@ -20,6 +20,7 @@ extern NSString *const Q_DEADKEY; extern NSString *const Q_NUL; extern NSString *const Q_BEEP; extern NSString *const Q_RETURN; +extern NSString *const Q_SAVEOPT; extern DWORD VKMap[0x80]; @@ -31,6 +32,7 @@ extern DWORD VKMap[0x80]; - (id)initWithKMX:(KMXFile *)kmx contextBuffer:(NSString *)ctxBuf; - (void)setContextBuffer:(NSString *)ctxBuf; - (NSString *)contextBuffer; +- (void)setStore:(DWORD)storeID withValue:(NSString *)value; - (NSArray *)processEvent:(NSEvent *)event; - (void)setUseVerboseLogging:(BOOL)useVerboseLogging; diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m index 7d4c274c75..fb234b1359 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m @@ -23,6 +23,7 @@ NSString *const Q_DEADKEY = @"Q_DEADKEY"; NSString *const Q_NUL = @"Q_NUL"; NSString *const Q_BEEP = @"Q_BEEP"; NSString *const Q_RETURN = @"Q_RETURN"; +NSString *const Q_SAVEOPT = @"Q_SAVEOPT"; DWORD VKMap[0x80]; @@ -103,6 +104,11 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; return _tmpCtxBuf; } +- (void)setStore:(DWORD)storeID withValue:(NSString *)value { + KMCompStore *store = [self.kmx.store objectAtIndex:storeID]; + store.string = [[NSString alloc] initWithString:value]; +} + - (NSArray *)processEvent:(NSEvent *)event { NSArray *actions = nil; @@ -408,7 +414,7 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; if (!outKey || !outKey.length) return nil; - BOOL handled = NO; + BOOL handledWithoutActions = NO; for (int i = 0; i < outKey.length;) { unichar c = [outKey characterAtIndex:i]; @@ -525,7 +531,7 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; KMCompStore *store1 = [self.kmx.store objectAtIndex:x1]; KMCompStore *store2 = [self.kmx.store objectAtIndex:x2]; store1.string = [[NSString alloc] initWithString:store2.string]; - handled = YES; + handledWithoutActions = YES; i+=4; break; @@ -535,7 +541,7 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; KMCompStore *store = [self.kmx.store objectAtIndex:x1]; KMCompStore *storeSaved = [self.kmx.storeSaved objectAtIndex:x1]; store.string = [[NSString alloc] initWithString:storeSaved.string]; - handled = YES; + handledWithoutActions = YES; i+=3; break; } @@ -544,7 +550,15 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; KMCompStore *store = [self.kmx.store objectAtIndex:x1]; KMCompStore *storeSaved = [self.kmx.storeSaved objectAtIndex:x1]; storeSaved.string = [[NSString alloc] initWithString:store.string]; - handled = YES; + handledWithoutActions = YES; + + NSDictionary *actionObj = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSString alloc] initWithString:store.string], [NSNumber numberWithUnsignedInteger:x1], nil]; + NSDictionary *action = [[NSDictionary alloc] initWithObjectsAndKeys:actionObj, Q_SAVEOPT, nil]; + if (!actions) + actions = [[NSMutableArray alloc] initWithObjects:action, nil]; + else + [actions addAction:action]; + i+=3; break; } @@ -569,7 +583,7 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; NSLog(@"tmpCtxBuf = \"%@\"", [self.tmpCtxBuf codeString]); } - if (!actions && handled) { + if (!actions && handledWithoutActions) { NSDictionary *action = [[NSDictionary alloc] initWithObjectsAndKeys:@"", Q_NUL, nil]; actions = [[NSMutableArray alloc] initWithObjects:action, nil]; } From 746dee181a138caa8948e1a3c226ff197e26e497 Mon Sep 17 00:00:00 2001 From: David Kamholz Date: Fri, 21 Jun 2019 13:49:58 -0700 Subject: [PATCH 09/11] remove unnecessary line --- mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m | 1 - 1 file changed, 1 deletion(-) diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m index fb234b1359..885155fa8a 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m @@ -550,7 +550,6 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; KMCompStore *store = [self.kmx.store objectAtIndex:x1]; KMCompStore *storeSaved = [self.kmx.storeSaved objectAtIndex:x1]; storeSaved.string = [[NSString alloc] initWithString:store.string]; - handledWithoutActions = YES; NSDictionary *actionObj = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSString alloc] initWithString:store.string], [NSNumber numberWithUnsignedInteger:x1], nil]; NSDictionary *action = [[NSDictionary alloc] initWithObjectsAndKeys:actionObj, Q_SAVEOPT, nil]; From 8262f3c1be59f720216c77a6f81a007381914338 Mon Sep 17 00:00:00 2001 From: David Kamholz Date: Sat, 22 Jun 2019 12:33:18 -0700 Subject: [PATCH 10/11] make setStore also set storeSaved --- mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m index 885155fa8a..ee123ce95d 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMEngine.m @@ -106,7 +106,9 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx"; - (void)setStore:(DWORD)storeID withValue:(NSString *)value { KMCompStore *store = [self.kmx.store objectAtIndex:storeID]; + KMCompStore *storeSaved = [self.kmx.storeSaved objectAtIndex:storeID]; store.string = [[NSString alloc] initWithString:value]; + storeSaved.string = [[NSString alloc] initWithString:value]; } - (NSArray *)processEvent:(NSEvent *)event { From 9dd06b3f278ebb0ed4b672fe694a7b513df11ea9 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 9 Jul 2019 06:36:48 +1000 Subject: [PATCH 11/11] [mac] [cherry-pick] [11.0] Merge fixes for #1838, #1839, #1840 into 11.0 --- mac/history.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mac/history.md b/mac/history.md index 03828de9b6..5f23d80858 100644 --- a/mac/history.md +++ b/mac/history.md @@ -1,5 +1,10 @@ # Keyman for macOS Version History +## 2019-02-26 11.0.221 stable +* Add support for option stores (if/set/reset/save statements) (#1838) +* Fix bug where keyboards with more than nine deadkeys did not operate correctly (#1839) +* Fix out of date context buffer when using command keys (#1840) + ## 2019-02-25 11.0.220 stable * 11.0 Stable release