From 8a44d048e3f1cf3a79a2ee1d287dfc3da71113c5 Mon Sep 17 00:00:00 2001 From: David Kamholz Date: Fri, 21 Jun 2019 11:18:58 -0700 Subject: [PATCH] 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]; }