Implements adding phrase from shift and arrow keys.
This commit is contained in:
parent
358462dff1
commit
6f761ecbcd
|
@ -37,6 +37,7 @@
|
||||||
#import "PreferencesWindowController.h"
|
#import "PreferencesWindowController.h"
|
||||||
|
|
||||||
extern void LTLoadLanguageModel(void);
|
extern void LTLoadLanguageModel(void);
|
||||||
|
extern void LTLoadUserLanguageModelFile(void);
|
||||||
|
|
||||||
static NSString *kCheckUpdateAutomatically = @"CheckUpdateAutomatically";
|
static NSString *kCheckUpdateAutomatically = @"CheckUpdateAutomatically";
|
||||||
static NSString *kNextUpdateCheckDateKey = @"NextUpdateCheckDate";
|
static NSString *kNextUpdateCheckDateKey = @"NextUpdateCheckDate";
|
||||||
|
@ -60,6 +61,7 @@ static const NSTimeInterval kTimeoutInterval = 60.0;
|
||||||
- (void)applicationDidFinishLaunching:(NSNotification *)inNotification
|
- (void)applicationDidFinishLaunching:(NSNotification *)inNotification
|
||||||
{
|
{
|
||||||
LTLoadLanguageModel();
|
LTLoadLanguageModel();
|
||||||
|
LTLoadUserLanguageModelFile();
|
||||||
|
|
||||||
if (![[NSUserDefaults standardUserDefaults] objectForKey:kCheckUpdateAutomatically]) {
|
if (![[NSUserDefaults standardUserDefaults] objectForKey:kCheckUpdateAutomatically]) {
|
||||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:kCheckUpdateAutomatically];
|
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:kCheckUpdateAutomatically];
|
||||||
|
|
|
@ -79,14 +79,14 @@ namespace Formosa {
|
||||||
inline BlockReadingBuilder::BlockReadingBuilder(LanguageModel *inLM)
|
inline BlockReadingBuilder::BlockReadingBuilder(LanguageModel *inLM)
|
||||||
: m_LM(inLM)
|
: m_LM(inLM)
|
||||||
, m_cursorIndex(0)
|
, m_cursorIndex(0)
|
||||||
, m_markerCursorIndex(-1)
|
, m_markerCursorIndex(SIZE_MAX)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BlockReadingBuilder::clear()
|
inline void BlockReadingBuilder::clear()
|
||||||
{
|
{
|
||||||
m_cursorIndex = 0;
|
m_cursorIndex = 0;
|
||||||
m_markerCursorIndex = -1;
|
m_markerCursorIndex = SIZE_MAX;
|
||||||
m_readings.clear();
|
m_readings.clear();
|
||||||
m_grid.clear();
|
m_grid.clear();
|
||||||
}
|
}
|
||||||
|
@ -113,6 +113,11 @@ namespace Formosa {
|
||||||
|
|
||||||
inline void BlockReadingBuilder::setMarkerCursorIndex(size_t inNewIndex)
|
inline void BlockReadingBuilder::setMarkerCursorIndex(size_t inNewIndex)
|
||||||
{
|
{
|
||||||
|
if (inNewIndex == SIZE_MAX) {
|
||||||
|
m_markerCursorIndex = SIZE_MAX;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_markerCursorIndex = inNewIndex > m_readings.size() ? m_readings.size() : inNewIndex;
|
m_markerCursorIndex = inNewIndex > m_readings.size() ? m_readings.size() : inNewIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
|
|
||||||
// language model
|
// language model
|
||||||
Formosa::Gramambular::FastLM *_languageModel;
|
Formosa::Gramambular::FastLM *_languageModel;
|
||||||
|
Formosa::Gramambular::FastLM *_userPhrases;
|
||||||
|
|
||||||
// the grid (lattice) builder for the unigrams (and bigrams)
|
// the grid (lattice) builder for the unigrams (and bigrams)
|
||||||
Formosa::Gramambular::BlockReadingBuilder* _builder;
|
Formosa::Gramambular::BlockReadingBuilder* _builder;
|
||||||
|
@ -80,3 +81,4 @@
|
||||||
|
|
||||||
// the shared language model object
|
// the shared language model object
|
||||||
extern "C" void LTLoadLanguageModel();
|
extern "C" void LTLoadLanguageModel();
|
||||||
|
extern "C" void LTLoadUserLanguageModelFile();
|
||||||
|
|
|
@ -116,6 +116,21 @@ FastLM gLanguageModel;
|
||||||
FastLM gLanguageModelPlainBopomofo;
|
FastLM gLanguageModelPlainBopomofo;
|
||||||
FastLM gUserPhraseLanguageModel;
|
FastLM gUserPhraseLanguageModel;
|
||||||
|
|
||||||
|
static NSString *userDataFolderPath()
|
||||||
|
{
|
||||||
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDirectory, YES);
|
||||||
|
NSString *appSupportPath = [paths objectAtIndex:0];
|
||||||
|
NSString *userDictPath = [appSupportPath stringByAppendingPathComponent:@"McBopomofo"];
|
||||||
|
return userDictPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NSString *userPhrasesDataPath()
|
||||||
|
{
|
||||||
|
return [userDataFolderPath() stringByAppendingPathComponent:@"data.txt"];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const int kUserOverrideModelCapacity = 500;
|
static const int kUserOverrideModelCapacity = 500;
|
||||||
static const double kObservedOverrideHalflife = 5400.0; // 1.5 hr.
|
static const double kObservedOverrideHalflife = 5400.0; // 1.5 hr.
|
||||||
McBopomofo::UserOverrideModel gUserOverrideModel(kUserOverrideModelCapacity, kObservedOverrideHalflife);
|
McBopomofo::UserOverrideModel gUserOverrideModel(kUserOverrideModelCapacity, kObservedOverrideHalflife);
|
||||||
|
@ -132,9 +147,7 @@ static inline NSString *LocalizationNotNeeded(NSString *s) {
|
||||||
+ (VTVerticalCandidateController *)verticalCandidateController;
|
+ (VTVerticalCandidateController *)verticalCandidateController;
|
||||||
|
|
||||||
- (void)collectCandidates;
|
- (void)collectCandidates;
|
||||||
|
|
||||||
- (size_t)actualCandidateCursorIndex;
|
- (size_t)actualCandidateCursorIndex;
|
||||||
|
|
||||||
- (void)_showCandidateWindowUsingVerticalMode:(BOOL)useVerticalMode client:(id)client;
|
- (void)_showCandidateWindowUsingVerticalMode:(BOOL)useVerticalMode client:(id)client;
|
||||||
|
|
||||||
- (void)beep;
|
- (void)beep;
|
||||||
|
@ -221,6 +234,9 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
chineseConversionMenuItem.state = _chineseConversionEnabled ? NSControlStateValueOn : NSControlStateValueOff;
|
chineseConversionMenuItem.state = _chineseConversionEnabled ? NSControlStateValueOn : NSControlStateValueOff;
|
||||||
[menu addItem:chineseConversionMenuItem];
|
[menu addItem:chineseConversionMenuItem];
|
||||||
|
|
||||||
|
NSMenuItem *editUserPhraseItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Edit User Phrases", @"") action:@selector(openUserPhrases:) keyEquivalent:@""];
|
||||||
|
[menu addItem:editUserPhraseItem];
|
||||||
|
|
||||||
NSMenuItem *updateCheckItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Check for Updates…", @"") action:@selector(checkForUpdate:) keyEquivalent:@""];
|
NSMenuItem *updateCheckItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Check for Updates…", @"") action:@selector(checkForUpdate:) keyEquivalent:@""];
|
||||||
[menu addItem:updateCheckItem];
|
[menu addItem:updateCheckItem];
|
||||||
|
|
||||||
|
@ -393,6 +409,9 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
[_candidates removeAllObjects];
|
[_candidates removeAllObjects];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_INLINE size_t min(size_t a, size_t b) { return a < b ? a : b; }
|
||||||
|
NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
|
|
||||||
// TODO: bug #28 is more likely to live in this method.
|
// TODO: bug #28 is more likely to live in this method.
|
||||||
- (void)updateClientComposingBuffer:(id)client
|
- (void)updateClientComposingBuffer:(id)client
|
||||||
{
|
{
|
||||||
|
@ -446,33 +465,39 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
NSString *composedText = [head stringByAppendingString:[reading stringByAppendingString:tail]];
|
NSString *composedText = [head stringByAppendingString:[reading stringByAppendingString:tail]];
|
||||||
NSInteger cursorIndex = composedStringCursorIndex + [reading length];
|
NSInteger cursorIndex = composedStringCursorIndex + [reading length];
|
||||||
|
|
||||||
// we must use NSAttributedString so that the cursor is visible --
|
if (_bpmfReadingBuffer->isEmpty() && _builder->markerCursorIndex() != SIZE_MAX) {
|
||||||
// can't just use NSString
|
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:composedText];
|
||||||
NSDictionary *attrDict = @{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle),
|
size_t begin = min(_builder->markerCursorIndex(), _builder->cursorIndex());
|
||||||
NSMarkedClauseSegmentAttributeName: @0};
|
size_t end = max(_builder->markerCursorIndex(), _builder->cursorIndex());
|
||||||
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:composedText attributes:attrDict];
|
[attrString setAttributes:@{
|
||||||
|
NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle),
|
||||||
|
NSMarkedClauseSegmentAttributeName: @0
|
||||||
|
} range:NSMakeRange(0, begin)];
|
||||||
|
[attrString setAttributes:@{
|
||||||
|
NSUnderlineStyleAttributeName: @(NSUnderlineStyleThick),
|
||||||
|
NSMarkedClauseSegmentAttributeName: @1
|
||||||
|
} range:NSMakeRange(begin, end - begin)];
|
||||||
|
[attrString setAttributes:@{
|
||||||
|
NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle),
|
||||||
|
NSMarkedClauseSegmentAttributeName: @2
|
||||||
|
} range:NSMakeRange(end, [composedText length] - end)];
|
||||||
|
NSLog(@"marked %@", [self _currentMarkedText]);
|
||||||
|
NSLog(@"attrString %@", attrString);
|
||||||
|
[client setMarkedText:attrString selectionRange:NSMakeRange((NSInteger)_builder->markerCursorIndex(), 0) replacementRange:NSMakeRange(NSNotFound, NSNotFound)];
|
||||||
|
_latestReadingCursor = (NSInteger)_builder->markerCursorIndex();
|
||||||
|
|
||||||
if (_bpmfReadingBuffer->isEmpty() && _builder->markerCursorIndex() != -1) {
|
} else {
|
||||||
NSInteger begin = 0;
|
// we must use NSAttributedString so that the cursor is visible --
|
||||||
NSInteger end = 0;
|
// can't just use NSString
|
||||||
if (_builder->markerCursorIndex() > _builder->cursorIndex()) {
|
NSDictionary *attrDict = @{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle),
|
||||||
begin = _builder->cursorIndex();
|
|
||||||
end = _builder->markerCursorIndex();
|
|
||||||
} else {
|
|
||||||
end = _builder->cursorIndex();
|
|
||||||
begin = _builder->markerCursorIndex();
|
|
||||||
}
|
|
||||||
NSRange range = NSMakeRange(begin, end - begin);
|
|
||||||
NSDictionary *highlightAttrDict = @{NSUnderlineStyleAttributeName: @(NSUnderlineStyleDouble),
|
|
||||||
NSMarkedClauseSegmentAttributeName: @0};
|
NSMarkedClauseSegmentAttributeName: @0};
|
||||||
[attrString addAttributes:highlightAttrDict range:range];
|
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:composedText attributes:attrDict];
|
||||||
|
|
||||||
|
// the selection range is where the cursor is, with the length being 0 and replacement range NSNotFound,
|
||||||
|
// i.e. the client app needs to take care of where to put ths composing buffer
|
||||||
|
[client setMarkedText:attrString selectionRange:NSMakeRange(cursorIndex, 0) replacementRange:NSMakeRange(NSNotFound, NSNotFound)];
|
||||||
|
_latestReadingCursor = cursorIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the selection range is where the cursor is, with the length being 0 and replacement range NSNotFound,
|
|
||||||
// i.e. the client app needs to take care of where to put ths composing buffer
|
|
||||||
[client setMarkedText:attrString selectionRange:NSMakeRange(cursorIndex, 0) replacementRange:NSMakeRange(NSNotFound, NSNotFound)];
|
|
||||||
|
|
||||||
_latestReadingCursor = cursorIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)walk
|
- (void)walk
|
||||||
|
@ -576,25 +601,22 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)_currentHighlighText
|
- (NSString *)_currentMarkedText
|
||||||
{
|
{
|
||||||
if (_builder->markerCursorIndex() == -1) {
|
if (_builder->markerCursorIndex() < 0) {
|
||||||
return @"";
|
return @"";
|
||||||
}
|
}
|
||||||
if (!_bpmfReadingBuffer->isEmpty()) {
|
if (!_bpmfReadingBuffer->isEmpty()) {
|
||||||
return @"";
|
return @"";
|
||||||
}
|
}
|
||||||
|
|
||||||
NSInteger begin = 0;
|
size_t begin = min(_builder->markerCursorIndex(), _builder->cursorIndex());
|
||||||
NSInteger end = 0;
|
size_t end = max(_builder->markerCursorIndex(), _builder->cursorIndex());
|
||||||
if (_builder->markerCursorIndex() > _builder->cursorIndex()) {
|
if (end - begin < 2) {
|
||||||
begin = _builder->cursorIndex();
|
return @"";
|
||||||
end = _builder->markerCursorIndex();
|
|
||||||
} else {
|
|
||||||
end = _builder->cursorIndex();
|
|
||||||
begin = _builder->markerCursorIndex();
|
|
||||||
}
|
}
|
||||||
NSRange range = NSMakeRange(begin, end - begin);
|
|
||||||
|
NSRange range = NSMakeRange((NSInteger)begin, (NSInteger)(end - begin));
|
||||||
NSString *reading = [_composingBuffer substringWithRange:range];
|
NSString *reading = [_composingBuffer substringWithRange:range];
|
||||||
NSMutableString *string = [[NSMutableString alloc] init];
|
NSMutableString *string = [[NSMutableString alloc] init];
|
||||||
[string appendString:reading];
|
[string appendString:reading];
|
||||||
|
@ -611,6 +633,39 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)_writeUserPhrase
|
||||||
|
{
|
||||||
|
NSString *currentMarkedPhrase = [self _currentMarkedText];
|
||||||
|
if (![currentMarkedPhrase length]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
NSString *path = userPhrasesDataPath();
|
||||||
|
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
|
||||||
|
BOOL result = [[@"" dataUsingEncoding:NSUTF8StringEncoding] writeToFile:path atomically:YES];
|
||||||
|
if (result) {
|
||||||
|
NSLog(@"user phrases file is creates");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NSLog(@"failed to create user phrases file");
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSLog(@"About to write %@ into %@", currentMarkedPhrase, path);
|
||||||
|
currentMarkedPhrase = [currentMarkedPhrase stringByAppendingString:@"\n"];
|
||||||
|
NSFileHandle *file = [NSFileHandle fileHandleForUpdatingAtPath:path];
|
||||||
|
NSLog(@"file %@", file);
|
||||||
|
if (!file) {
|
||||||
|
NSLog(@"Failed to write to %@", path);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
[file seekToEndOfFile];
|
||||||
|
NSData *data = [currentMarkedPhrase dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
[file writeData:data];
|
||||||
|
[file closeFile];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)handleInputText:(NSString*)inputText key:(NSInteger)keyCode modifiers:(NSUInteger)flags client:(id)client
|
- (BOOL)handleInputText:(NSString*)inputText key:(NSInteger)keyCode modifiers:(NSUInteger)flags client:(id)client
|
||||||
{
|
{
|
||||||
NSRect textFrame = NSZeroRect;
|
NSRect textFrame = NSZeroRect;
|
||||||
|
@ -651,7 +706,6 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Caps Lock processing : if Caps Lock is on, temporarily disable bopomofo.
|
// Caps Lock processing : if Caps Lock is on, temporarily disable bopomofo.
|
||||||
if (charCode == 8 || charCode == 13 || keyCode == absorbedArrowKey || keyCode == extraChooseCandidateKey || keyCode == cursorForwardKey || keyCode == cursorBackwardKey) {
|
if (charCode == 8 || charCode == 13 || keyCode == absorbedArrowKey || keyCode == extraChooseCandidateKey || keyCode == cursorForwardKey || keyCode == cursorBackwardKey) {
|
||||||
// do nothing if backspace is pressed -- we ignore the key
|
// do nothing if backspace is pressed -- we ignore the key
|
||||||
|
@ -695,6 +749,50 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
return [self handleCandidateEventWithInputText:inputText charCode:charCode keyCode:keyCode];
|
return [self handleCandidateEventWithInputText:inputText charCode:charCode keyCode:keyCode];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we have marker index.
|
||||||
|
if (_builder->markerCursorIndex() != SIZE_MAX) {
|
||||||
|
// ESC
|
||||||
|
if (charCode == 27) {
|
||||||
|
_builder->setMarkerCursorIndex(SIZE_MAX);
|
||||||
|
[self updateClientComposingBuffer:client];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
// Enter
|
||||||
|
if (charCode == 13) {
|
||||||
|
if ([self _writeUserPhrase]) {
|
||||||
|
_builder->setMarkerCursorIndex(SIZE_MAX);
|
||||||
|
} else {
|
||||||
|
[self beep];
|
||||||
|
}
|
||||||
|
[self updateClientComposingBuffer:client];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
// Shift + left
|
||||||
|
if (keyCode == cursorBackwardKey && (flags & NSShiftKeyMask)) {
|
||||||
|
if (_builder->markerCursorIndex() > 0) {
|
||||||
|
_builder->setMarkerCursorIndex(_builder->markerCursorIndex() - 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[self beep];
|
||||||
|
}
|
||||||
|
[self updateClientComposingBuffer:client];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
// Shift + Right
|
||||||
|
if (keyCode == cursorForwardKey && (flags & NSShiftKeyMask)) {
|
||||||
|
if (_builder->markerCursorIndex() < _builder->length()) {
|
||||||
|
_builder->setMarkerCursorIndex(_builder->markerCursorIndex() + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[self beep];
|
||||||
|
}
|
||||||
|
[self updateClientComposingBuffer:client];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
_builder->setMarkerCursorIndex(SIZE_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
// see if it's valid BPMF reading
|
// see if it's valid BPMF reading
|
||||||
if (_bpmfReadingBuffer->isValidKey((char)charCode)) {
|
if (_bpmfReadingBuffer->isValidKey((char)charCode)) {
|
||||||
_bpmfReadingBuffer->combineKey((char)charCode);
|
_bpmfReadingBuffer->combineKey((char)charCode);
|
||||||
|
@ -824,21 +922,11 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & NSShiftKeyMask) {
|
if (flags & NSShiftKeyMask) {
|
||||||
if (_builder->markerCursorIndex() == -1) {
|
if (_builder->cursorIndex() > 0) {
|
||||||
if (_builder->cursorIndex() > 0) {
|
_builder->setMarkerCursorIndex(_builder->cursorIndex() - 1);
|
||||||
_builder->setMarkerCursorIndex(_builder->cursorIndex() - 1);
|
|
||||||
} else {
|
|
||||||
[self beep];
|
|
||||||
}
|
|
||||||
NSString *tmp = [self _currentHighlighText];
|
|
||||||
NSLog(@"%@", tmp);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (_builder->markerCursorIndex() > 0) {
|
[self beep];
|
||||||
_builder->setMarkerCursorIndex(_builder->markerCursorIndex() - 1);
|
|
||||||
} else {
|
|
||||||
[self beep];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_builder->cursorIndex() > 0) {
|
if (_builder->cursorIndex() > 0) {
|
||||||
|
@ -865,23 +953,10 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & NSShiftKeyMask) {
|
if (flags & NSShiftKeyMask) {
|
||||||
if (_builder->markerCursorIndex() == -1) {
|
if (_builder->cursorIndex() < _builder->length()) {
|
||||||
if (_builder->cursorIndex() < _builder->length()) {
|
_builder->setMarkerCursorIndex(_builder->cursorIndex() + 1);
|
||||||
_builder->setMarkerCursorIndex(_builder->cursorIndex() + 1);
|
} else {
|
||||||
} else {
|
[self beep];
|
||||||
[self beep];
|
|
||||||
}
|
|
||||||
NSString *tmp = [self _currentHighlighText];
|
|
||||||
NSLog(@"%@", tmp);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (_builder->markerCursorIndex() < _builder->length()) {
|
|
||||||
_builder->setMarkerCursorIndex(_builder->markerCursorIndex() + 1);
|
|
||||||
} else {
|
|
||||||
[self beep];
|
|
||||||
}
|
|
||||||
NSString *tmp = [self _currentHighlighText];
|
|
||||||
NSLog(@"%@", tmp);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_builder->cursorIndex() < _builder->length()) {
|
if (_builder->cursorIndex() < _builder->length()) {
|
||||||
|
@ -1463,6 +1538,22 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
[(AppDelegate *)[[NSApplication sharedApplication] delegate] checkForUpdateForced:YES];
|
[(AppDelegate *)[[NSApplication sharedApplication] delegate] checkForUpdateForced:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)openUserPhrases:(id)sender
|
||||||
|
{
|
||||||
|
NSString *path = userPhrasesDataPath();
|
||||||
|
NSLog(@"path: %@", path);
|
||||||
|
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
|
||||||
|
[[@"" dataUsingEncoding:NSUTF8StringEncoding] writeToFile:path atomically:YES];
|
||||||
|
}
|
||||||
|
NSURL *url = [NSURL fileURLWithPath:path];
|
||||||
|
[[NSWorkspace sharedWorkspace] openURL:url];
|
||||||
|
// NSWorkspaceOpenConfiguration *config = [NSWorkspaceOpenConfiguration configuration];
|
||||||
|
// [[NSWorkspace sharedWorkspace] openURL:url configuration:config completionHandler:^(NSRunningApplication * app, NSError * error) {
|
||||||
|
// NSLog(@"app %@", app);
|
||||||
|
// NSLog(@"error %@", error);
|
||||||
|
// }];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)showAbout:(id)sender
|
- (void)showAbout:(id)sender
|
||||||
{
|
{
|
||||||
[[NSApplication sharedApplication] orderFrontStandardAboutPanel:sender];
|
[[NSApplication sharedApplication] orderFrontStandardAboutPanel:sender];
|
||||||
|
@ -1511,12 +1602,6 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
static NSString *userDataFolderPath() {
|
|
||||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDirectory, YES);
|
|
||||||
NSString *appSupportPath = [paths objectAtIndex:0];
|
|
||||||
NSString *userDictPath = [appSupportPath stringByAppendingPathComponent:@"McBopomofo"];
|
|
||||||
return userDictPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, FastLM &lm)
|
static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, FastLM &lm)
|
||||||
{
|
{
|
||||||
|
@ -1527,18 +1612,14 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, FastLM &
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LTLoadUserLanguageModelFile(NSString *filenameWithoutExtension, FastLM &lm)
|
|
||||||
{
|
|
||||||
NSString *filename = [filenameWithoutExtension stringByAppendingPathExtension:@"txt"];
|
|
||||||
NSString *dataPath = [userDataFolderPath() stringByAppendingPathComponent:filename];
|
|
||||||
bool result = lm.open([dataPath UTF8String]);
|
|
||||||
if (!result) {
|
|
||||||
NSLog(@"Failed opening language model: %@", dataPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LTLoadLanguageModel()
|
void LTLoadLanguageModel()
|
||||||
{
|
{
|
||||||
LTLoadLanguageModelFile(@"data", gLanguageModel);
|
LTLoadLanguageModelFile(@"data", gLanguageModel);
|
||||||
LTLoadLanguageModelFile(@"data-plain-bpmf", gLanguageModelPlainBopomofo);
|
LTLoadLanguageModelFile(@"data-plain-bpmf", gLanguageModelPlainBopomofo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LTLoadUserLanguageModelFile()
|
||||||
|
{
|
||||||
|
gUserPhraseLanguageModel.close();
|
||||||
|
gUserPhraseLanguageModel.open([userPhrasesDataPath() UTF8String]);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue