chore(typing): snapshot local pinyin WIP before syncing cloud branch
Preserve the in-progress local typing/pinyin implementation so feat/pinyin can safely reset to origin/feat/pinyin (cloud English + Chinese typing).
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
#import "include/OSGRimeBridge.h"
|
||||
|
||||
@import RimeStatic;
|
||||
|
||||
const int OSGRimeKeyBackSpace = 0xff08;
|
||||
const int OSGRimeKeyReturn = 0xff0d;
|
||||
|
||||
static NSString *const OSGRimeErrorDomain = @"com.osgkeyboard.rime";
|
||||
static RimeApi_stdbool *OSGRimeAPI(void) {
|
||||
return rime_get_api_stdbool();
|
||||
}
|
||||
|
||||
@implementation OSGRimeCandidate
|
||||
|
||||
- (instancetype)initWithText:(NSString *)text comment:(NSString *)comment {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_text = [text copy];
|
||||
_comment = [comment copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation OSGRimeSnapshot
|
||||
|
||||
- (instancetype)initWithPreedit:(NSString *)preedit
|
||||
candidates:(NSArray<OSGRimeCandidate *> *)candidates
|
||||
commitText:(NSString *)commitText
|
||||
composing:(BOOL)composing {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_preedit = [preedit copy];
|
||||
_candidates = [candidates copy];
|
||||
_commitText = [commitText copy];
|
||||
_composing = composing;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface OSGRimeBridge ()
|
||||
@property(nonatomic, copy) NSString *sharedDataDirectory;
|
||||
@property(nonatomic, copy) NSString *userDataDirectory;
|
||||
@property(nonatomic, copy) NSString *distributionVersion;
|
||||
@property(nonatomic) RimeSessionId session;
|
||||
@end
|
||||
|
||||
@implementation OSGRimeBridge
|
||||
|
||||
static BOOL sSetupComplete = NO;
|
||||
static BOOL sInitialized = NO;
|
||||
|
||||
- (instancetype)initWithSharedDataDirectory:(NSString *)sharedDataDirectory
|
||||
userDataDirectory:(NSString *)userDataDirectory
|
||||
distributionVersion:(NSString *)distributionVersion {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_sharedDataDirectory = [sharedDataDirectory copy];
|
||||
_userDataDirectory = [userDataDirectory copy];
|
||||
_distributionVersion = [distributionVersion copy];
|
||||
_session = 0;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)running {
|
||||
return self.session != 0 && OSGRimeAPI()->find_session(self.session);
|
||||
}
|
||||
|
||||
- (void)populateTraits:(RimeTraits *)traits {
|
||||
traits->shared_data_dir = self.sharedDataDirectory.UTF8String;
|
||||
traits->user_data_dir = self.userDataDirectory.UTF8String;
|
||||
traits->distribution_name = "OSGKeyboard";
|
||||
traits->distribution_code_name = "OSGKeyboard";
|
||||
traits->distribution_version = self.distributionVersion.UTF8String;
|
||||
traits->app_name = "rime.OSGKeyboard";
|
||||
traits->min_log_level = 2;
|
||||
}
|
||||
|
||||
- (BOOL)prepareRuntime:(NSError **)error {
|
||||
RimeApi_stdbool *api = OSGRimeAPI();
|
||||
if (api == NULL) {
|
||||
if (error) {
|
||||
*error = [NSError errorWithDomain:OSGRimeErrorDomain
|
||||
code:1
|
||||
userInfo:@{NSLocalizedDescriptionKey: @"librime API unavailable"}];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
@synchronized([OSGRimeBridge class]) {
|
||||
RIME_STRUCT(RimeTraits, traits);
|
||||
[self populateTraits:&traits];
|
||||
if (!sSetupComplete) {
|
||||
api->setup(&traits);
|
||||
sSetupComplete = YES;
|
||||
}
|
||||
if (!sInitialized) {
|
||||
api->initialize(&traits);
|
||||
sInitialized = YES;
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)start:(NSError **)error {
|
||||
if (![self prepareRuntime:error]) {
|
||||
return NO;
|
||||
}
|
||||
if ([self running]) {
|
||||
return YES;
|
||||
}
|
||||
self.session = OSGRimeAPI()->create_session();
|
||||
if (self.session == 0) {
|
||||
if (error) {
|
||||
*error = [NSError errorWithDomain:OSGRimeErrorDomain
|
||||
code:2
|
||||
userInfo:@{NSLocalizedDescriptionKey: @"Unable to create Rime session"}];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)stopSession {
|
||||
if (self.session != 0) {
|
||||
OSGRimeAPI()->destroy_session(self.session);
|
||||
self.session = 0;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)finalizeRuntime {
|
||||
[self stopSession];
|
||||
@synchronized([OSGRimeBridge class]) {
|
||||
if (sInitialized) {
|
||||
OSGRimeAPI()->finalize();
|
||||
sInitialized = NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)deployWithFullCheck:(BOOL)fullCheck error:(NSError **)error {
|
||||
if (![self prepareRuntime:error]) {
|
||||
return NO;
|
||||
}
|
||||
RimeApi_stdbool *api = OSGRimeAPI();
|
||||
Bool started = api->start_maintenance(fullCheck ? True : False);
|
||||
if (started && api->is_maintenance_mode()) {
|
||||
api->join_maintenance_thread();
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)selectSchema:(NSString *)schemaIdentifier {
|
||||
if (![self running]) {
|
||||
return NO;
|
||||
}
|
||||
return OSGRimeAPI()->select_schema(self.session, schemaIdentifier.UTF8String);
|
||||
}
|
||||
|
||||
- (BOOL)setASCIIMode:(BOOL)enabled {
|
||||
if (![self running]) {
|
||||
return NO;
|
||||
}
|
||||
OSGRimeAPI()->set_option(self.session, "ascii_mode", enabled ? True : False);
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)processKeyCode:(int)keyCode modifiers:(int)modifiers {
|
||||
if (![self running]) {
|
||||
return NO;
|
||||
}
|
||||
return OSGRimeAPI()->process_key(self.session, keyCode, modifiers);
|
||||
}
|
||||
|
||||
- (BOOL)selectCandidateAtIndex:(NSInteger)index {
|
||||
if (![self running] || index < 0) {
|
||||
return NO;
|
||||
}
|
||||
return OSGRimeAPI()->select_candidate(self.session, (size_t)index);
|
||||
}
|
||||
|
||||
- (BOOL)commitComposition {
|
||||
if (![self running]) {
|
||||
return NO;
|
||||
}
|
||||
return OSGRimeAPI()->commit_composition(self.session);
|
||||
}
|
||||
|
||||
- (void)clearComposition {
|
||||
if ([self running]) {
|
||||
OSGRimeAPI()->clear_composition(self.session);
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)rawInput {
|
||||
if (![self running]) {
|
||||
return @"";
|
||||
}
|
||||
const char *input = OSGRimeAPI()->get_input(self.session);
|
||||
return input ? [NSString stringWithUTF8String:input] : @"";
|
||||
}
|
||||
|
||||
- (OSGRimeSnapshot *)snapshotWithCandidateLimit:(NSInteger)limit {
|
||||
if (![self running]) {
|
||||
return [[OSGRimeSnapshot alloc] initWithPreedit:@""
|
||||
candidates:@[]
|
||||
commitText:@""
|
||||
composing:NO];
|
||||
}
|
||||
|
||||
RimeApi_stdbool *api = OSGRimeAPI();
|
||||
NSString *commitText = @"";
|
||||
RIME_STRUCT(RimeCommit, commit);
|
||||
if (api->get_commit(self.session, &commit)) {
|
||||
if (commit.text) {
|
||||
commitText = [NSString stringWithUTF8String:commit.text];
|
||||
}
|
||||
api->free_commit(&commit);
|
||||
}
|
||||
|
||||
NSString *preedit = @"";
|
||||
BOOL composing = NO;
|
||||
NSMutableArray<OSGRimeCandidate *> *candidates = [NSMutableArray array];
|
||||
RIME_STRUCT(RimeContext_stdbool, context);
|
||||
if (api->get_context(self.session, &context)) {
|
||||
composing = context.composition.length > 0;
|
||||
if (context.composition.preedit) {
|
||||
preedit = [NSString stringWithUTF8String:context.composition.preedit];
|
||||
}
|
||||
NSInteger count = MIN((NSInteger)context.menu.num_candidates, MAX((NSInteger)0, limit));
|
||||
for (NSInteger index = 0; index < count; index++) {
|
||||
RimeCandidate item = context.menu.candidates[index];
|
||||
NSString *text = item.text ? [NSString stringWithUTF8String:item.text] : @"";
|
||||
NSString *comment = item.comment ? [NSString stringWithUTF8String:item.comment] : @"";
|
||||
[candidates addObject:[[OSGRimeCandidate alloc] initWithText:text comment:comment]];
|
||||
}
|
||||
api->free_context(&context);
|
||||
}
|
||||
|
||||
return [[OSGRimeSnapshot alloc] initWithPreedit:preedit
|
||||
candidates:candidates
|
||||
commitText:commitText
|
||||
composing:composing];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,57 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// Immutable candidate copied out of librime-owned memory.
|
||||
@interface OSGRimeCandidate : NSObject
|
||||
@property(nonatomic, copy, readonly) NSString *text;
|
||||
@property(nonatomic, copy, readonly) NSString *comment;
|
||||
- (instancetype)initWithText:(NSString *)text comment:(NSString *)comment;
|
||||
@end
|
||||
|
||||
/// Immutable runtime snapshot consumed by SwiftUI.
|
||||
@interface OSGRimeSnapshot : NSObject
|
||||
@property(nonatomic, copy, readonly) NSString *preedit;
|
||||
@property(nonatomic, copy, readonly) NSArray<OSGRimeCandidate *> *candidates;
|
||||
@property(nonatomic, copy, readonly) NSString *commitText;
|
||||
@property(nonatomic, readonly) BOOL composing;
|
||||
- (instancetype)initWithPreedit:(NSString *)preedit
|
||||
candidates:(NSArray<OSGRimeCandidate *> *)candidates
|
||||
commitText:(NSString *)commitText
|
||||
composing:(BOOL)composing;
|
||||
@end
|
||||
|
||||
/// Minimal Objective-C++ façade over librime's C API.
|
||||
///
|
||||
/// Callers must serialize access. A bridge owns one session; setup and
|
||||
/// initialization are process-global inside librime.
|
||||
@interface OSGRimeBridge : NSObject
|
||||
|
||||
@property(nonatomic, readonly) BOOL running;
|
||||
|
||||
- (instancetype)initWithSharedDataDirectory:(NSString *)sharedDataDirectory
|
||||
userDataDirectory:(NSString *)userDataDirectory
|
||||
distributionVersion:(NSString *)distributionVersion;
|
||||
|
||||
- (BOOL)start:(NSError * _Nullable * _Nullable)error;
|
||||
- (void)stopSession;
|
||||
- (void)finalizeRuntime;
|
||||
- (BOOL)deployWithFullCheck:(BOOL)fullCheck
|
||||
error:(NSError * _Nullable * _Nullable)error;
|
||||
|
||||
- (BOOL)selectSchema:(NSString *)schemaIdentifier;
|
||||
- (BOOL)setASCIIMode:(BOOL)enabled;
|
||||
- (BOOL)processKeyCode:(int)keyCode modifiers:(int)modifiers;
|
||||
- (BOOL)selectCandidateAtIndex:(NSInteger)index;
|
||||
- (BOOL)commitComposition;
|
||||
- (void)clearComposition;
|
||||
- (NSString *)rawInput;
|
||||
- (OSGRimeSnapshot *)snapshotWithCandidateLimit:(NSInteger)limit;
|
||||
|
||||
@end
|
||||
|
||||
/// X11-compatible key symbols used by librime.
|
||||
FOUNDATION_EXPORT const int OSGRimeKeyBackSpace;
|
||||
FOUNDATION_EXPORT const int OSGRimeKeyReturn;
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Reference in New Issue
Block a user