Merge pull request #54 from ShikiSuen/upd/1.3.4

v1.3.4 // Maintenance release, fixing certain behaviors with UserPhrases.
This commit is contained in:
Shiki Suen 2022-02-20 23:42:18 +08:00 committed by GitHub
commit 8eaab3da31
55 changed files with 1573 additions and 1411 deletions

View File

@ -67,7 +67,7 @@
<window title="vChewing Installer" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" animationBehavior="default" titlebarAppearsTransparent="YES" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<rect key="contentRect" x="335" y="390" width="533" height="457"/>
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1055"/>
<rect key="screenRect" x="0.0" y="0.0" width="1600" height="875"/>
<value key="minSize" type="size" width="533" height="457"/>
<value key="maxSize" type="size" width="533" height="457"/>
<view key="contentView" id="372">
@ -271,7 +271,6 @@ Gw
<connections>
<outlet property="appCopyrightLabel" destination="03l-rN-zf9" id="XS5-cZ-k9H"/>
<outlet property="appEULAContent" destination="47J-tO-8TZ" id="kRU-X2-8kX"/>
<outlet property="appNameLabel" destination="bzR-Oa-BZa" id="swF-1l-dhS"/>
<outlet property="appVersionLabel" destination="z1m-8k-Z63" id="75X-uy-0Iz"/>
<outlet property="cancelButton" destination="592" id="710"/>
<outlet property="installButton" destination="575" id="709"/>
@ -283,7 +282,7 @@ Gw
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="gHl-Hx-eQn">
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="283" y="305" width="480" height="180"/>
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1055"/>
<rect key="screenRect" x="0.0" y="0.0" width="1600" height="875"/>
<view key="contentView" id="wAe-c8-Vh9">
<rect key="frame" x="0.0" y="0.0" width="480" height="180"/>
<autoresizingMask key="autoresizingMask"/>

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="13150" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13150"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="ShareViewController" customModuleProvider="target">
<connections>
<outlet property="view" destination="1" id="2"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="1">
<rect key="frame" x="0.0" y="0.0" width="388" height="202"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="1uM-r7-H1c">
<rect key="frame" x="302" y="3" width="82" height="32"/>
<buttonCell key="cell" type="push" title="Send" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="2l4-PO-we5">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent">D</string>
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</buttonCell>
<connections>
<action selector="send:" target="-2" id="yic-EC-GGk"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="NVE-vN-dkz">
<rect key="frame" x="224" y="3" width="82" height="32"/>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="60" id="cP1-hK-9ZX"/>
</constraints>
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="6Up-t3-mwm">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
Gw
</string>
</buttonCell>
<connections>
<action selector="cancel:" target="-2" id="Qav-AK-DGt"/>
</connections>
</button>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="aNc-0i-CWK">
<rect key="frame" x="140" y="170" width="108" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="My Service Title" id="0xp-rC-2gr">
<font key="font" metaFont="systemBold"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="4M6-D5-WIf">
<rect key="frame" x="110" y="170" width="22" height="22"/>
<constraints>
<constraint firstAttribute="width" constant="22" id="BOe-aZ-Njc"/>
<constraint firstAttribute="height" constant="22" id="zLg-1a-wlZ"/>
</constraints>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="q3u-Am-ZIA"/>
</imageView>
</subviews>
<constraints>
<constraint firstItem="1uM-r7-H1c" firstAttribute="leading" secondItem="NVE-vN-dkz" secondAttribute="trailing" constant="8" id="1UO-J1-LbJ"/>
<constraint firstItem="NVE-vN-dkz" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="1" secondAttribute="leading" constant="20" symbolic="YES" id="3N9-qo-UfS"/>
<constraint firstAttribute="bottom" secondItem="1uM-r7-H1c" secondAttribute="bottom" constant="10" id="4wH-De-nMF"/>
<constraint firstAttribute="bottom" secondItem="NVE-vN-dkz" secondAttribute="bottom" constant="10" id="USG-Gg-of3"/>
<constraint firstItem="1uM-r7-H1c" firstAttribute="leading" secondItem="NVE-vN-dkz" secondAttribute="trailing" constant="8" id="a8N-vS-Ew9"/>
<constraint firstItem="aNc-0i-CWK" firstAttribute="centerY" secondItem="4M6-D5-WIf" secondAttribute="centerY" constant="2.5" id="ilP-G0-GVG"/>
<constraint firstItem="NVE-vN-dkz" firstAttribute="width" secondItem="1uM-r7-H1c" secondAttribute="width" id="qPo-ky-Fcw"/>
<constraint firstAttribute="trailing" secondItem="1uM-r7-H1c" secondAttribute="trailing" constant="10" id="qfT-cw-QQ2"/>
<constraint firstAttribute="centerX" secondItem="aNc-0i-CWK" secondAttribute="centerX" id="uV3-Wn-RA3"/>
<constraint firstItem="aNc-0i-CWK" firstAttribute="leading" secondItem="4M6-D5-WIf" secondAttribute="trailing" constant="10" id="vFR-5i-Dvo"/>
<constraint firstItem="aNc-0i-CWK" firstAttribute="top" secondItem="1" secondAttribute="top" constant="15" id="vpR-tf-ebx"/>
</constraints>
</customView>
</objects>
</document>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIconFile</key>
<string>icon</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>NSExtensionActivationRule</key>
<dict>
<key>NSExtensionActivationSupportsText</key>
<true/>
</dict>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.share-services</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).ShareViewController</string>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.temporary-exception.mach-register.global-name</key>
<string>org_atelierInmu_inputmethod_vChewing</string>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,41 @@
//
// ShareViewController.swift
// KeyboardExtension
//
// Created by ShikiSuen on 2022/2/20.
//
import Cocoa
class ShareViewController: NSViewController {
override var nibName: NSNib.Name? {
return NSNib.Name("ShareViewController")
}
override func loadView() {
super.loadView()
// Insert code here to customize the view
let item = self.extensionContext!.inputItems[0] as! NSExtensionItem
if let attachments = item.attachments {
NSLog("Attachments = %@", attachments as NSArray)
} else {
NSLog("No Attachments")
}
}
@IBAction func send(_ sender: AnyObject?) {
let outputItem = NSExtensionItem()
// Complete implementation by setting the appropriate value on the output item
let outputItems = [outputItem]
self.extensionContext!.completeRequest(returningItems: outputItems, completionHandler: nil)
}
@IBAction func cancel(_ sender: AnyObject?) {
let cancelError = NSError(domain: NSCocoaErrorDomain, code: NSUserCancelledError, userInfo: nil)
self.extensionContext!.cancelRequest(withError: cancelError)
}
}

BIN
KeyboardExtension/icon.icns Normal file

Binary file not shown.

View File

@ -8,48 +8,48 @@
<string>vChewingKeyLayout</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>KLInfo_Zhuyin Dachen</key>
<key>KLInfo_vChewingDachen</key>
<dict>
<key>TICapsLockLanguageSwitchCapable</key>
<false/>
<key>TISInputSourceID</key>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyindachen</string>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingDachen</string>
<key>TISIntendedLanguage</key>
<string>zh-Hanb</string>
</dict>
<key>KLInfo_Zhuyin ETen</key>
<key>KLInfo_vChewingETen</key>
<dict>
<key>TICapsLockLanguageSwitchCapable</key>
<false/>
<key>TISInputSourceID</key>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyineten</string>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingETen</string>
<key>TISIntendedLanguage</key>
<string>zh-Hanb</string>
</dict>
<key>KLInfo_Zhuyin IBM</key>
<key>KLInfo_vChewingIBM</key>
<dict>
<key>TICapsLockLanguageSwitchCapable</key>
<false/>
<key>TISInputSourceID</key>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyinibm</string>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingIBM</string>
<key>TISIntendedLanguage</key>
<string>zh-Hanb</string>
</dict>
<key>KLInfo_Zhuyin MiTAC</key>
<key>KLInfo_vChewingMiTAC</key>
<dict>
<key>TICapsLockLanguageSwitchCapable</key>
<false/>
<key>TISInputSourceID</key>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyinmitac</string>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingMiTAC</string>
<key>TISIntendedLanguage</key>
<string>zh-Hanb</string>
</dict>
<key>KLInfo_Zhuyin Seigyou</key>
<key>KLInfo_vChewingSeigyou</key>
<dict>
<key>TICapsLockLanguageSwitchCapable</key>
<false/>
<key>TISInputSourceID</key>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyinseigyou</string>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingSeigyou</string>
<key>TISIntendedLanguage</key>
<string>zh-Hanb</string>
</dict>

View File

@ -1,7 +1,7 @@
<?xml version="1.1" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd">
<!--Last edited by Ukelele version 351 on 2022-02-14 at 17:15 (GMT+8)-->
<keyboard group="126" id="-1524" name="Zhuyin Dachen" maxout="1">
<keyboard group="126" id="-1524" name="vChewing Dachen" maxout="1">
<layouts>
<layout first="0" last="17" mapSet="16c" modifiers="f4"/>
<layout first="18" last="18" mapSet="a88" modifiers="f4"/>

View File

@ -1,7 +1,7 @@
<?xml version="1.1" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd">
<!--Last edited by Ukelele version 351 on 2022-02-14 at 17:29 (GMT+8)-->
<keyboard group="126" id="-2369" name="Zhuyin ETen" maxout="1">
<keyboard group="126" id="-2369" name="vChewing ETen" maxout="1">
<layouts>
<layout first="0" last="17" mapSet="16c" modifiers="f4"/>
<layout first="18" last="18" mapSet="a88" modifiers="f4"/>

View File

@ -1,7 +1,7 @@
<?xml version="1.1" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd">
<!--Last edited by Ukelele version 351 on 2022-02-14 at 17:36 (GMT+8)-->
<keyboard group="126" id="-28630" name="Zhuyin IBM" maxout="1">
<keyboard group="126" id="-28630" name="vChewing IBM" maxout="1">
<layouts>
<layout first="0" last="17" mapSet="16c" modifiers="f4"/>
<layout first="18" last="18" mapSet="a88" modifiers="f4"/>

View File

@ -1,7 +1,7 @@
<?xml version="1.1" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd">
<!--Last edited by Ukelele version 351 on 2022-02-14 at 17:15 (GMT+8)-->
<keyboard group="126" id="-7969" name="Zhuyin MiTAC" maxout="1">
<keyboard group="126" id="-7969" name="vChewing MiTAC" maxout="1">
<layouts>
<layout first="0" last="17" mapSet="16c" modifiers="f4"/>
<layout first="18" last="18" mapSet="a88" modifiers="f4"/>

View File

@ -1,7 +1,7 @@
<?xml version="1.1" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd">
<!--Last edited by Ukelele version 351 on 2022-02-14 at 17:40 (GMT+8)-->
<keyboard group="126" id="-17519" name="Zhuyin Seigyou" maxout="1">
<keyboard group="126" id="-17519" name="vChewing Seigyou" maxout="1">
<layouts>
<layout first="0" last="17" mapSet="16c" modifiers="f4"/>
<layout first="18" last="18" mapSet="a88" modifiers="f4"/>

@ -1 +1 @@
Subproject commit 36a71ee9d2e58611cd8466a1908f0a30274e261e
Subproject commit 6dc73cd3edd47c85089db8f58e92f0c821e67ed6

View File

@ -142,8 +142,8 @@ struct VersionUpdateApi {
@objc(AppDelegate)
class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelegate, FSEventStreamHelperDelegate {
func helper(_ helper: FSEventStreamHelper, didReceive events: [FSEventStreamHelper.Event]) {
// 使使
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
// 100ms 使使
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) {
if Preferences.shouldAutoReloadUserDataFiles {
mgrLangModel.loadUserPhrases()
mgrLangModel.loadUserPhraseReplacement()
@ -159,7 +159,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega
private var ctlAboutWindowInstance: ctlAboutWindow? // New About Window
private var checkTask: URLSessionTask?
private var updateNextStepURL: URL?
private var fsStreamHelper = FSEventStreamHelper(path: mgrLangModel.dataFolderPath, queue: DispatchQueue(label: "User Phrases"))
private var fsStreamHelper = FSEventStreamHelper(path: mgrLangModel.dataFolderPath, queue: DispatchQueue(label: "vChewing User Phrases"))
// dealloc
deinit {

View File

@ -182,9 +182,9 @@ class InputState: NSObject {
let (exactEnd, _) = (composingBuffer as NSString).characterIndex(from: markedRange.location + markedRange.length)
let selectedReadings = readings[exactBegin..<exactEnd]
let joined = selectedReadings.joined(separator: "-")
let exist = mgrLangModel.checkIfExist(userPhrase: text, key: joined)
let exist = mgrLangModel.checkIfUserPhraseExist(userPhrase: text, mode: ctlInputMethod.currentKeyHandler.inputMode, key: joined)
if exist {
return String(format: NSLocalizedString("\"%@\" already exists.", comment: ""), text)
return String(format: NSLocalizedString("\"%@\" already exists, ENTER to boost its priority.", comment: ""), text)
}
return String(format: NSLocalizedString("\"%@\" selected. ENTER to add user phrase.", comment: ""), text)
@ -246,12 +246,16 @@ class InputState: NSObject {
if markedRange.length > kMaxMarkRangeLength {
return false
}
return markedRange.length >= kMinMarkRangeLength && markedRange.length <= kMaxMarkRangeLength
}
@objc var chkIfUserPhraseExists: Bool {
let text = (composingBuffer as NSString).substring(with: markedRange)
let (exactBegin, _) = (composingBuffer as NSString).characterIndex(from: markedRange.location)
let (exactEnd, _) = (composingBuffer as NSString).characterIndex(from: markedRange.location + markedRange.length)
let selectedReadings = readings[exactBegin..<exactEnd]
let joined = selectedReadings.joined(separator: "-")
return mgrLangModel.checkIfExist(userPhrase: text, key: joined) == false
return mgrLangModel.checkIfUserPhraseExist(userPhrase: text, mode: ctlInputMethod.currentKeyHandler.inputMode, key: joined) == true
}
@objc var userPhrase: String {

View File

@ -17,28 +17,23 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#import "Mandarin.h"
#import "Gramambular.h"
#import "vChewingLM.h"
#import "UserOverrideModel.h"
#import "mgrLangModel_Privates.h"
#import "KeyHandler.h"
#import "LMInstantiator.h"
#import "Mandarin.h"
#import "mgrLangModel_Privates.h"
#import "UserOverrideModel.h"
#import "vChewing-Swift.h"
#import <string>
// C++ namespace usages
using namespace std;
using namespace Taiyan::Mandarin;
using namespace Taiyan::Gramambular;
using namespace vChewing;
InputMode imeModeCHT = @"org.atelierInmu.inputmethod.vChewing.IMECHT";
InputMode imeModeCHS = @"org.atelierInmu.inputmethod.vChewing.IMECHS";
InputMode imeModeNULL = @"org.atelierInmu.inputmethod.vChewing.IMENULL";
static const double kEpsilon = 0.000001;
static double FindHighestScore(const vector<NodeAnchor> &nodes, double epsilon) {
static double FindHighestScore(const std::vector<Taiyan::Gramambular::NodeAnchor> &nodes, double epsilon) {
double highestScore = 0.0;
for (auto ni = nodes.begin(), ne = nodes.end(); ni != ne; ++ni) {
double score = ni->node->highestUnigramScore();
@ -49,16 +44,15 @@ static double FindHighestScore(const vector<NodeAnchor> &nodes, double epsilon)
return highestScore + epsilon;
}
// sort helper
class NodeAnchorDescendingSorter
{
class NodeAnchorDescendingSorter {
public:
bool operator()(const NodeAnchor &a, const NodeAnchor &b) const {
bool operator()(const Taiyan::Gramambular::NodeAnchor &a, const Taiyan::Gramambular::NodeAnchor &b) const
{
return a.node->key().length() > b.node->key().length();
}
};
// if DEBUG is defined, a DOT file (GraphViz format) will be written to the
;// if DEBUG is defined, a DOT file (GraphViz format) will be written to the
// specified path every time the grid is walked
#if DEBUG
static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
@ -71,7 +65,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
Taiyan::Mandarin::BopomofoReadingBuffer *_bpmfReadingBuffer;
// language model
vChewing::vChewingLM *_languageModel;
vChewing::LMInstantiator *_languageModel;
// user override model
vChewing::UserOverrideModel *_userOverrideModel;
@ -96,8 +90,8 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
- (void)setInputMode:(NSString *)value
{
NSString *newInputMode;
vChewingLM *newLanguageModel;
UserOverrideModel *newUserOverrideModel;
vChewing::LMInstantiator *newLanguageModel;
vChewing::UserOverrideModel *newUserOverrideModel;
if ([value isKindOfClass:[NSString class]] && [value isEqual:imeModeCHS]) {
newInputMode = imeModeCHS;
@ -120,7 +114,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
if (_builder) {
delete _builder;
_builder = new BlockReadingBuilder(_languageModel);
_builder = new Taiyan::Gramambular::BlockReadingBuilder(_languageModel);
_builder->setJoinSeparator("-");
}
@ -146,7 +140,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
{
self = [super init];
if (self) {
_bpmfReadingBuffer = new BopomofoReadingBuffer(BopomofoKeyboardLayout::StandardLayout());
_bpmfReadingBuffer = new Taiyan::Mandarin::BopomofoReadingBuffer(Taiyan::Mandarin::BopomofoKeyboardLayout::StandardLayout());
// create the lattice builder
_languageModel = [mgrLangModel lmCHT];
@ -154,7 +148,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
_languageModel->setCNSEnabled(Preferences.cns11643Enabled);
_userOverrideModel = [mgrLangModel userOverrideModelCHT];
_builder = new BlockReadingBuilder(_languageModel);
_builder = new Taiyan::Gramambular::BlockReadingBuilder(_languageModel);
// each Mandarin syllable is separated by a hyphen
_builder->setJoinSeparator("-");
@ -168,31 +162,31 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
NSInteger layout = Preferences.keyboardLayout;
switch (layout) {
case KeyboardLayoutStandard:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::StandardLayout());
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::StandardLayout());
break;
case KeyboardLayoutEten:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::ETenLayout());
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::ETenLayout());
break;
case KeyboardLayoutHsu:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::HsuLayout());
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::HsuLayout());
break;
case KeyboardLayoutEten26:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::ETen26Layout());
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::ETen26Layout());
break;
case KeyboardLayoutIBM:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::IBMLayout());
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::IBMLayout());
break;
case KeyboardLayoutMiTAC:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::MiTACLayout());
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::MiTACLayout());
break;
case KeyboardLayoutFakeSeigyou:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::FakeSeigyouLayout());
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::FakeSeigyouLayout());
break;
case KeyboardLayoutHanyuPinyin:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::HanyuPinyinLayout());
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::HanyuPinyinLayout());
break;
default:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::StandardLayout());
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::StandardLayout());
Preferences.keyboardLayout = KeyboardLayoutStandard;
}
}
@ -200,8 +194,8 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
- (void)fixNodeWithValue:(NSString *)value
{
size_t cursorIndex = [self _actualCandidateCursorIndex];
string stringValue = [value UTF8String];
NodeAnchor selectedNode = _builder->grid().fixNodeSelectedCandidate(cursorIndex, stringValue);
std::string stringValue(value.UTF8String);
Taiyan::Gramambular::NodeAnchor selectedNode = _builder->grid().fixNodeSelectedCandidate(cursorIndex, stringValue);
if (!Preferences.useSCPCTypingMode) { // 不要針對逐字選字模式啟用臨時半衰記憶模型。
// If the length of the readings and the characters do not match,
// it often means it is a special symbol and it should not be stored
@ -234,10 +228,10 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
_walkedNodes.clear();
}
- (string)_currentLayout
- (std::string)_currentLayout
{
NSString *keyboardLayoutName = Preferences.keyboardLayoutName;
string layout = string(keyboardLayoutName.UTF8String) + string("_");
std::string layout = std::string(keyboardLayoutName.UTF8String) + std::string("_");
return layout;
}
@ -348,7 +342,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
composeReading |= (!_bpmfReadingBuffer->isEmpty() && ([input isSpace] || [input isEnterCharCode] || [input isEnter]));
if (composeReading) {
// combine the reading
string reading = _bpmfReadingBuffer->syllable().composedString();
std::string reading = _bpmfReadingBuffer->syllable().composedString();
// see if we have a unigram for this
if (!_languageModel->hasUnigramsForKey(reading)) {
@ -365,12 +359,12 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
NSString *poppedText = [self _popOverflowComposingTextAndWalk];
// get user override model suggestion
string overrideValue = (Preferences.useSCPCTypingMode) ? "" :
std::string overrideValue = (Preferences.useSCPCTypingMode) ? "" :
_userOverrideModel->suggest(_walkedNodes, _builder->cursorIndex(), [[NSDate date] timeIntervalSince1970]);
if (!overrideValue.empty()) {
size_t cursorIndex = [self _actualCandidateCursorIndex];
vector<NodeAnchor> nodes = _builder->grid().nodesCrossingOrEndingAt(cursorIndex);
std::vector<Taiyan::Gramambular::NodeAnchor> nodes = _builder->grid().nodesCrossingOrEndingAt(cursorIndex);
double highestScore = FindHighestScore(nodes, kEpsilon);
_builder->grid().overrideNodeScoreForSelectedCandidate(cursorIndex, overrideValue, static_cast<float>(highestScore));
}
@ -411,13 +405,13 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
return YES;
}
// MARK: Space and Down, plus PageUp / PageDn / PageLeft / PageRight.
// keyCode 125 = Down, charCode 32 = Space
if (_bpmfReadingBuffer->isEmpty() &&
[state isKindOfClass:[InputStateNotEmpty class]] &&
([input isExtraChooseCandidateKey] || [input isExtraChooseCandidateKeyReverse]
// MARK: Space and Down, plus PageUp / PageDn / PageLeft / PageRight.
// keyCode 125 = Down, charCode 32 = Space
if (_bpmfReadingBuffer->isEmpty() &&
[state isKindOfClass:[InputStateNotEmpty class]] &&
([input isExtraChooseCandidateKey] || [input isExtraChooseCandidateKeyReverse]
|| [input isSpace] || [input isPageDown] || [input isPageUp]
|| (input.useVerticalMode && ([input isVerticalModeOnlyChooseCandidateKey])))) {
|| (input.useVerticalMode && ([input isVerticalModeOnlyChooseCandidateKey])))) {
if ([input isSpace]) {
// if the spacebar is NOT set to be a selection key
if ([input isShiftHold] || !Preferences.chooseCandidateUsingSpace) {
@ -521,7 +515,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
InputStateSymbolTable *symbolState = [[InputStateSymbolTable alloc] initWithNode:root useVerticalMode:input.useVerticalMode];
stateCallback(symbolState);
return YES;
// if (_languageModel->hasUnigramsForKey(string("_punctuation_list"))) {
// if (_languageModel->hasUnigramsForKey("_punctuation_list"))) {
// if (_bpmfReadingBuffer->isEmpty()) {
// _builder->insertReadingAtCursor(string("_punctuation_list"));
// NSString *poppedText = [self _popOverflowComposingTextAndWalk];
@ -540,28 +534,30 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
// MARK: Punctuation
// if nothing is matched, see if it's a punctuation key for current layout.
string punctuationNamePrefix;
std::string punctuationNamePrefix;
if ([input isControlHold]) {
punctuationNamePrefix = string("_ctrl_punctuation_");
punctuationNamePrefix = std::string("_ctrl_punctuation_");
} else if (Preferences.halfWidthPunctuationEnabled) {
punctuationNamePrefix = string("_half_punctuation_");
punctuationNamePrefix = std::string("_half_punctuation_");
} else {
punctuationNamePrefix = string("_punctuation_");
punctuationNamePrefix = std::string("_punctuation_");
}
string layout = [self _currentLayout];
string customPunctuation = punctuationNamePrefix + layout + string(1, (char) charCode);
std::string layout = [self _currentLayout];
std::string customPunctuation = punctuationNamePrefix + layout + std::string(1, (char) charCode);
if ([self _handlePunctuation:customPunctuation state:state usingVerticalMode:input.useVerticalMode stateCallback:stateCallback errorCallback:errorCallback]) {
return YES;
}
// if nothing is matched, see if it's a punctuation key.
string punctuation = punctuationNamePrefix + string(1, (char) charCode);
std::string punctuation = punctuationNamePrefix + std::string(1, (char) charCode);
if ([self _handlePunctuation:punctuation state:state usingVerticalMode:input.useVerticalMode stateCallback:stateCallback errorCallback:errorCallback]) {
return YES;
}
if ((char) charCode >= 'A' && (char) charCode <= 'Z') {
string letter = string("_letter_") + string(1, (char) charCode);
// Lukhnos 這裡的處理反而會使得 Apple 倚天注音動態鍵盤佈局「敲不了半形大寫英文」的缺點曝露無疑,所以注釋掉。
// 至於他試圖用這種處理來解決的上游 UPR293 的問題,其實針對詞庫檔案的排序做點手腳就可以解決。威注音本來也就是這麼做的。
if (/*[state isKindOfClass:[InputStateNotEmpty class]] && */(char) charCode >= 'A' && (char) charCode <= 'Z') {
std::string letter = std::string("_letter_") + std::string(1, (char) charCode);
if ([self _handlePunctuation:letter state:state usingVerticalMode:input.useVerticalMode stateCallback:stateCallback errorCallback:errorCallback]) {
return YES;
}
@ -845,7 +841,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
return YES;
}
- (BOOL)_handlePunctuation:(string)customPunctuation state:(InputState *)state usingVerticalMode:(BOOL)useVerticalMode stateCallback:(void (^)(InputState *))stateCallback errorCallback:(void (^)(void))errorCallback
- (BOOL)_handlePunctuation:(std::string)customPunctuation state:(InputState *)state usingVerticalMode:(BOOL)useVerticalMode stateCallback:(void (^)(InputState *))stateCallback errorCallback:(void (^)(void))errorCallback
{
if (!_languageModel->hasUnigramsForKey(customPunctuation)) {
return NO;
@ -1150,23 +1146,23 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
}
if (Preferences.useSCPCTypingMode) {
string layout = [self _currentLayout];
string punctuationNamePrefix;
std::string layout = [self _currentLayout];
std::string punctuationNamePrefix;
if ([input isControlHold]) {
punctuationNamePrefix = string("_ctrl_punctuation_");
punctuationNamePrefix = std::string("_ctrl_punctuation_");
} else if (Preferences.halfWidthPunctuationEnabled) {
punctuationNamePrefix = string("_half_punctuation_");
punctuationNamePrefix = std::string("_half_punctuation_");
} else {
punctuationNamePrefix = string("_punctuation_");
punctuationNamePrefix = std::string("_punctuation_");
}
string customPunctuation = punctuationNamePrefix + layout + string(1, (char) charCode);
string punctuation = punctuationNamePrefix + string(1, (char) charCode);
std::string customPunctuation = punctuationNamePrefix + layout + std::string(1, (char) charCode);
std::string punctuation = punctuationNamePrefix + std::string(1, (char) charCode);
BOOL shouldAutoSelectCandidate = _bpmfReadingBuffer->isValidKey((char) charCode) || _languageModel->hasUnigramsForKey(customPunctuation) ||
_languageModel->hasUnigramsForKey(punctuation);
if (!shouldAutoSelectCandidate && (char) charCode >= 'A' && (char) charCode <= 'Z') {
string letter = string("_letter_") + string(1, (char) charCode);
std::string letter = std::string("_letter_") + std::string(1, (char) charCode);
if (_languageModel->hasUnigramsForKey(letter)) {
shouldAutoSelectCandidate = YES;
}
@ -1206,9 +1202,9 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
// we must do some Unicode codepoint counting to find the actual cursor location for the client
// i.e. we need to take UTF-16 into consideration, for which a surrogate pair takes 2 UniChars
// locations
for (vector<NodeAnchor>::iterator wi = _walkedNodes.begin(), we = _walkedNodes.end(); wi != we; ++wi) {
for (std::vector<Taiyan::Gramambular::NodeAnchor>::iterator wi = _walkedNodes.begin(), we = _walkedNodes.end(); wi != we; ++wi) {
if ((*wi).node) {
string nodeStr = (*wi).node->currentKeyValue().value;
std::string nodeStr = (*wi).node->currentKeyValue().value;
NSString *valueString = [NSString stringWithUTF8String:nodeStr.c_str()];
[composingBuffer appendString:valueString];
@ -1274,7 +1270,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
// retrieve the most likely trellis, i.e. a Maximum Likelihood Estimation
// of the best possible Mandarain characters given the input syllables,
// using the Viterbi algorithm implemented in the Gramambular library
Walker walker(&_builder->grid());
Taiyan::Gramambular::Walker walker(&_builder->grid());
// the reverse walk traces the trellis from the end
_walkedNodes = walker.reverseWalk(_builder->grid().width());
@ -1284,7 +1280,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
// if DEBUG is defined, a GraphViz file is written to kGraphVizOutputfile
#if DEBUG
string dotDump = _builder->grid().dumpDOT();
std::string dotDump = _builder->grid().dumpDOT();
NSString *dotStr = [NSString stringWithUTF8String:dotDump.c_str()];
NSError *error = nil;
@ -1307,7 +1303,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
if (_builder->grid().width() > (size_t) composingBufferSize) {
if (_walkedNodes.size() > 0) {
NodeAnchor &anchor = _walkedNodes[0];
Taiyan::Gramambular::NodeAnchor &anchor = _walkedNodes[0];
poppedText = [NSString stringWithUTF8String:anchor.node->currentKeyValue().value.c_str()];
_builder->removeHeadReadings(anchor.spanningLength);
}
@ -1322,15 +1318,15 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
NSMutableArray *candidatesArray = [[NSMutableArray alloc] init];
size_t cursorIndex = [self _actualCandidateCursorIndex];
vector<NodeAnchor> nodes = _builder->grid().nodesCrossingOrEndingAt(cursorIndex);
std::vector<Taiyan::Gramambular::NodeAnchor> nodes = _builder->grid().nodesCrossingOrEndingAt(cursorIndex);
// sort the nodes, so that longer nodes (representing longer phrases) are placed at the top of the candidate list
stable_sort(nodes.begin(), nodes.end(), NodeAnchorDescendingSorter());
// then use the C++ trick to retrieve the candidates for each node at/crossing the cursor
for (vector<NodeAnchor>::iterator ni = nodes.begin(), ne = nodes.end(); ni != ne; ++ni) {
const vector<KeyValuePair> &candidates = (*ni).node->candidates();
for (vector<KeyValuePair>::const_iterator ci = candidates.begin(), ce = candidates.end(); ci != ce; ++ci) {
for (std::vector<Taiyan::Gramambular::NodeAnchor>::iterator ni = nodes.begin(), ne = nodes.end(); ni != ne; ++ni) {
const std::vector<Taiyan::Gramambular::KeyValuePair> &candidates = (*ni).node->candidates();
for (std::vector<Taiyan::Gramambular::KeyValuePair>::const_iterator ci = candidates.begin(), ce = candidates.end(); ci != ce; ++ci) {
[candidatesArray addObject:[NSString stringWithUTF8String:(*ci).value.c_str()]];
}
}
@ -1359,8 +1355,8 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
- (NSArray *)_currentReadings
{
NSMutableArray *readingsArray = [[NSMutableArray alloc] init];
vector<std::string> v = _builder->readings();
for (vector<std::string>::iterator it_i = v.begin(); it_i != v.end(); ++it_i) {
std::vector<std::string> v = _builder->readings();
for (std::vector<std::string>::iterator it_i = v.begin(); it_i != v.end(); ++it_i) {
[readingsArray addObject:[NSString stringWithUTF8String:it_i->c_str()]];
}
return readingsArray;
@ -1368,9 +1364,9 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
- (nullable InputState *)buildAssociatePhraseStateWithKey:(NSString *)key useVerticalMode:(BOOL)useVerticalMode
{
string cppKey = string(key.UTF8String);
std::string cppKey = std::string(key.UTF8String);
if (_languageModel->hasAssociatedPhrasesForKey(cppKey)) {
vector<string> phrases = _languageModel->associatedPhrasesForKey(cppKey);
std::vector<std::string> phrases = _languageModel->associatedPhrasesForKey(cppKey);
NSMutableArray <NSString *> *array = [NSMutableArray array];
for (auto phrase: phrases) {
NSString *item = [[NSString alloc] initWithUTF8String:phrase.c_str()];

View File

@ -37,7 +37,7 @@ class LMConsolidator
public:
static bool CheckPragma(const char *path);
static bool FixEOF(const char *path);
static bool ConsolidateContent(const char *path, bool shouldsort);
static bool ConsolidateContent(const char *path, bool shouldsort, bool shouldCheckPragma);
};
} // namespace vChewing

View File

@ -71,8 +71,8 @@ bool LMConsolidator::FixEOF(const char *path)
} // END: EOF FIXER.
// CONTENT CONSOLIDATOR. CREDIT: Shiki Suen.
bool LMConsolidator::ConsolidateContent(const char *path, bool shouldsort) {
if (LMConsolidator::CheckPragma(path) && !shouldsort){
bool LMConsolidator::ConsolidateContent(const char *path, bool shouldsort, bool shouldCheckPragma) {
if (LMConsolidator::CheckPragma(path) && !shouldsort && shouldCheckPragma){
return true;
}

View File

@ -47,6 +47,13 @@ class ctlInputMethod: IMKInputController {
private var keyHandler: KeyHandler = KeyHandler()
private var state: InputState = InputState.Empty()
// keyHandler 調 keyHandler
// InputState ctlInputMethod
// keyHandler keyHandlerInput
// currentKeyHandler keyHandler
// currentKeyHandler
static var currentKeyHandler: KeyHandler = KeyHandler()
// MARK: - IMKInputController methods
override init!(server: IMKServer!, delegate: Any!, client inputClient: Any!) {
@ -157,6 +164,8 @@ class ctlInputMethod: IMKInputController {
keyHandler.inputMode = newInputMode
self.handle(state: .Empty(), client: client)
}
//
ctlInputMethod.currentKeyHandler.inputMode = keyHandler.inputMode
}
// MARK: - IMKServerInput protocol methods
@ -603,7 +612,7 @@ extension ctlInputMethod: KeyHandlerDelegate {
if !state.validToWrite {
return false
}
mgrLangModel.writeUserPhrase(state.userPhrase, inputMode: keyHandler.inputMode)
mgrLangModel.writeUserPhrase(state.userPhrase, inputMode: keyHandler.inputMode, areWeDuplicating: state.chkIfUserPhraseExists)
return true
}
}

View File

@ -17,22 +17,22 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef VCHEWINGLM_H
#define VCHEWINGLM_H
#ifndef LMInstantiator_H
#define LMInstantiator_H
#include <stdio.h>
#include "UserPhrasesLM.h"
#include "ParselessLM.h"
#include "CNSLM.h"
#include "PhraseReplacementMap.h"
#include "AssociatedPhrases.h"
#include "CNSLM.h"
#include "ParselessLM.h"
#include "PhraseReplacementMap.h"
#include "UserPhrasesLM.h"
#include <stdio.h>
#include <unordered_set>
namespace vChewing {
using namespace Taiyan::Gramambular;
/// vChewingLM is a facade for managing a set of models including
/// LMInstantiator is a facade for managing a set of models including
/// the input method language model, user phrases and excluded phrases.
///
/// It is the primary model class that the input controller and grammar builder
@ -41,7 +41,7 @@ using namespace Taiyan::Gramambular;
/// if there are valid unigrams, and use returned unigrams to produce the final
/// results.
///
/// vChewingLM combine and transform the unigrams from the primary language
/// LMInstantiator combine and transform the unigrams from the primary language
/// model and user phrases. The process is
///
/// 1) Get the original unigrams.
@ -54,10 +54,10 @@ using namespace Taiyan::Gramambular;
/// model while launching and to load the user phrases anytime if the custom
/// files are modified. It does not keep the reference of the data pathes but
/// you have to pass the paths when you ask it to do loading.
class vChewingLM : public LanguageModel {
class LMInstantiator : public Taiyan::Gramambular::LanguageModel {
public:
vChewingLM();
~vChewingLM();
LMInstantiator();
~LMInstantiator();
/// Asks to load the primary language model at the given path.
/// @param languageModelPath The path of the language model.
@ -83,14 +83,14 @@ public:
void loadPhraseReplacementMap(const char* phraseReplacementPath);
/// Not implemented since we do not have data to provide bigram function.
const vector<Bigram> bigramsForKeys(const string& preceedingKey, const string& key);
const std::vector<Taiyan::Gramambular::Bigram> bigramsForKeys(const std::string& preceedingKey, const std::string& key);
/// Returns a list of available unigram for the given key.
/// @param key A string represents the BPMF reading or a symbol key. For
/// @param key A std::string represents the BPMF reading or a symbol key. For
/// example, it you pass "ㄇㄚ", it returns "嗎", "媽", and so on.
const vector<Unigram> unigramsForKey(const string& key);
const std::vector<Taiyan::Gramambular::Unigram> unigramsForKey(const std::string& key);
/// If the model has unigrams for the given key.
/// @param key The key.
bool hasUnigramsForKey(const string& key);
bool hasUnigramsForKey(const std::string& key);
/// Enables or disables phrase replacement.
void setPhraseReplacementEnabled(bool enabled);
@ -107,10 +107,10 @@ public:
/// If the external converted is enabled or not.
bool externalConverterEnabled();
/// Sets a lambda to let the values of unigrams could be converted by it.
void setExternalConverter(std::function<string(string)> externalConverter);
void setExternalConverter(std::function<std::string(std::string)> externalConverter);
const vector<std::string> associatedPhrasesForKey(const string& key);
bool hasAssociatedPhrasesForKey(const string& key);
const std::vector<std::string> associatedPhrasesForKey(const std::string& key);
bool hasAssociatedPhrasesForKey(const std::string& key);
protected:
@ -121,9 +121,9 @@ protected:
/// @param insertedValues The values for unigrams already in the results.
/// It helps to prevent duplicated unigrams. Please note that the method
/// has a side effect that it inserts values to `insertedValues`.
const vector<Unigram> filterAndTransformUnigrams(const vector<Unigram> unigrams,
const std::unordered_set<string>& excludedValues,
std::unordered_set<string>& insertedValues);
const std::vector<Taiyan::Gramambular::Unigram> filterAndTransformUnigrams(const std::vector<Taiyan::Gramambular::Unigram> unigrams,
const std::unordered_set<std::string>& excludedValues,
std::unordered_set<std::string>& insertedValues);
ParselessLM m_languageModel;
CNSLM m_cnsModel;
@ -134,7 +134,7 @@ protected:
bool m_phraseReplacementEnabled;
bool m_cnsEnabled;
bool m_externalConverterEnabled;
std::function<string(string)> m_externalConverter;
std::function<std::string(std::string)> m_externalConverter;
};
};

View File

@ -17,17 +17,17 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "vChewingLM.h"
#include "LMInstantiator.h"
#include <algorithm>
#include <iterator>
using namespace vChewing;
namespace vChewing {
vChewingLM::vChewingLM()
LMInstantiator::LMInstantiator()
{
}
vChewingLM::~vChewingLM()
LMInstantiator::~LMInstantiator()
{
m_languageModel.close();
m_userPhrases.close();
@ -37,7 +37,7 @@ vChewingLM::~vChewingLM()
m_associatedPhrases.close();
}
void vChewingLM::loadLanguageModel(const char* languageModelDataPath)
void LMInstantiator::loadLanguageModel(const char* languageModelDataPath)
{
if (languageModelDataPath) {
m_languageModel.close();
@ -45,12 +45,12 @@ void vChewingLM::loadLanguageModel(const char* languageModelDataPath)
}
}
bool vChewingLM::isDataModelLoaded()
bool LMInstantiator::isDataModelLoaded()
{
return m_languageModel.isLoaded();
}
void vChewingLM::loadCNSData(const char* cnsDataPath)
void LMInstantiator::loadCNSData(const char* cnsDataPath)
{
if (cnsDataPath) {
m_cnsModel.close();
@ -58,12 +58,12 @@ void vChewingLM::loadCNSData(const char* cnsDataPath)
}
}
bool vChewingLM::isCNSDataLoaded()
bool LMInstantiator::isCNSDataLoaded()
{
return m_cnsModel.isLoaded();
}
void vChewingLM::loadUserPhrases(const char* userPhrasesDataPath,
void LMInstantiator::loadUserPhrases(const char* userPhrasesDataPath,
const char* excludedPhrasesDataPath)
{
if (userPhrasesDataPath) {
@ -76,7 +76,7 @@ void vChewingLM::loadUserPhrases(const char* userPhrasesDataPath,
}
}
void vChewingLM::loadUserAssociatedPhrases(const char *userAssociatedPhrasesPath)
void LMInstantiator::loadUserAssociatedPhrases(const char *userAssociatedPhrasesPath)
{
if (userAssociatedPhrasesPath) {
m_associatedPhrases.close();
@ -84,7 +84,7 @@ void vChewingLM::loadUserAssociatedPhrases(const char *userAssociatedPhrasesPath
}
}
void vChewingLM::loadPhraseReplacementMap(const char* phraseReplacementPath)
void LMInstantiator::loadPhraseReplacementMap(const char* phraseReplacementPath)
{
if (phraseReplacementPath) {
m_phraseReplacement.close();
@ -92,49 +92,49 @@ void vChewingLM::loadPhraseReplacementMap(const char* phraseReplacementPath)
}
}
const vector<Bigram> vChewingLM::bigramsForKeys(const string& preceedingKey, const string& key)
const std::vector<Taiyan::Gramambular::Bigram> LMInstantiator::bigramsForKeys(const std::string& preceedingKey, const std::string& key)
{
return vector<Bigram>();
return std::vector<Taiyan::Gramambular::Bigram>();
}
const vector<Unigram> vChewingLM::unigramsForKey(const string& key)
const std::vector<Taiyan::Gramambular::Unigram> LMInstantiator::unigramsForKey(const std::string& key)
{
if (key == " ") {
vector<Unigram> spaceUnigrams;
Unigram g;
std::vector<Taiyan::Gramambular::Unigram> spaceUnigrams;
Taiyan::Gramambular::Unigram g;
g.keyValue.key = " ";
g.keyValue.value= " ";
g.keyValue.value = " ";
g.score = 0;
spaceUnigrams.push_back(g);
return spaceUnigrams;
}
vector<Unigram> allUnigrams;
vector<Unigram> userUnigrams;
vector<Unigram> cnsUnigrams;
std::vector<Taiyan::Gramambular::Unigram> allUnigrams;
std::vector<Taiyan::Gramambular::Unigram> userUnigrams;
std::vector<Taiyan::Gramambular::Unigram> cnsUnigrams;
unordered_set<string> excludedValues;
unordered_set<string> insertedValues;
std::unordered_set<std::string> excludedValues;
std::unordered_set<std::string> insertedValues;
if (m_excludedPhrases.hasUnigramsForKey(key)) {
vector<Unigram> excludedUnigrams = m_excludedPhrases.unigramsForKey(key);
std::vector<Taiyan::Gramambular::Unigram> excludedUnigrams = m_excludedPhrases.unigramsForKey(key);
transform(excludedUnigrams.begin(), excludedUnigrams.end(),
inserter(excludedValues, excludedValues.end()),
[](const Unigram& u) { return u.keyValue.value; });
[](const Taiyan::Gramambular::Unigram& u) { return u.keyValue.value; });
}
if (m_userPhrases.hasUnigramsForKey(key)) {
vector<Unigram> rawUserUnigrams = m_userPhrases.unigramsForKey(key);
std::vector<Taiyan::Gramambular::Unigram> rawUserUnigrams = m_userPhrases.unigramsForKey(key);
userUnigrams = filterAndTransformUnigrams(rawUserUnigrams, excludedValues, insertedValues);
}
if (m_languageModel.hasUnigramsForKey(key)) {
vector<Unigram> rawGlobalUnigrams = m_languageModel.unigramsForKey(key);
std::vector<Taiyan::Gramambular::Unigram> rawGlobalUnigrams = m_languageModel.unigramsForKey(key);
allUnigrams = filterAndTransformUnigrams(rawGlobalUnigrams, excludedValues, insertedValues);
}
if (m_cnsModel.hasUnigramsForKey(key) && m_cnsEnabled) {
vector<Unigram> rawCNSUnigrams = m_cnsModel.unigramsForKey(key);
std::vector<Taiyan::Gramambular::Unigram> rawCNSUnigrams = m_cnsModel.unigramsForKey(key);
cnsUnigrams = filterAndTransformUnigrams(rawCNSUnigrams, excludedValues, insertedValues);
}
@ -143,7 +143,7 @@ const vector<Unigram> vChewingLM::unigramsForKey(const string& key)
return allUnigrams;
}
bool vChewingLM::hasUnigramsForKey(const string& key)
bool LMInstantiator::hasUnigramsForKey(const std::string& key)
{
if (key == " ") {
return true;
@ -156,65 +156,65 @@ bool vChewingLM::hasUnigramsForKey(const string& key)
return unigramsForKey(key).size() > 0;
}
void vChewingLM::setPhraseReplacementEnabled(bool enabled)
void LMInstantiator::setPhraseReplacementEnabled(bool enabled)
{
m_phraseReplacementEnabled = enabled;
}
bool vChewingLM::phraseReplacementEnabled()
bool LMInstantiator::phraseReplacementEnabled()
{
return m_phraseReplacementEnabled;
}
void vChewingLM::setCNSEnabled(bool enabled)
void LMInstantiator::setCNSEnabled(bool enabled)
{
m_cnsEnabled = enabled;
}
bool vChewingLM::cnsEnabled()
bool LMInstantiator::cnsEnabled()
{
return m_cnsEnabled;
}
void vChewingLM::setExternalConverterEnabled(bool enabled)
void LMInstantiator::setExternalConverterEnabled(bool enabled)
{
m_externalConverterEnabled = enabled;
}
bool vChewingLM::externalConverterEnabled()
bool LMInstantiator::externalConverterEnabled()
{
return m_externalConverterEnabled;
}
void vChewingLM::setExternalConverter(std::function<string(string)> externalConverter)
void LMInstantiator::setExternalConverter(std::function<std::string(std::string)> externalConverter)
{
m_externalConverter = externalConverter;
}
const vector<Unigram> vChewingLM::filterAndTransformUnigrams(const vector<Unigram> unigrams, const unordered_set<string>& excludedValues, unordered_set<string>& insertedValues)
const std::vector<Taiyan::Gramambular::Unigram> LMInstantiator::filterAndTransformUnigrams(const std::vector<Taiyan::Gramambular::Unigram> unigrams, const std::unordered_set<std::string>& excludedValues, std::unordered_set<std::string>& insertedValues)
{
vector<Unigram> results;
std::vector<Taiyan::Gramambular::Unigram> results;
for (auto&& unigram : unigrams) {
// excludedValues filters out the unigrams with the original value.
// insertedValues filters out the ones with the converted value
string originalValue = unigram.keyValue.value;
std::string originalValue = unigram.keyValue.value;
if (excludedValues.find(originalValue) != excludedValues.end()) {
continue;
}
string value = originalValue;
std::string value = originalValue;
if (m_phraseReplacementEnabled) {
string replacement = m_phraseReplacement.valueForKey(value);
std::string replacement = m_phraseReplacement.valueForKey(value);
if (replacement != "") {
value = replacement;
}
}
if (m_externalConverterEnabled && m_externalConverter) {
string replacement = m_externalConverter(value);
std::string replacement = m_externalConverter(value);
value = replacement;
}
if (insertedValues.find(value) == insertedValues.end()) {
Unigram g;
Taiyan::Gramambular::Unigram g;
g.keyValue.value = value;
g.keyValue.key = unigram.keyValue.key;
g.score = unigram.score;
@ -225,12 +225,14 @@ const vector<Unigram> vChewingLM::filterAndTransformUnigrams(const vector<Unigra
return results;
}
const vector<std::string> vChewingLM::associatedPhrasesForKey(const string& key)
const std::vector<std::string> LMInstantiator::associatedPhrasesForKey(const std::string& key)
{
return m_associatedPhrases.valuesForKey(key);
}
bool vChewingLM::hasAssociatedPhrasesForKey(const string& key)
bool LMInstantiator::hasAssociatedPhrasesForKey(const std::string& key)
{
return m_associatedPhrases.hasValuesForKey(key);
}
} // namespace vChewing

View File

@ -59,12 +59,7 @@ bool AssociatedPhrases::open(const char *path)
}
LMConsolidator::FixEOF(path);
if (Preferences.shouldAutoSortAssociatedPhrasesOnLoad) {
LMConsolidator::ConsolidateContent(path, true);
} else {
LMConsolidator::ConsolidateContent(path, false);
}
LMConsolidator::ConsolidateContent(path, Preferences.shouldAutoSortAssociatedPhrasesOnLoad, true);
fd = ::open(path, O_RDONLY);
if (fd == -1) {

View File

@ -45,8 +45,8 @@ public:
void close();
void dump();
virtual const vector<Bigram> bigramsForKeys(const string& preceedingKey, const string& key);
virtual const vector<Unigram> unigramsForKey(const string& key);
virtual const std::vector<Taiyan::Gramambular::Bigram> bigramsForKeys(const string& preceedingKey, const string& key);
virtual const std::vector<Taiyan::Gramambular::Unigram> unigramsForKey(const string& key);
virtual bool hasUnigramsForKey(const string& key);
protected:

View File

@ -281,14 +281,14 @@ void vChewing::CoreLM::dump()
}
}
const vector<Bigram> vChewing::CoreLM::bigramsForKeys(const string& preceedingKey, const string& key)
const std::vector<Taiyan::Gramambular::Bigram> vChewing::CoreLM::bigramsForKeys(const string& preceedingKey, const string& key)
{
return vector<Bigram>();
return std::vector<Taiyan::Gramambular::Bigram>();
}
const vector<Unigram> vChewing::CoreLM::unigramsForKey(const string& key)
const std::vector<Taiyan::Gramambular::Unigram> vChewing::CoreLM::unigramsForKey(const string& key)
{
vector<Unigram> v;
std::vector<Taiyan::Gramambular::Unigram> v;
map<const char *, vector<Row> >::const_iterator i = keyRowMap.find(key.c_str());
if (i != keyRowMap.end()) {

View File

@ -54,12 +54,7 @@ bool PhraseReplacementMap::open(const char *path)
}
LMConsolidator::FixEOF(path);
if (Preferences.shouldAutoSortPhraseReplacementMapOnLoad) {
LMConsolidator::ConsolidateContent(path, true);
} else {
LMConsolidator::ConsolidateContent(path, false);
}
LMConsolidator::ConsolidateContent(path, Preferences.shouldAutoSortPhraseReplacementMapOnLoad, true);
fd = ::open(path, O_RDONLY);
if (fd == -1) {

View File

@ -23,7 +23,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
#include <cmath>
#include <sstream>
using namespace vChewing;
namespace vChewing {
// About 20 generations.
static const double DecayThreshould = 1.0 / 1048576.0;
@ -33,8 +33,8 @@ static double Score(size_t eventCount,
double eventTimestamp,
double timestamp,
double lambda);
static bool IsEndingPunctuation(const string& value);
static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
static bool IsEndingPunctuation(const std::string& value);
static std::string WalkedNodesToKey(const std::vector<Taiyan::Gramambular::NodeAnchor>& walkedNodes,
size_t cursorIndex);
UserOverrideModel::UserOverrideModel(size_t capacity, double decayConstant)
@ -43,11 +43,11 @@ UserOverrideModel::UserOverrideModel(size_t capacity, double decayConstant)
m_decayExponent = log(0.5) / decayConstant;
}
void UserOverrideModel::observe(const std::vector<NodeAnchor>& walkedNodes,
void UserOverrideModel::observe(const std::vector<Taiyan::Gramambular::NodeAnchor>& walkedNodes,
size_t cursorIndex,
const string& candidate,
const std::string& candidate,
double timestamp) {
string key = WalkedNodesToKey(walkedNodes, cursorIndex);
std::string key = WalkedNodesToKey(walkedNodes, cursorIndex);
auto mapIter = m_lruMap.find(key);
if (mapIter == m_lruMap.end()) {
auto keyValuePair = KeyObservationPair(key, Observation());
@ -76,20 +76,20 @@ void UserOverrideModel::observe(const std::vector<NodeAnchor>& walkedNodes,
}
}
string UserOverrideModel::suggest(const std::vector<NodeAnchor>& walkedNodes,
std::string UserOverrideModel::suggest(const std::vector<Taiyan::Gramambular::NodeAnchor>& walkedNodes,
size_t cursorIndex,
double timestamp) {
string key = WalkedNodesToKey(walkedNodes, cursorIndex);
std::string key = WalkedNodesToKey(walkedNodes, cursorIndex);
auto mapIter = m_lruMap.find(key);
if (mapIter == m_lruMap.end()) {
return string();
return std::string();
}
auto listIter = mapIter->second;
auto& keyValuePair = *listIter;
const Observation& observation = keyValuePair.second;
string candidate;
std::string candidate;
double score = 0.0;
for (auto i = observation.overrides.begin();
i != observation.overrides.end();
@ -112,7 +112,7 @@ string UserOverrideModel::suggest(const std::vector<NodeAnchor>& walkedNodes,
return candidate;
}
void UserOverrideModel::Observation::update(const string& candidate,
void UserOverrideModel::Observation::update(const std::string& candidate,
double timestamp) {
count++;
auto& o = overrides[candidate];
@ -134,16 +134,16 @@ static double Score(size_t eventCount,
return prob * decay;
}
static bool IsEndingPunctuation(const string& value) {
static bool IsEndingPunctuation(const std::string& value) {
return value == "" || value == "" || value== "" || value == "" ||
value == "" || value == "" || value== "" || value == "";
}
static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
static std::string WalkedNodesToKey(const std::vector<Taiyan::Gramambular::NodeAnchor>& walkedNodes,
size_t cursorIndex) {
std::stringstream s;
std::vector<NodeAnchor> n;
std::vector<Taiyan::Gramambular::NodeAnchor> n;
size_t ll = 0;
for (std::vector<NodeAnchor>::const_iterator i = walkedNodes.begin();
for (std::vector<Taiyan::Gramambular::NodeAnchor>::const_iterator i = walkedNodes.begin();
i != walkedNodes.end();
++i) {
const auto& nn = *i;
@ -154,19 +154,19 @@ static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
}
}
std::vector<NodeAnchor>::const_reverse_iterator r = n.rbegin();
std::vector<Taiyan::Gramambular::NodeAnchor>::const_reverse_iterator r = n.rbegin();
if (r == n.rend()) {
return "";
}
string current = (*r).node->currentKeyValue().key;
std::string current = (*r).node->currentKeyValue().key;
++r;
s.clear();
s.str(std::string());
if (r != n.rend()) {
string value = (*r).node->currentKeyValue().value;
std::string value = (*r).node->currentKeyValue().value;
if (IsEndingPunctuation(value)) {
s << "()";
r = n.rend();
@ -181,12 +181,12 @@ static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
} else {
s << "()";
}
string prev = s.str();
std::string prev = s.str();
s.clear();
s.str(std::string());
if (r != n.rend()) {
string value = (*r).node->currentKeyValue().value;
std::string value = (*r).node->currentKeyValue().value;
if (IsEndingPunctuation(value)) {
s << "()";
r = n.rend();
@ -201,7 +201,7 @@ static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
} else {
s << "()";
}
string anterior = s.str();
std::string anterior = s.str();
s.clear();
s.str(std::string());
@ -209,3 +209,5 @@ static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
return s.str();
}
} // namespace vChewing

View File

@ -22,7 +22,6 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
#include <list>
#include <map>
#include <string>
#include "Gramambular.h"
@ -34,12 +33,12 @@ class UserOverrideModel {
public:
UserOverrideModel(size_t capacity, double decayConstant);
void observe(const std::vector<NodeAnchor>& walkedNodes,
void observe(const std::vector<Taiyan::Gramambular::NodeAnchor>& walkedNodes,
size_t cursorIndex,
const string& candidate,
const std::string& candidate,
double timestamp);
string suggest(const std::vector<NodeAnchor>& walkedNodes,
std::string suggest(const std::vector<Taiyan::Gramambular::NodeAnchor>& walkedNodes,
size_t cursorIndex,
double timestamp);
@ -56,7 +55,7 @@ private:
std::map<std::string, Override> overrides;
Observation() : count(0) {}
void update(const string& candidate, double timestamp);
void update(const std::string& candidate, double timestamp);
};
typedef std::pair<std::string, Observation> KeyObservationPair;
@ -67,7 +66,7 @@ private:
std::map<std::string, std::list<KeyObservationPair>::iterator> m_lruMap;
};
}; // namespace vChewing
}; // namespace vChewing
#endif

View File

@ -60,12 +60,7 @@ bool UserPhrasesLM::open(const char *path)
}
LMConsolidator::FixEOF(path);
if (Preferences.shouldAutoSortUserPhrasesAndExclListOnLoad) {
LMConsolidator::ConsolidateContent(path, true);
} else {
LMConsolidator::ConsolidateContent(path, false);
}
LMConsolidator::ConsolidateContent(path, Preferences.shouldAutoSortUserPhrasesAndExclListOnLoad, true);
fd = ::open(path, O_RDONLY);
if (fd == -1) {

View File

@ -32,8 +32,8 @@ NS_ASSUME_NONNULL_BEGIN
+ (BOOL)checkIfUserLanguageModelFilesExist;
+ (BOOL)checkIfUserDataFolderExists;
+ (BOOL)checkIfUserPhraseExist:(NSString *)userPhrase key:(NSString *)key NS_SWIFT_NAME(checkIfExist(userPhrase:key:));
+ (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode;
+ (BOOL)checkIfUserPhraseExist:(NSString *)userPhrase inputMode:(InputMode)mode key:(NSString *)key NS_SWIFT_NAME(checkIfUserPhraseExist(userPhrase:mode:key:));
+ (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode areWeDuplicating:(BOOL)areWeDuplicating;
+ (void)setPhraseReplacementEnabled:(BOOL)phraseReplacementEnabled;
+ (void)setCNSEnabled:(BOOL)cnsEnabled;
+ (NSString *)userPhrasesDataPath:(InputMode)mode;

View File

@ -20,17 +20,15 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
#import "mgrLangModel.h"
#import "mgrLangModel_Privates.h"
#import "vChewing-Swift.h"
using namespace std;
using namespace vChewing;
#import "LMConsolidator.h"
static const int kUserOverrideModelCapacity = 500;
static const double kObservedOverrideHalflife = 5400.0;
static vChewingLM gLangModelCHT;
static vChewingLM gLangModelCHS;
static UserOverrideModel gUserOverrideModelCHT(kUserOverrideModelCapacity, kObservedOverrideHalflife);
static UserOverrideModel gUserOverrideModelCHS(kUserOverrideModelCapacity, kObservedOverrideHalflife);
static vChewing::LMInstantiator gLangModelCHT;
static vChewing::LMInstantiator gLangModelCHS;
static vChewing::UserOverrideModel gUserOverrideModelCHT(kUserOverrideModelCapacity, kObservedOverrideHalflife);
static vChewing::UserOverrideModel gUserOverrideModelCHS(kUserOverrideModelCapacity, kObservedOverrideHalflife);
static NSString *const kUserDataTemplateName = @"template-data";
static NSString *const kUserAssDataTemplateName = @"template-data";
@ -40,7 +38,7 @@ static NSString *const kTemplateExtension = @".txt";
@implementation mgrLangModel
static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewingLM &lm)
static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing::LMInstantiator &lm)
{
Class cls = NSClassFromString(@"ctlInputMethod");
NSString *dataPath = [[NSBundle bundleForClass:cls] pathForResource:filenameWithoutExtension ofType:@"txt"];
@ -206,10 +204,10 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
return YES;
}
+ (BOOL)checkIfUserPhraseExist:(NSString *)userPhrase key:(NSString *)key NS_SWIFT_NAME(checkIfExist(userPhrase:key:))
+ (BOOL)checkIfUserPhraseExist:(NSString *)userPhrase inputMode:(InputMode)mode key:(NSString *)key NS_SWIFT_NAME(checkIfUserPhraseExist(userPhrase:mode:key:))
{
string unigramKey = string(key.UTF8String);
vector<Unigram> unigrams = gLangModelCHT.unigramsForKey(unigramKey);
vector<vChewing::Unigram> unigrams = [mode isEqualToString:imeModeCHT] ? gLangModelCHT.unigramsForKey(unigramKey): gLangModelCHS.unigramsForKey(unigramKey);
string userPhraseString = string(userPhrase.UTF8String);
for (auto unigram: unigrams) {
if (unigram.keyValue.value == userPhraseString) {
@ -219,7 +217,7 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
return NO;
}
+ (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode;
+ (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode areWeDuplicating:(BOOL)areWeDuplicating
{
if (![self checkIfUserLanguageModelFilesExist]) {
return NO;
@ -251,6 +249,11 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
// [currentMarkedPhrase appendString:@"\n"];
// }
[currentMarkedPhrase appendString:userPhrase];
if (areWeDuplicating) {
// Do not use ASCII characters to comment here.
// Otherwise, it will be scrambled by HYPY2BPMF module shipped in the vChewing Phrase Editor.
[currentMarkedPhrase appendString:@"\t#𝙾𝚟𝚎𝚛𝚛𝚒𝚍𝚎"];
}
[currentMarkedPhrase appendString:@"\n"];
NSFileHandle *writeFile = [NSFileHandle fileHandleForUpdatingAtPath:path];
@ -262,9 +265,14 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
[writeFile writeData:data];
[writeFile closeFile];
// We use FSEventStream to monitor the change of the user phrase folder,
// so we don't have to load data here.
// [self loadUserPhrases];
// We enforce the format consolidation here, since the pragma header will let the UserPhraseLM bypasses the consolidating process on load.
vChewing::LMConsolidator::ConsolidateContent([path UTF8String], Preferences.shouldAutoSortUserPhrasesAndExclListOnLoad, false);
// We use FSEventStream to monitor the change of the user phrase folder,
// so we don't have to load data here unless FSEventStream is disabled by user.
if (!Preferences.shouldAutoReloadUserDataFiles) {
[self loadUserPhrases];
}
return YES;
}
@ -306,12 +314,12 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
return [[NSBundle bundleForClass:cls] pathForResource:@"char-kanji-cns" ofType:@"txt"];
}
+ (vChewingLM *)lmCHT
+ (vChewing::LMInstantiator *)lmCHT
{
return &gLangModelCHT;
}
+ (vChewingLM *)lmCHS
+ (vChewing::LMInstantiator *)lmCHS
{
return &gLangModelCHS;
}

View File

@ -19,13 +19,13 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
#import "mgrLangModel.h"
#import "UserOverrideModel.h"
#import "vChewingLM.h"
#import "LMInstantiator.h"
NS_ASSUME_NONNULL_BEGIN
@interface mgrLangModel ()
@property (class, readonly, nonatomic) vChewing::vChewingLM *lmCHT;
@property (class, readonly, nonatomic) vChewing::vChewingLM *lmCHS;
@property (class, readonly, nonatomic) vChewing::LMInstantiator *lmCHT;
@property (class, readonly, nonatomic) vChewing::LMInstantiator *lmCHS;
@property (class, readonly, nonatomic) vChewing::UserOverrideModel *userOverrideModelCHS;
@property (class, readonly, nonatomic) vChewing::UserOverrideModel *userOverrideModelCHT;
@end

View File

@ -17,82 +17,77 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef Bigram_h
#define Bigram_h
#ifndef BIGRAM_H_
#define BIGRAM_H_
#include <vector>
#include "KeyValuePair.h"
namespace Taiyan {
namespace Gramambular {
class Bigram {
public:
Bigram();
namespace Gramambular {
class Bigram {
public:
Bigram();
KeyValuePair preceedingKeyValue;
KeyValuePair keyValue;
double score;
KeyValuePair preceedingKeyValue;
KeyValuePair keyValue;
double score;
bool operator==(const Bigram& inAnother) const;
bool operator<(const Bigram& inAnother) const;
};
bool operator==(const Bigram& another) const;
bool operator<(const Bigram& another) const;
};
inline ostream& operator<<(ostream& inStream, const Bigram& inGram)
{
streamsize p = inStream.precision();
inStream.precision(6);
inStream << "(" << inGram.keyValue << "|" <<inGram.preceedingKeyValue << "," << inGram.score << ")";
inStream.precision(p);
return inStream;
}
inline ostream& operator<<(ostream& inStream, const vector<Bigram>& inGrams)
{
inStream << "[" << inGrams.size() << "]=>{";
size_t index = 0;
for (vector<Bigram>::const_iterator gi = inGrams.begin() ; gi != inGrams.end() ; ++gi, ++index) {
inStream << index << "=>";
inStream << *gi;
if (gi + 1 != inGrams.end()) {
inStream << ",";
}
}
inStream << "}";
return inStream;
}
inline Bigram::Bigram()
: score(0.0)
{
}
inline bool Bigram::operator==(const Bigram& inAnother) const
{
return preceedingKeyValue == inAnother.preceedingKeyValue && keyValue == inAnother.keyValue && score == inAnother.score;
}
inline bool Bigram::operator<(const Bigram& inAnother) const
{
if (preceedingKeyValue < inAnother.preceedingKeyValue) {
return true;
}
else if (preceedingKeyValue == inAnother.preceedingKeyValue) {
if (keyValue < inAnother.keyValue) {
return true;
}
else if (keyValue == inAnother.keyValue) {
return score < inAnother.score;
}
return false;
}
return false;
}
}
inline std::ostream& operator<<(std::ostream& stream, const Bigram& gram) {
std::streamsize p = stream.precision();
stream.precision(6);
stream << "(" << gram.keyValue << "|" << gram.preceedingKeyValue << ","
<< gram.score << ")";
stream.precision(p);
return stream;
}
inline std::ostream& operator<<(std::ostream& stream,
const std::vector<Bigram>& grams) {
stream << "[" << grams.size() << "]=>{";
size_t index = 0;
for (std::vector<Bigram>::const_iterator gi = grams.begin();
gi != grams.end(); ++gi, ++index) {
stream << index << "=>";
stream << *gi;
if (gi + 1 != grams.end()) {
stream << ",";
}
}
stream << "}";
return stream;
}
inline Bigram::Bigram() : score(0.0) {}
inline bool Bigram::operator==(const Bigram& another) const {
return preceedingKeyValue == another.preceedingKeyValue &&
keyValue == another.keyValue && score == another.score;
}
inline bool Bigram::operator<(const Bigram& another) const {
if (preceedingKeyValue < another.preceedingKeyValue) {
return true;
} else if (preceedingKeyValue == another.preceedingKeyValue) {
if (keyValue < another.keyValue) {
return true;
} else if (keyValue == another.keyValue) {
return score < another.score;
}
return false;
}
return false;
}
} // namespace Gramambular
} // namespace Taiyan
#endif

View File

@ -17,202 +17,190 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef BlockReadingBuilder_h
#define BlockReadingBuilder_h
#ifndef BLOCKREADINGBUILDER_H_
#define BLOCKREADINGBUILDER_H_
#include <string>
#include <vector>
#include "Grid.h"
#include "LanguageModel.h"
namespace Taiyan {
namespace Gramambular {
using namespace std;
namespace Gramambular {
class BlockReadingBuilder {
public:
BlockReadingBuilder(LanguageModel *inLM);
void clear();
class BlockReadingBuilder {
public:
explicit BlockReadingBuilder(LanguageModel* lm);
void clear();
size_t length() const;
size_t cursorIndex() const;
void setCursorIndex(size_t inNewIndex);
void insertReadingAtCursor(const string& inReading);
bool deleteReadingBeforeCursor(); // backspace
bool deleteReadingAfterCursor(); // delete
size_t length() const;
size_t cursorIndex() const;
void setCursorIndex(size_t newIndex);
void insertReadingAtCursor(const std::string& reading);
bool deleteReadingBeforeCursor(); // backspace
bool deleteReadingAfterCursor(); // delete
bool removeHeadReadings(size_t count);
bool removeHeadReadings(size_t count);
void setJoinSeparator(const string& separator);
const string joinSeparator() const;
void setJoinSeparator(const std::string& separator);
const std::string joinSeparator() const;
vector<string> readings() const;
std::vector<std::string> readings() const;
Grid& grid();
Grid& grid();
protected:
void build();
protected:
void build();
static const string Join(vector<string>::const_iterator begin, vector<string>::const_iterator end, const string& separator);
static const std::string Join(std::vector<std::string>::const_iterator begin,
std::vector<std::string>::const_iterator end,
const std::string& separator);
//最多使用六個字組成一個詞
static const size_t MaximumBuildSpanLength = 6;
// 最多使用六個字組成一個詞
static const size_t MaximumBuildSpanLength = 6;
size_t m_cursorIndex;
vector<string> m_readings;
size_t m_cursorIndex;
std::vector<std::string> m_readings;
Grid m_grid;
LanguageModel *m_LM;
string m_joinSeparator;
};
Grid m_grid;
LanguageModel* m_LM;
std::string m_joinSeparator;
};
inline BlockReadingBuilder::BlockReadingBuilder(LanguageModel *inLM)
: m_LM(inLM)
, m_cursorIndex(0)
{
}
inline BlockReadingBuilder::BlockReadingBuilder(LanguageModel* lm)
: m_LM(lm), m_cursorIndex(0) {}
inline void BlockReadingBuilder::clear()
{
m_cursorIndex = 0;
m_readings.clear();
m_grid.clear();
}
inline void BlockReadingBuilder::clear() {
m_cursorIndex = 0;
m_readings.clear();
m_grid.clear();
}
inline size_t BlockReadingBuilder::length() const
{
return m_readings.size();
}
inline size_t BlockReadingBuilder::length() const { return m_readings.size(); }
inline size_t BlockReadingBuilder::cursorIndex() const
{
return m_cursorIndex;
}
inline size_t BlockReadingBuilder::cursorIndex() const { return m_cursorIndex; }
inline void BlockReadingBuilder::setCursorIndex(size_t inNewIndex)
{
m_cursorIndex = inNewIndex > m_readings.size() ? m_readings.size() : inNewIndex;
}
inline void BlockReadingBuilder::setCursorIndex(size_t newIndex) {
m_cursorIndex = newIndex > m_readings.size() ? m_readings.size() : newIndex;
}
inline void BlockReadingBuilder::insertReadingAtCursor(const string& inReading)
{
m_readings.insert(m_readings.begin() + m_cursorIndex, inReading);
inline void BlockReadingBuilder::insertReadingAtCursor(
const std::string& reading) {
m_readings.insert(m_readings.begin() + m_cursorIndex, reading);
m_grid.expandGridByOneAtLocation(m_cursorIndex);
build();
m_cursorIndex++;
}
m_grid.expandGridByOneAtLocation(m_cursorIndex);
build();
m_cursorIndex++;
}
inline vector<string> BlockReadingBuilder::readings() const
{
return m_readings;
}
inline std::vector<std::string> BlockReadingBuilder::readings() const {
return m_readings;
}
inline bool BlockReadingBuilder::deleteReadingBeforeCursor()
{
if (!m_cursorIndex) {
return false;
}
inline bool BlockReadingBuilder::deleteReadingBeforeCursor() {
if (!m_cursorIndex) {
return false;
}
m_readings.erase(m_readings.begin() + m_cursorIndex - 1, m_readings.begin() + m_cursorIndex);
m_readings.erase(m_readings.begin() + m_cursorIndex - 1,
m_readings.begin() + m_cursorIndex);
m_cursorIndex--;
m_grid.shrinkGridByOneAtLocation(m_cursorIndex);
build();
return true;
}
inline bool BlockReadingBuilder::deleteReadingAfterCursor() {
if (m_cursorIndex == m_readings.size()) {
return false;
}
m_readings.erase(m_readings.begin() + m_cursorIndex,
m_readings.begin() + m_cursorIndex + 1);
m_grid.shrinkGridByOneAtLocation(m_cursorIndex);
build();
return true;
}
inline bool BlockReadingBuilder::removeHeadReadings(size_t count) {
if (count > length()) {
return false;
}
for (size_t i = 0; i < count; i++) {
if (m_cursorIndex) {
m_cursorIndex--;
m_grid.shrinkGridByOneAtLocation(m_cursorIndex);
build();
return true;
}
m_readings.erase(m_readings.begin(), m_readings.begin() + 1);
m_grid.shrinkGridByOneAtLocation(0);
build();
}
inline bool BlockReadingBuilder::deleteReadingAfterCursor()
{
if (m_cursorIndex == m_readings.size()) {
return false;
}
return true;
}
m_readings.erase(m_readings.begin() + m_cursorIndex, m_readings.begin() + m_cursorIndex + 1);
m_grid.shrinkGridByOneAtLocation(m_cursorIndex);
build();
return true;
}
inline void BlockReadingBuilder::setJoinSeparator(
const std::string& separator) {
m_joinSeparator = separator;
}
inline bool BlockReadingBuilder::removeHeadReadings(size_t count)
{
if (count > length()) {
return false;
}
inline const std::string BlockReadingBuilder::joinSeparator() const {
return m_joinSeparator;
}
for (size_t i = 0; i < count; i++) {
if (m_cursorIndex) {
m_cursorIndex--;
}
m_readings.erase(m_readings.begin(), m_readings.begin() + 1);
m_grid.shrinkGridByOneAtLocation(0);
build();
}
inline Grid& BlockReadingBuilder::grid() { return m_grid; }
return true;
}
inline void BlockReadingBuilder::build() {
if (!m_LM) {
return;
}
inline void BlockReadingBuilder::setJoinSeparator(const string& separator)
{
m_joinSeparator = separator;
}
size_t begin = 0;
size_t end = m_cursorIndex + MaximumBuildSpanLength;
inline const string BlockReadingBuilder::joinSeparator() const
{
return m_joinSeparator;
}
if (m_cursorIndex < MaximumBuildSpanLength) {
begin = 0;
} else {
begin = m_cursorIndex - MaximumBuildSpanLength;
}
inline Grid& BlockReadingBuilder::grid()
{
return m_grid;
}
if (end > m_readings.size()) {
end = m_readings.size();
}
inline void BlockReadingBuilder::build()
{
if (!m_LM) {
return;
}
for (size_t p = begin; p < end; p++) {
for (size_t q = 1; q <= MaximumBuildSpanLength && p + q <= end; q++) {
std::string combinedReading = Join(
m_readings.begin() + p, m_readings.begin() + p + q, m_joinSeparator);
if (!m_grid.hasNodeAtLocationSpanningLengthMatchingKey(p, q,
combinedReading)) {
std::vector<Unigram> unigrams = m_LM->unigramsForKey(combinedReading);
size_t begin = 0;
size_t end = m_cursorIndex + MaximumBuildSpanLength;
if (m_cursorIndex < MaximumBuildSpanLength) {
begin = 0;
}
else {
begin = m_cursorIndex - MaximumBuildSpanLength;
}
if (end > m_readings.size()) {
end = m_readings.size();
}
for (size_t p = begin ; p < end ; p++) {
for (size_t q = 1 ; q <= MaximumBuildSpanLength && p+q <= end ; q++) {
string combinedReading = Join(m_readings.begin() + p, m_readings.begin() + p + q, m_joinSeparator);
if (!m_grid.hasNodeAtLocationSpanningLengthMatchingKey(p, q, combinedReading)) {
vector<Unigram> unigrams = m_LM->unigramsForKey(combinedReading);
if (unigrams.size() > 0) {
Node n(combinedReading, unigrams, vector<Bigram>());
m_grid.insertNode(n, p, q);
}
}
if (unigrams.size() > 0) {
Node n(combinedReading, unigrams, std::vector<Bigram>());
m_grid.insertNode(n, p, q);
}
}
}
inline const string BlockReadingBuilder::Join(vector<string>::const_iterator begin, vector<string>::const_iterator end, const string& separator)
{
string result;
for (vector<string>::const_iterator iter = begin ; iter != end ; ) {
result += *iter;
++iter;
if (iter != end) {
result += separator;
}
}
return result;
}
}
}
inline const std::string BlockReadingBuilder::Join(
std::vector<std::string>::const_iterator begin,
std::vector<std::string>::const_iterator end,
const std::string& separator) {
std::string result;
for (std::vector<std::string>::const_iterator iter = begin; iter != end;) {
result += *iter;
++iter;
if (iter != end) {
result += separator;
}
}
return result;
}
} // namespace Gramambular
} // namespace Taiyan
#endif

View File

@ -17,8 +17,8 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef Gramambular_h
#define Gramambular_h
#ifndef GRAMAMBULAR_H_
#define GRAMAMBULAR_H_
#include "Bigram.h"
#include "BlockReadingBuilder.h"

View File

@ -17,248 +17,207 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef Grid_h
#define Grid_h
#ifndef GRID_H_
#define GRID_H_
#include <map>
#include <string>
#include <vector>
#include "NodeAnchor.h"
#include "Span.h"
namespace Taiyan {
namespace Gramambular {
namespace Gramambular {
class Grid {
public:
void clear();
void insertNode(const Node& inNode, size_t inLocation, size_t inSpanningLength);
bool hasNodeAtLocationSpanningLengthMatchingKey(size_t inLocation, size_t inSpanningLength, const string& inKey);
class Grid {
public:
void clear();
void insertNode(const Node& node, size_t location, size_t spanningLength);
bool hasNodeAtLocationSpanningLengthMatchingKey(size_t location,
size_t spanningLength,
const std::string& key);
void expandGridByOneAtLocation(size_t inLocation);
void shrinkGridByOneAtLocation(size_t inLocation);
void expandGridByOneAtLocation(size_t location);
void shrinkGridByOneAtLocation(size_t location);
size_t width() const;
vector<NodeAnchor> nodesEndingAt(size_t inLocation);
vector<NodeAnchor> nodesCrossingOrEndingAt(size_t inLocation);
size_t width() const;
std::vector<NodeAnchor> nodesEndingAt(size_t location);
std::vector<NodeAnchor> nodesCrossingOrEndingAt(size_t location);
// "Freeze" the node with the unigram that represents the selected candidate value.
// After this, the node that contains the unigram will always be evaluated to that
// unigram, while all other overlapping nodes will be reset to their initial state
// (that is, if any of those nodes were "frozen" or fixed, they will be unfrozen.)
NodeAnchor fixNodeSelectedCandidate(size_t location, const string& value);
// "Freeze" the node with the unigram that represents the selected candidate
// value. After this, the node that contains the unigram will always be
// evaluated to that unigram, while all other overlapping nodes will be reset
// to their initial state (that is, if any of those nodes were "frozen" or
// fixed, they will be unfrozen.)
NodeAnchor fixNodeSelectedCandidate(size_t location,
const std::string& value);
// Similar to fixNodeSelectedCandidate, but instead of "freezing" the node, only
// boost the unigram that represents the value with an overriding score. This
// has the same side effect as fixNodeSelectedCandidate, which is that all other
// overlapping nodes will be reset to their initial state.
void overrideNodeScoreForSelectedCandidate(size_t location, const string& value, float overridingScore);
// Similar to fixNodeSelectedCandidate, but instead of "freezing" the node,
// only boost the unigram that represents the value with an overriding score.
// This has the same side effect as fixNodeSelectedCandidate, which is that
// all other overlapping nodes will be reset to their initial state.
void overrideNodeScoreForSelectedCandidate(size_t location,
const std::string& value,
float overridingScore);
const string dumpDOT();
std::string dumpDOT();
protected:
vector<Span> m_spans;
};
protected:
std::vector<Span> m_spans;
};
inline void Grid::clear()
{
m_spans.clear();
inline void Grid::clear() { m_spans.clear(); }
inline void Grid::insertNode(const Node& node, size_t location,
size_t spanningLength) {
if (location >= m_spans.size()) {
size_t diff = location - m_spans.size() + 1;
for (size_t i = 0; i < diff; i++) {
m_spans.push_back(Span());
}
}
inline void Grid::insertNode(const Node& inNode, size_t inLocation, size_t inSpanningLength)
{
if (inLocation >= m_spans.size()) {
size_t diff = inLocation - m_spans.size() + 1;
m_spans[location].insertNodeOfLength(node, spanningLength);
}
for (size_t i = 0 ; i < diff ; i++) {
m_spans.push_back(Span());
}
}
inline bool Grid::hasNodeAtLocationSpanningLengthMatchingKey(
size_t location, size_t spanningLength, const std::string& key) {
if (location > m_spans.size()) {
return false;
}
m_spans[inLocation].insertNodeOfLength(inNode, inSpanningLength);
}
const Node* n = m_spans[location].nodeOfLength(spanningLength);
if (!n) {
return false;
}
inline bool Grid::hasNodeAtLocationSpanningLengthMatchingKey(size_t inLocation, size_t inSpanningLength, const string& inKey)
{
if (inLocation > m_spans.size()) {
return false;
}
return key == n->key();
}
const Node *n = m_spans[inLocation].nodeOfLength(inSpanningLength);
if (!n) {
return false;
}
return inKey == n->key();
}
inline void Grid::expandGridByOneAtLocation(size_t inLocation)
{
if (!inLocation || inLocation == m_spans.size()) {
m_spans.insert(m_spans.begin() + inLocation, Span());
}
else {
m_spans.insert(m_spans.begin() + inLocation, Span());
for (size_t i = 0 ; i < inLocation ; i++) {
// zaps overlapping spans
m_spans[i].removeNodeOfLengthGreaterThan(inLocation - i);
}
}
}
inline void Grid::shrinkGridByOneAtLocation(size_t inLocation)
{
if (inLocation >= m_spans.size()) {
return;
}
m_spans.erase(m_spans.begin() + inLocation);
for (size_t i = 0 ; i < inLocation ; i++) {
// zaps overlapping spans
m_spans[i].removeNodeOfLengthGreaterThan(inLocation - i);
}
}
inline size_t Grid::width() const
{
return m_spans.size();
}
inline vector<NodeAnchor> Grid::nodesEndingAt(size_t inLocation)
{
vector<NodeAnchor> result;
if (m_spans.size() && inLocation <= m_spans.size()) {
for (size_t i = 0 ; i < inLocation ; i++) {
Span& span = m_spans[i];
if (i + span.maximumLength() >= inLocation) {
Node *np = span.nodeOfLength(inLocation - i);
if (np) {
NodeAnchor na;
na.node = np;
na.location = i;
na.spanningLength = inLocation - i;
result.push_back(na);
}
}
}
}
return result;
}
inline vector<NodeAnchor> Grid::nodesCrossingOrEndingAt(size_t inLocation)
{
vector<NodeAnchor> result;
if (m_spans.size() && inLocation <= m_spans.size()) {
for (size_t i = 0 ; i < inLocation ; i++) {
Span& span = m_spans[i];
if (i + span.maximumLength() >= inLocation) {
for (size_t j = 1, m = span.maximumLength(); j <= m ; j++) {
if (i + j < inLocation) {
continue;
}
Node *np = span.nodeOfLength(j);
if (np) {
NodeAnchor na;
na.node = np;
na.location = i;
na.spanningLength = inLocation - i;
result.push_back(na);
}
}
}
}
}
return result;
}
// For nodes found at the location, fix their currently-selected candidate using the supplied string value.
inline NodeAnchor Grid::fixNodeSelectedCandidate(size_t location, const string& value)
{
vector<NodeAnchor> nodes = nodesCrossingOrEndingAt(location);
NodeAnchor node;
for (auto nodeAnchor : nodes) {
auto candidates = nodeAnchor.node->candidates();
// Reset the candidate-fixed state of every node at the location.
const_cast<Node*>(nodeAnchor.node)->resetCandidate();
for (size_t i = 0, c = candidates.size(); i < c; ++i) {
if (candidates[i].value == value) {
const_cast<Node*>(nodeAnchor.node)->selectCandidateAtIndex(i);
node = nodeAnchor;
break;;
}
}
}
return node;
}
inline void Grid::overrideNodeScoreForSelectedCandidate(size_t location, const string& value, float overridingScore)
{
vector<NodeAnchor> nodes = nodesCrossingOrEndingAt(location);
for (auto nodeAnchor : nodes) {
auto candidates = nodeAnchor.node->candidates();
// Reset the candidate-fixed state of every node at the location.
const_cast<Node*>(nodeAnchor.node)->resetCandidate();
for (size_t i = 0, c = candidates.size(); i < c; ++i) {
if (candidates[i].value == value) {
const_cast<Node*>(nodeAnchor.node)->selectFloatingCandidateAtIndex(i, overridingScore);
break;
}
}
}
}
inline const string Grid::dumpDOT()
{
stringstream sst;
sst << "digraph {" << endl;
sst << "graph [ rankdir=LR ];" << endl;
sst << "BOS;" << endl;
for (size_t p = 0 ; p < m_spans.size() ; p++) {
Span& span = m_spans[p];
for (size_t ni = 0 ; ni <= span.maximumLength() ; ni++) {
Node* np = span.nodeOfLength(ni);
if (np) {
if (!p) {
sst << "BOS -> " << np->currentKeyValue().value << ";" << endl;
}
sst << np->currentKeyValue().value << ";" << endl;
if (p + ni < m_spans.size()) {
Span& dstSpan = m_spans[p+ni];
for (size_t q = 0 ; q <= dstSpan.maximumLength() ; q++) {
Node *dn = dstSpan.nodeOfLength(q);
if (dn) {
sst << np->currentKeyValue().value << " -> " << dn->currentKeyValue().value << ";" << endl;
}
}
}
if (p + ni == m_spans.size()) {
sst << np->currentKeyValue().value << " -> " << "EOS;" << endl;
}
}
}
}
sst << "EOS;" << endl;
sst << "}";
return sst.str();
inline void Grid::expandGridByOneAtLocation(size_t location) {
if (!location || location == m_spans.size()) {
m_spans.insert(m_spans.begin() + location, Span());
} else {
m_spans.insert(m_spans.begin() + location, Span());
for (size_t i = 0; i < location; i++) {
// zaps overlapping spans
m_spans[i].removeNodeOfLengthGreaterThan(location - i);
}
}
}
inline void Grid::shrinkGridByOneAtLocation(size_t location) {
if (location >= m_spans.size()) {
return;
}
m_spans.erase(m_spans.begin() + location);
for (size_t i = 0; i < location; i++) {
// zaps overlapping spans
m_spans[i].removeNodeOfLengthGreaterThan(location - i);
}
}
inline size_t Grid::width() const { return m_spans.size(); }
inline std::vector<NodeAnchor> Grid::nodesEndingAt(size_t location) {
std::vector<NodeAnchor> result;
if (m_spans.size() && location <= m_spans.size()) {
for (size_t i = 0; i < location; i++) {
Span& span = m_spans[i];
if (i + span.maximumLength() >= location) {
Node* np = span.nodeOfLength(location - i);
if (np) {
NodeAnchor na;
na.node = np;
na.location = i;
na.spanningLength = location - i;
result.push_back(na);
}
}
}
}
return result;
}
inline std::vector<NodeAnchor> Grid::nodesCrossingOrEndingAt(size_t location) {
std::vector<NodeAnchor> result;
if (m_spans.size() && location <= m_spans.size()) {
for (size_t i = 0; i < location; i++) {
Span& span = m_spans[i];
if (i + span.maximumLength() >= location) {
for (size_t j = 1, m = span.maximumLength(); j <= m; j++) {
if (i + j < location) {
continue;
}
Node* np = span.nodeOfLength(j);
if (np) {
NodeAnchor na;
na.node = np;
na.location = i;
na.spanningLength = location - i;
result.push_back(na);
}
}
}
}
}
return result;
}
// For nodes found at the location, fix their currently-selected candidate using
// the supplied string value.
inline NodeAnchor Grid::fixNodeSelectedCandidate(size_t location,
const std::string& value) {
std::vector<NodeAnchor> nodes = nodesCrossingOrEndingAt(location);
NodeAnchor node;
for (auto nodeAnchor : nodes) {
auto candidates = nodeAnchor.node->candidates();
// Reset the candidate-fixed state of every node at the location.
const_cast<Node*>(nodeAnchor.node)->resetCandidate();
for (size_t i = 0, c = candidates.size(); i < c; ++i) {
if (candidates[i].value == value) {
const_cast<Node*>(nodeAnchor.node)->selectCandidateAtIndex(i);
node = nodeAnchor;
break;
}
}
}
return node;
}
inline void Grid::overrideNodeScoreForSelectedCandidate(
size_t location, const std::string& value, float overridingScore) {
std::vector<NodeAnchor> nodes = nodesCrossingOrEndingAt(location);
for (auto nodeAnchor : nodes) {
auto candidates = nodeAnchor.node->candidates();
// Reset the candidate-fixed state of every node at the location.
const_cast<Node*>(nodeAnchor.node)->resetCandidate();
for (size_t i = 0, c = candidates.size(); i < c; ++i) {
if (candidates[i].value == value) {
const_cast<Node*>(nodeAnchor.node)
->selectFloatingCandidateAtIndex(i, overridingScore);
break;
}
}
}
}
} // namespace Gramambular
} // namespace Taiyan
#endif

View File

@ -0,0 +1,70 @@
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License).
// All possible vChewing-specific modifications are (c) 2021 and onwards The vChewing Project (MIT-NTL License).
/*
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
to permit persons to whom the Software is furnished to do so, subject to the following conditions:
1. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
2. No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor,
except as required to fulfill notice requirements above.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "Grid.h"
#include <iostream>
#include <string>
namespace Taiyan {
namespace Gramambular {
std::string Grid::dumpDOT() {
std::stringstream sst;
sst << "digraph {" << std::endl;
sst << "graph [ rankdir=LR ];" << std::endl;
sst << "BOS;" << std::endl;
for (size_t p = 0; p < m_spans.size(); p++) {
Span& span = m_spans[p];
for (size_t ni = 0; ni <= span.maximumLength(); ni++) {
Node* np = span.nodeOfLength(ni);
if (np) {
if (!p) {
sst << "BOS -> " << np->currentKeyValue().value << ";" << std::endl;
}
sst << np->currentKeyValue().value << ";" << std::endl;
if (p + ni < m_spans.size()) {
Span& dstSpan = m_spans[p + ni];
for (size_t q = 0; q <= dstSpan.maximumLength(); q++) {
Node* dn = dstSpan.nodeOfLength(q);
if (dn) {
sst << np->currentKeyValue().value << " -> "
<< dn->currentKeyValue().value << ";" << std::endl;
}
}
}
if (p + ni == m_spans.size()) {
sst << np->currentKeyValue().value << " -> "
<< "EOS;" << std::endl;
}
}
}
}
sst << "EOS;" << std::endl;
sst << "}";
return sst.str();
}
} // namespace Gramambular
} // namespace Taiyan

View File

@ -17,47 +17,43 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef KeyValuePair_h
#define KeyValuePair_h
#ifndef KEYVALUEPAIR_H_
#define KEYVALUEPAIR_H_
#include <ostream>
#include <string>
namespace Taiyan {
namespace Gramambular {
using namespace std;
namespace Gramambular {
class KeyValuePair {
public:
string key;
string value;
class KeyValuePair {
public:
std::string key;
std::string value;
bool operator==(const KeyValuePair& inAnother) const;
bool operator<(const KeyValuePair& inAnother) const;
};
bool operator==(const KeyValuePair& another) const;
bool operator<(const KeyValuePair& another) const;
};
inline ostream& operator<<(ostream& inStream, const KeyValuePair& inPair)
{
inStream << "(" << inPair.key << "," << inPair.value << ")";
return inStream;
}
inline bool KeyValuePair::operator==(const KeyValuePair& inAnother) const
{
return key == inAnother.key && value == inAnother.value;
}
inline bool KeyValuePair::operator<(const KeyValuePair& inAnother) const
{
if (key < inAnother.key) {
return true;
}
else if (key == inAnother.key) {
return value < inAnother.value;
}
return false;
}
}
inline std::ostream& operator<<(std::ostream& stream,
const KeyValuePair& pair) {
stream << "(" << pair.key << "," << pair.value << ")";
return stream;
}
inline bool KeyValuePair::operator==(const KeyValuePair& another) const {
return key == another.key && value == another.value;
}
inline bool KeyValuePair::operator<(const KeyValuePair& another) const {
if (key < another.key) {
return true;
} else if (key == another.key) {
return value < another.value;
}
return false;
}
} // namespace Gramambular
} // namespace Taiyan
#endif

View File

@ -17,28 +17,28 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef LanguageModel_h
#define LanguageModel_h
#ifndef LANGUAGEMODEL_H_
#define LANGUAGEMODEL_H_
#include <string>
#include <vector>
#include "Bigram.h"
#include "Unigram.h"
namespace Taiyan {
namespace Gramambular {
namespace Gramambular {
using namespace std;
class LanguageModel {
public:
virtual ~LanguageModel() {}
virtual const vector<Bigram> bigramsForKeys(const string &preceedingKey, const string& key) = 0;
virtual const vector<Unigram> unigramsForKey(const string &key) = 0;
virtual bool hasUnigramsForKey(const string& key) = 0;
};
}
}
class LanguageModel {
public:
virtual ~LanguageModel() {}
virtual const std::vector<Bigram> bigramsForKeys(
const std::string& preceedingKey, const std::string& key) = 0;
virtual const std::vector<Unigram> unigramsForKey(const std::string& key) = 0;
virtual bool hasUnigramsForKey(const std::string& key) = 0;
};
} // namespace Gramambular
} // namespace Taiyan
#endif

View File

@ -17,208 +17,198 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef Node_h
#define Node_h
#ifndef NODE_H_
#define NODE_H_
#include <limits>
#include <map>
#include <string>
#include <vector>
#include "LanguageModel.h"
namespace Taiyan {
namespace Gramambular {
using namespace std;
namespace Gramambular {
class Node {
public:
Node();
Node(const string& inKey, const vector<Unigram>& inUnigrams, const vector<Bigram>& inBigrams);
class Node {
public:
Node();
Node(const std::string& key, const std::vector<Unigram>& unigrams,
const std::vector<Bigram>& bigrams);
void primeNodeWithPreceedingKeyValues(const vector<KeyValuePair>& inKeyValues);
void primeNodeWithPreceedingKeyValues(
const std::vector<KeyValuePair>& keyValues);
bool isCandidateFixed() const;
const vector<KeyValuePair>& candidates() const;
void selectCandidateAtIndex(size_t inIndex = 0, bool inFix = true);
void resetCandidate();
void selectFloatingCandidateAtIndex(size_t index, double score);
bool isCandidateFixed() const;
const std::vector<KeyValuePair>& candidates() const;
void selectCandidateAtIndex(size_t index = 0, bool fix = true);
void resetCandidate();
void selectFloatingCandidateAtIndex(size_t index, double score);
const string& key() const;
double score() const;
// double scoreForCandidate(string &candidate) const; // Prevents the override model to remember symbols with scode -X or lower.
const KeyValuePair currentKeyValue() const;
double highestUnigramScore() const;
const std::string& key() const;
double score() const;
double scoreForCandidate(const std::string& candidate) const;
const KeyValuePair currentKeyValue() const;
double highestUnigramScore() const;
protected:
const LanguageModel* m_LM;
protected:
const LanguageModel* m_LM;
string m_key;
double m_score;
std::string m_key;
double m_score;
vector<Unigram> m_unigrams;
vector<KeyValuePair> m_candidates;
map<string, size_t> m_valueUnigramIndexMap;
map<KeyValuePair, vector<Bigram> > m_preceedingGramBigramMap;
std::vector<Unigram> m_unigrams;
std::vector<KeyValuePair> m_candidates;
std::map<std::string, size_t> m_valueUnigramIndexMap;
std::map<KeyValuePair, std::vector<Bigram> > m_preceedingGramBigramMap;
bool m_candidateFixed;
size_t m_selectedUnigramIndex;
bool m_candidateFixed;
size_t m_selectedUnigramIndex;
friend ostream& operator<<(ostream& inStream, const Node& inNode);
};
friend std::ostream& operator<<(std::ostream& stream, const Node& node);
};
inline ostream& operator<<(ostream& inStream, const Node& inNode)
{
inStream << "(node,key:" << inNode.m_key << ",fixed:" << (inNode.m_candidateFixed ? "true" : "false")
<< ",selected:" << inNode.m_selectedUnigramIndex
<< "," << inNode.m_unigrams << ")";
return inStream;
}
inline std::ostream& operator<<(std::ostream& stream, const Node& node) {
stream << "(node,key:" << node.m_key
<< ",fixed:" << (node.m_candidateFixed ? "true" : "false")
<< ",selected:" << node.m_selectedUnigramIndex << ","
<< node.m_unigrams << ")";
return stream;
}
inline Node::Node()
: m_candidateFixed(false)
, m_selectedUnigramIndex(0)
, m_score(0.0)
{
}
inline Node::Node()
: m_candidateFixed(false), m_selectedUnigramIndex(0), m_score(0.0) {}
inline Node::Node(const string& inKey, const vector<Unigram>& inUnigrams, const vector<Bigram>& inBigrams)
: m_key(inKey)
, m_unigrams(inUnigrams)
, m_candidateFixed(false)
, m_selectedUnigramIndex(0)
, m_score(0.0)
{
stable_sort(m_unigrams.begin(), m_unigrams.end(), Unigram::ScoreCompare);
inline Node::Node(const std::string& key, const std::vector<Unigram>& unigrams,
const std::vector<Bigram>& bigrams)
: m_key(key),
m_unigrams(unigrams),
m_candidateFixed(false),
m_selectedUnigramIndex(0),
m_score(0.0) {
stable_sort(m_unigrams.begin(), m_unigrams.end(), Unigram::ScoreCompare);
if (m_unigrams.size()) {
m_score = m_unigrams[0].score;
}
if (m_unigrams.size()) {
m_score = m_unigrams[0].score;
}
size_t i = 0;
for (vector<Unigram>::const_iterator ui = m_unigrams.begin() ; ui != m_unigrams.end() ; ++ui) {
m_valueUnigramIndexMap[(*ui).keyValue.value] = i;
i++;
size_t i = 0;
for (std::vector<Unigram>::const_iterator ui = m_unigrams.begin();
ui != m_unigrams.end(); ++ui) {
m_valueUnigramIndexMap[(*ui).keyValue.value] = i;
i++;
m_candidates.push_back((*ui).keyValue);
}
m_candidates.push_back((*ui).keyValue);
}
for (vector<Bigram>::const_iterator bi = inBigrams.begin() ; bi != inBigrams.end() ; ++bi) {
m_preceedingGramBigramMap[(*bi).preceedingKeyValue].push_back(*bi);
}
}
for (std::vector<Bigram>::const_iterator bi = bigrams.begin();
bi != bigrams.end(); ++bi) {
m_preceedingGramBigramMap[(*bi).preceedingKeyValue].push_back(*bi);
}
}
inline void Node::primeNodeWithPreceedingKeyValues(const vector<KeyValuePair>& inKeyValues)
{
size_t newIndex = m_selectedUnigramIndex;
double max = m_score;
inline void Node::primeNodeWithPreceedingKeyValues(
const std::vector<KeyValuePair>& keyValues) {
size_t newIndex = m_selectedUnigramIndex;
double max = m_score;
if (!isCandidateFixed()) {
for (vector<KeyValuePair>::const_iterator kvi = inKeyValues.begin() ; kvi != inKeyValues.end() ; ++kvi) {
map<KeyValuePair, vector<Bigram> >::const_iterator f = m_preceedingGramBigramMap.find(*kvi);
if (f != m_preceedingGramBigramMap.end()) {
const vector<Bigram>& bigrams = (*f).second;
if (!isCandidateFixed()) {
for (std::vector<KeyValuePair>::const_iterator kvi = keyValues.begin();
kvi != keyValues.end(); ++kvi) {
std::map<KeyValuePair, std::vector<Bigram> >::const_iterator f =
m_preceedingGramBigramMap.find(*kvi);
if (f != m_preceedingGramBigramMap.end()) {
const std::vector<Bigram>& bigrams = (*f).second;
for (vector<Bigram>::const_iterator bi = bigrams.begin() ; bi != bigrams.end() ; ++bi) {
const Bigram& bigram = *bi;
if (bigram.score > max) {
map<string, size_t>::const_iterator uf = m_valueUnigramIndexMap.find((*bi).keyValue.value);
if (uf != m_valueUnigramIndexMap.end()) {
newIndex = (*uf).second;
max = bigram.score;
}
}
for (std::vector<Bigram>::const_iterator bi = bigrams.begin();
bi != bigrams.end(); ++bi) {
const Bigram& bigram = *bi;
if (bigram.score > max) {
std::map<std::string, size_t>::const_iterator uf =
m_valueUnigramIndexMap.find((*bi).keyValue.value);
if (uf != m_valueUnigramIndexMap.end()) {
newIndex = (*uf).second;
max = bigram.score;
}
}
}
}
if (m_score != max) {
m_score = max;
}
if (newIndex != m_selectedUnigramIndex) {
m_selectedUnigramIndex = newIndex;
}
}
}
inline bool Node::isCandidateFixed() const
{
return m_candidateFixed;
}
if (m_score != max) {
m_score = max;
}
inline const vector<KeyValuePair>& Node::candidates() const
{
return m_candidates;
}
inline void Node::selectCandidateAtIndex(size_t inIndex, bool inFix)
{
if (inIndex >= m_unigrams.size()) {
m_selectedUnigramIndex = 0;
}
else {
m_selectedUnigramIndex = inIndex;
}
m_candidateFixed = inFix;
m_score = 99;
}
inline void Node::resetCandidate()
{
m_selectedUnigramIndex = 0;
m_candidateFixed = 0;
if (m_unigrams.size()) {
m_score = m_unigrams[0].score;
}
}
inline void Node::selectFloatingCandidateAtIndex(size_t index, double score) {
if (index >= m_unigrams.size()) {
m_selectedUnigramIndex = 0;
} else {
m_selectedUnigramIndex = index;
}
m_candidateFixed = false;
m_score = score;
}
inline const string& Node::key() const
{
return m_key;
}
inline double Node::score() const
{
return m_score;
}
// Prevents the override model to remember symbols with scode -X or lower.
// inline double Node::scoreForCandidate(string &candidate) const
// {
// for (auto unigram : m_unigrams) {
// if (unigram.keyValue.value == candidate) {
// return unigram.score;
// }
// }
// return 0.0;
// }
inline double Node::highestUnigramScore() const {
if (m_unigrams.empty()) {
return 0.0;
}
return m_unigrams[0].score;
}
inline const KeyValuePair Node::currentKeyValue() const
{
if(m_selectedUnigramIndex >= m_unigrams.size()) {
return KeyValuePair();
}
else {
return m_candidates[m_selectedUnigramIndex];
}
}
if (newIndex != m_selectedUnigramIndex) {
m_selectedUnigramIndex = newIndex;
}
}
inline bool Node::isCandidateFixed() const { return m_candidateFixed; }
inline const std::vector<KeyValuePair>& Node::candidates() const {
return m_candidates;
}
inline void Node::selectCandidateAtIndex(size_t index, bool fix) {
if (index >= m_unigrams.size()) {
m_selectedUnigramIndex = 0;
} else {
m_selectedUnigramIndex = index;
}
m_candidateFixed = fix;
m_score = 99;
}
inline void Node::resetCandidate() {
m_selectedUnigramIndex = 0;
m_candidateFixed = 0;
if (m_unigrams.size()) {
m_score = m_unigrams[0].score;
}
}
inline void Node::selectFloatingCandidateAtIndex(size_t index, double score) {
if (index >= m_unigrams.size()) {
m_selectedUnigramIndex = 0;
} else {
m_selectedUnigramIndex = index;
}
m_candidateFixed = false;
m_score = score;
}
inline const std::string& Node::key() const { return m_key; }
inline double Node::score() const { return m_score; }
// Prevents the override model to remember symbols with scode -X or lower.
//inline double Node::scoreForCandidate(const std::string& candidate) const {
// for (auto unigram : m_unigrams) {
// if (unigram.keyValue.value == candidate) {
// return unigram.score;
// }
// }
// return 0.0;
//}
inline double Node::highestUnigramScore() const {
if (m_unigrams.empty()) {
return 0.0;
}
return m_unigrams[0].score;
}
inline const KeyValuePair Node::currentKeyValue() const {
if (m_selectedUnigramIndex >= m_unigrams.size()) {
return KeyValuePair();
} else {
return m_candidates[m_selectedUnigramIndex];
}
}
} // namespace Gramambular
} // namespace Taiyan
#endif

View File

@ -17,55 +17,48 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef NodeAnchor_h
#define NodeAnchor_h
#ifndef NODEANCHOR_H_
#define NODEANCHOR_H_
#include <vector>
#include "Node.h"
namespace Taiyan {
namespace Gramambular {
class NodeAnchor {
public:
NodeAnchor();
const Node *node;
size_t location;
size_t spanningLength;
double accumulatedScore;
};
namespace Gramambular {
inline NodeAnchor::NodeAnchor()
: node(0)
, location(0)
, spanningLength(0)
, accumulatedScore(0.0)
{
}
struct NodeAnchor {
const Node* node = nullptr;
size_t location = 0;
size_t spanningLength = 0;
double accumulatedScore = 0.0;
};
inline ostream& operator<<(ostream& inStream, const NodeAnchor& inAnchor)
{
inStream << "{@(" << inAnchor.location << "," << inAnchor.spanningLength << "),";
if (inAnchor.node) {
inStream << *(inAnchor.node);
}
else {
inStream << "null";
}
inStream << "}";
return inStream;
}
inline ostream& operator<<(ostream& inStream, const vector<NodeAnchor>& inAnchor)
{
for (vector<NodeAnchor>::const_iterator i = inAnchor.begin() ; i != inAnchor.end() ; ++i) {
inStream << *i;
if (i + 1 != inAnchor.end()) {
inStream << "<-";
}
}
return inStream;
}
inline std::ostream& operator<<(std::ostream& stream,
const NodeAnchor& anchor) {
stream << "{@(" << anchor.location << "," << anchor.spanningLength << "),";
if (anchor.node) {
stream << *(anchor.node);
} else {
stream << "null";
}
stream << "}";
return stream;
}
inline std::ostream& operator<<(std::ostream& stream,
const std::vector<NodeAnchor>& anchor) {
for (std::vector<NodeAnchor>::const_iterator i = anchor.begin();
i != anchor.end(); ++i) {
stream << *i;
if (i + 1 != anchor.end()) {
stream << "<-";
}
}
return stream;
}
} // namespace Gramambular
} // namespace Taiyan
#endif

View File

@ -17,88 +17,77 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef Span_h
#define Span_h
#ifndef SPAN_H_
#define SPAN_H_
#include <map>
#include <set>
#include <sstream>
#include "Node.h"
namespace Taiyan {
namespace Gramambular {
class Span {
public:
Span();
namespace Gramambular {
class Span {
public:
void clear();
void insertNodeOfLength(const Node& node, size_t length);
void removeNodeOfLengthGreaterThan(size_t length);
void clear();
void insertNodeOfLength(const Node& inNode, size_t inLength);
void removeNodeOfLengthGreaterThan(size_t inLength);
Node* nodeOfLength(size_t length);
size_t maximumLength() const;
Node* nodeOfLength(size_t inLength);
size_t maximumLength() const;
protected:
std::map<size_t, Node> m_lengthNodeMap;
size_t m_maximumLength = 0;
};
protected:
map<size_t, Node> m_lengthNodeMap;
size_t m_maximumLength;
};
inline void Span::clear() {
m_lengthNodeMap.clear();
m_maximumLength = 0;
}
inline Span::Span()
: m_maximumLength(0)
{
}
inline void Span::clear()
{
m_lengthNodeMap.clear();
m_maximumLength = 0;
}
inline void Span::insertNodeOfLength(const Node& inNode, size_t inLength)
{
m_lengthNodeMap[inLength] = inNode;
if (inLength > m_maximumLength) {
m_maximumLength = inLength;
}
}
inline void Span::removeNodeOfLengthGreaterThan(size_t inLength)
{
if (inLength > m_maximumLength) {
return;
}
size_t max = 0;
set<size_t> removeSet;
for (map<size_t, Node>::iterator i = m_lengthNodeMap.begin(), e = m_lengthNodeMap.end() ; i != e ; ++i) {
if ((*i).first > inLength) {
removeSet.insert((*i).first);
}
else {
if ((*i).first > max) {
max = (*i).first;
}
}
}
for (set<size_t>::iterator i = removeSet.begin(), e = removeSet.end(); i != e; ++i) {
m_lengthNodeMap.erase(*i);
}
m_maximumLength = max;
}
inline Node* Span::nodeOfLength(size_t inLength)
{
map<size_t, Node>::iterator f = m_lengthNodeMap.find(inLength);
return f == m_lengthNodeMap.end() ? 0 : &(*f).second;
}
inline size_t Span::maximumLength() const
{
return m_maximumLength;
}
inline void Span::insertNodeOfLength(const Node& node, size_t length) {
m_lengthNodeMap[length] = node;
if (length > m_maximumLength) {
m_maximumLength = length;
}
}
inline void Span::removeNodeOfLengthGreaterThan(size_t length) {
if (length > m_maximumLength) {
return;
}
size_t max = 0;
std::set<size_t> removeSet;
for (std::map<size_t, Node>::iterator i = m_lengthNodeMap.begin(),
e = m_lengthNodeMap.end();
i != e; ++i) {
if ((*i).first > length) {
removeSet.insert((*i).first);
} else {
if ((*i).first > max) {
max = (*i).first;
}
}
}
for (std::set<size_t>::iterator i = removeSet.begin(), e = removeSet.end();
i != e; ++i) {
m_lengthNodeMap.erase(*i);
}
m_maximumLength = max;
}
inline Node* Span::nodeOfLength(size_t length) {
std::map<size_t, Node>::iterator f = m_lengthNodeMap.find(length);
return f == m_lengthNodeMap.end() ? 0 : &(*f).second;
}
inline size_t Span::maximumLength() const { return m_maximumLength; }
} // namespace Gramambular
} // namespace Taiyan
#endif

View File

@ -17,80 +17,75 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef Unigram_h
#define Unigram_h
#ifndef UNIGRAM_H_
#define UNIGRAM_H_
#include <vector>
#include "KeyValuePair.h"
namespace Taiyan {
namespace Gramambular {
class Unigram {
public:
Unigram();
namespace Gramambular {
KeyValuePair keyValue;
double score;
class Unigram {
public:
Unigram();
bool operator==(const Unigram& inAnother) const;
bool operator<(const Unigram& inAnother) const;
KeyValuePair keyValue;
double score;
static bool ScoreCompare(const Unigram& a, const Unigram& b);
};
bool operator==(const Unigram& another) const;
bool operator<(const Unigram& another) const;
inline ostream& operator<<(ostream& inStream, const Unigram& inGram)
{
streamsize p = inStream.precision();
inStream.precision(6);
inStream << "(" << inGram.keyValue << "," << inGram.score << ")";
inStream.precision(p);
return inStream;
}
static bool ScoreCompare(const Unigram& a, const Unigram& b);
};
inline ostream& operator<<(ostream& inStream, const vector<Unigram>& inGrams)
{
inStream << "[" << inGrams.size() << "]=>{";
size_t index = 0;
for (vector<Unigram>::const_iterator gi = inGrams.begin() ; gi != inGrams.end() ; ++gi, ++index) {
inStream << index << "=>";
inStream << *gi;
if (gi + 1 != inGrams.end()) {
inStream << ",";
}
}
inStream << "}";
return inStream;
}
inline Unigram::Unigram()
: score(0.0)
{
}
inline bool Unigram::operator==(const Unigram& inAnother) const
{
return keyValue == inAnother.keyValue && score == inAnother.score;
}
inline bool Unigram::operator<(const Unigram& inAnother) const
{
if (keyValue < inAnother.keyValue) {
return true;
}
else if (keyValue == inAnother.keyValue) {
return score < inAnother.score;
}
return false;
}
inline bool Unigram::ScoreCompare(const Unigram& a, const Unigram& b)
{
return a.score > b.score;
}
}
inline std::ostream& operator<<(std::ostream& stream, const Unigram& gram) {
std::streamsize p = stream.precision();
stream.precision(6);
stream << "(" << gram.keyValue << "," << gram.score << ")";
stream.precision(p);
return stream;
}
inline std::ostream& operator<<(std::ostream& stream,
const std::vector<Unigram>& grams) {
stream << "[" << grams.size() << "]=>{";
size_t index = 0;
for (std::vector<Unigram>::const_iterator gi = grams.begin();
gi != grams.end(); ++gi, ++index) {
stream << index << "=>";
stream << *gi;
if (gi + 1 != grams.end()) {
stream << ",";
}
}
stream << "}";
return stream;
}
inline Unigram::Unigram() : score(0.0) {}
inline bool Unigram::operator==(const Unigram& another) const {
return keyValue == another.keyValue && score == another.score;
}
inline bool Unigram::operator<(const Unigram& another) const {
if (keyValue < another.keyValue) {
return true;
} else if (keyValue == another.keyValue) {
return score < another.score;
}
return false;
}
inline bool Unigram::ScoreCompare(const Unigram& a, const Unigram& b) {
return a.score > b.score;
}
} // namespace Gramambular
} // namespace Taiyan
#endif

View File

@ -17,67 +17,69 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef Walker_h
#define Walker_h
#ifndef WALKER_H_
#define WALKER_H_
#include <algorithm>
#include <vector>
#include "Grid.h"
namespace Taiyan {
namespace Gramambular {
using namespace std;
namespace Gramambular {
class Walker {
public:
Walker(Grid* inGrid);
const vector<NodeAnchor> reverseWalk(size_t inLocation, double inAccumulatedScore = 0.0);
class Walker {
public:
explicit Walker(Grid* inGrid);
const std::vector<NodeAnchor> reverseWalk(size_t location,
double accumulatedScore = 0.0);
protected:
Grid* m_grid;
};
protected:
Grid* m_grid;
};
inline Walker::Walker(Grid* inGrid)
: m_grid(inGrid)
{
inline Walker::Walker(Grid* inGrid) : m_grid(inGrid) {}
inline const std::vector<NodeAnchor> Walker::reverseWalk(
size_t location, double accumulatedScore) {
if (!location || location > m_grid->width()) {
return std::vector<NodeAnchor>();
}
std::vector<std::vector<NodeAnchor> > paths;
std::vector<NodeAnchor> nodes = m_grid->nodesEndingAt(location);
for (std::vector<NodeAnchor>::iterator ni = nodes.begin(); ni != nodes.end();
++ni) {
if (!(*ni).node) {
continue;
}
inline const vector<NodeAnchor> Walker::reverseWalk(size_t inLocation, double inAccumulatedScore)
{
if (!inLocation || inLocation > m_grid->width()) {
return vector<NodeAnchor>();
}
(*ni).accumulatedScore = accumulatedScore + (*ni).node->score();
vector<vector<NodeAnchor> > paths;
std::vector<NodeAnchor> path =
reverseWalk(location - (*ni).spanningLength, (*ni).accumulatedScore);
path.insert(path.begin(), *ni);
vector<NodeAnchor> nodes = m_grid->nodesEndingAt(inLocation);
paths.push_back(path);
}
for (vector<NodeAnchor>::iterator ni = nodes.begin() ; ni != nodes.end() ; ++ni) {
if (!(*ni).node) {
continue;
}
if (!paths.size()) {
return std::vector<NodeAnchor>();
}
(*ni).accumulatedScore = inAccumulatedScore + (*ni).node->score();
vector<NodeAnchor> path = reverseWalk(inLocation - (*ni).spanningLength, (*ni).accumulatedScore);
path.insert(path.begin(), *ni);
paths.push_back(path);
}
if (!paths.size()) {
return vector<NodeAnchor>();
}
vector<NodeAnchor>* result = &*(paths.begin());
for (vector<vector<NodeAnchor> >::iterator pi = paths.begin() ; pi != paths.end() ; ++pi) {
if ((*pi).back().accumulatedScore > result->back().accumulatedScore) {
result = &*pi;
}
}
return *result;
std::vector<NodeAnchor>* result = &*(paths.begin());
for (std::vector<std::vector<NodeAnchor> >::iterator pi = paths.begin();
pi != paths.end(); ++pi) {
if ((*pi).back().accumulatedScore > result->back().accumulatedScore) {
result = &*pi;
}
}
return *result;
}
} // namespace Gramambular
} // namespace Taiyan
#endif

View File

@ -1,182 +0,0 @@
.
├── AppDelegate.swift
├── Base.lproj
│   ├── Credits.rtf
│   ├── InfoPlist.strings
│   ├── Localizable.strings
│   ├── MainMenu.xib
│   ├── preferences.xib
│   ├── template-data.txt
│   ├── template-exclude-phrases-plain-bpmf.txt
│   ├── template-exclude-phrases.txt
│   └── template-phrases-replacement.txt
├── Data
│   ├── BPMFBase.txt
│   ├── BPMFMappings.txt
│   ├── BPMFPunctuations.txt
│   ├── Makefile
│   ├── PhraseFreq.txt
│   ├── README
│   ├── Symbols.txt
│   ├── associated-phrases.cin
│   ├── bin
│   │   ├── C_Version
│   │   │   ├── Makefile
│   │   │   ├── count.bash
│   │   │   └── count.occurrence.c
│   │   ├── README
│   │   ├── Sample_Prep
│   │   │   ├── build.bash
│   │   │   └── filter.bash
│   │   ├── bpmfmap.py
│   │   ├── buildFreq.py
│   │   ├── cook-plain-bpmf.py
│   │   ├── cook.py
│   │   ├── cook_util.py
│   │   ├── count.bash
│   │   ├── count.occurrence.py
│   │   ├── disabled
│   │   │   ├── BIG5toUTF8.pl
│   │   │   ├── bpmfmap_human.py
│   │   │   ├── build4wlist.bash
│   │   │   ├── buildFreq.bash
│   │   │   ├── cook.rb
│   │   │   ├── count.occurrence.pl
│   │   │   ├── countphrase.bash
│   │   │   ├── randomShuffle.bash
│   │   │   ├── typocorrection.bash
│   │   │   └── utf8length.pl
│   │   ├── nonCJK_filter.py
│   │   ├── self-score-test.py
│   │   └── textpool.rc
│   ├── data-plain-bpmf.txt
│   ├── data.txt
│   ├── exclusion.txt
│   ├── heterophony1.list
│   ├── heterophony2.list
│   ├── heterophony3.list
│   ├── memo
│   │   ├── blacklist.txt
│   │   ├── covered_by_others.txt
│   │   ├── covered_by_singles.txt
│   │   └── falsecount.txt
│   └── phrase.occ
├── Engine
│   ├── AssociatedPhrases.cpp
│   ├── AssociatedPhrases.h
│   ├── CMakeLists.txt
│   ├── Gramambular
│   │   ├── Bigram.h
│   │   ├── BlockReadingBuilder.h
│   │   ├── Gramambular.h
│   │   ├── Grid.h
│   │   ├── KeyValuePair.h
│   │   ├── LanguageModel.h
│   │   ├── Node.h
│   │   ├── NodeAnchor.h
│   │   ├── Span.h
│   │   ├── Unigram.h
│   │   └── Walker.h
│   ├── KeyValueBlobReader.cpp
│   ├── KeyValueBlobReader.h
│   ├── KeyValueBlobReaderTest.cpp
│   ├── Mandarin
│   │   ├── CMakeLists.txt
│   │   ├── Mandarin.cpp
│   │   ├── Mandarin.h
│   │   └── MandarinTest.cpp
│   ├── McBopomofoLM.cpp
│   ├── McBopomofoLM.h
│   ├── ParselessLM.cpp
│   ├── ParselessLM.h
│   ├── ParselessLMBenchmark.cpp
│   ├── ParselessLMTest.cpp
│   ├── ParselessPhraseDB.cpp
│   ├── ParselessPhraseDB.h
│   ├── ParselessPhraseDBTest.cpp
│   ├── PhraseReplacementMap.cpp
│   ├── PhraseReplacementMap.h
│   ├── PhraseReplacementMapTest.cpp
│   ├── UserOverrideModel.cpp
│   ├── UserOverrideModel.h
│   ├── UserPhrasesLM.cpp
│   ├── UserPhrasesLM.h
│   └── UserPhrasesLMTest.cpp
├── Images
│   ├── Bopomofo.tiff
│   ├── Bopomofo@2x.tiff
│   ├── Images.xcassets
│   │   ├── AlertIcon.imageset
│   │   │   ├── 128X128.png
│   │   │   ├── 192x192.png
│   │   │   ├── 64X64.png
│   │   │   └── Contents.json
│   │   ├── AppIcon.appiconset
│   │   │   ├── 1024X1024.png
│   │   │   ├── 128X128.png
│   │   │   ├── 16X16.png
│   │   │   ├── 256X256.png
│   │   │   ├── 32X32.png
│   │   │   ├── 512X512.png
│   │   │   ├── 64X64.png
│   │   │   └── Contents.json
│   │   └── Contents.json
│   ├── PlainBopomofo.tiff
│   └── PlainBopomofo@2x.tiff
├── InputMethodController.swift
├── InputState.swift
├── Installer
│   ├── AppDelegate.swift
│   ├── ArchiveUtil.swift
│   ├── Base.lproj
│   │   └── MainMenu.xib
│   ├── BundleTranslocate.h
│   ├── BundleTranslocate.m
│   ├── Installer-Info.plist
│   ├── Installer-Prefix.pch
│   ├── McBopomofoInstaller-Bridging-Header.h
│   ├── NotarizedArchives
│   │   └── README.md
│   ├── en.lproj
│   │   ├── InfoPlist.strings
│   │   ├── License.rtf
│   │   └── Localizable.strings
│   └── zh-Hant.lproj
│   ├── InfoPlist.strings
│   ├── License.rtf
│   ├── Localizable.strings
│   └── MainMenu.xib
├── KeyHandler.h
├── KeyHandler.mm
├── KeyHandlerInput.swift
├── LanguageModelManager+Privates.h
├── LanguageModelManager.h
├── LanguageModelManager.mm
├── McBopomofo-Bridging-Header.h
├── McBopomofo-Info.plist
├── McBopomofo-Prefix.pch
├── NonModalAlertWindowController.swift
├── NonModalAlertWindowController.xib
├── Preferences.swift
├── PreferencesWindowController.swift
├── README
├── Tools
│   ├── genRTF.py
│   └── tistool.m
├── en.lproj
│   ├── Credits.rtf
│   ├── InfoPlist.strings
│   └── Localizable.strings
├── main.swift
└── zh-Hant.lproj
├── Credits.rtf
├── InfoPlist.strings
├── Localizable.strings
├── MainMenu.xib
├── preferences.xib
├── template-data.txt
├── template-exclude-phrases-plain-bpmf.txt
├── template-exclude-phrases.txt
└── template-phrases-replacement.txt
22 directories, 157 files

View File

@ -24,7 +24,7 @@
"\"%@\" length must ≥ 2 for a user phrase." = "\"%@\" length must ≥ 2 for a user phrase.";
"\"%@\" length should ≤ %d for a user phrase." = "\"%@\" length should ≤ %d for a user phrase.";
"\"%@\" selected. ENTER to add user phrase." = "\"%@\" selected. ENTER to add user phrase.";
"\"%@\" already exists." = "\"%@\" already exists.";
"\"%@\" already exists, ENTER to boost its priority." = "\"%@\" already exists, ENTER to boost its priority.";
"Edit Phrase Replacement Table…" = "Edit Phrase Replacement Table…";
"Use Phrase Replacement" = "Use Phrase Replacement";
"Candidates keys cannot be empty." = "Candidates keys cannot be empty.";

View File

@ -24,7 +24,7 @@
"\"%@\" length must ≥ 2 for a user phrase." = "\"%@\" length must ≥ 2 for a user phrase.";
"\"%@\" length should ≤ %d for a user phrase." = "\"%@\" length should ≤ %d for a user phrase.";
"\"%@\" selected. ENTER to add user phrase." = "\"%@\" selected. ENTER to add user phrase.";
"\"%@\" already exists." = "\"%@\" already exists.";
"\"%@\" already exists, ENTER to boost its priority." = "\"%@\" already exists, ENTER to boost its priority.";
"Edit Phrase Replacement Table…" = "Edit Phrase Replacement Table…";
"Use Phrase Replacement" = "Use Phrase Replacement";
"Candidates keys cannot be empty." = "Candidates keys cannot be empty.";

View File

@ -24,7 +24,7 @@
"\"%@\" length must ≥ 2 for a user phrase." = "「%@」もう1つ文字のお選びを。";
"\"%@\" length should ≤ %d for a user phrase." = "「%@」文字数過剰で登録不可、%d 文字以内にして下さい。";
"\"%@\" selected. ENTER to add user phrase." = "「%@」を ENTER で辞書に登録。";
"\"%@\" already exists." = "「%@」は既存語彙である。";
"\"%@\" already exists, ENTER to boost its priority." = "「%@」は既存語彙であり、ENTER で最優先にする。";
"Edit Phrase Replacement Table…" = "言葉置換表を編集…";
"Use Phrase Replacement" = "言葉置換機能";
"Candidates keys cannot be empty." = "言選り用キー陣列に何かキーをご登録ください。";

View File

@ -24,7 +24,7 @@
"\"%@\" length must ≥ 2 for a user phrase." = "「%@」字数不足以自订语汇。";
"\"%@\" length should ≤ %d for a user phrase." = "「%@」字数超过 %d、无法自订。";
"\"%@\" selected. ENTER to add user phrase." = "「%@」敲 Enter 添入自订语汇。";
"\"%@\" already exists." = "「%@」已存在。";
"\"%@\" already exists, ENTER to boost its priority." = "「%@」已存在,敲 ENTER 以提升其权重。";
"Edit Phrase Replacement Table…" = "编辑语汇置换表…";
"Use Phrase Replacement" = "使用语汇置换";
"Candidates keys cannot be empty." = "您必须指定选字键。";

View File

@ -24,7 +24,7 @@
"\"%@\" length must ≥ 2 for a user phrase." = "「%@」字數不足以自訂語彙。";
"\"%@\" length should ≤ %d for a user phrase." = "「%@」字數超過 %d、無法自訂。";
"\"%@\" selected. ENTER to add user phrase." = "「%@」敲 Enter 添入自訂語彙。";
"\"%@\" already exists." = "「%@」已存在。";
"\"%@\" already exists, ENTER to boost its priority." = "「%@」已存在,敲 ENTER 以提升其權重。";
"Edit Phrase Replacement Table…" = "編輯語彙置換表…";
"Use Phrase Replacement" = "使用語彙置換";
"Candidates keys cannot be empty." = "您必須指定選字鍵。";

View File

@ -86,7 +86,7 @@ extension RangeReplaceableCollection where Element: Hashable {
let menuItem_vChewingDachen = NSMenuItem()
menuItem_vChewingDachen.title = String(format: NSLocalizedString("vChewing Dachen (Not Finished Yet)", comment: ""))
menuItem_vChewingDachen.representedObject = String("org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyindachen")
menuItem_vChewingDachen.representedObject = String("org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingDachen")
basisKeyboardLayoutButton.menu?.addItem(menuItem_vChewingDachen)
let basisKeyboardLayoutID = Preferences.basisKeyboardLayout

View File

@ -7,8 +7,8 @@
<key>UpdateInfoSite</key>
<string>https://gitee.com/vchewing/vChewing-macOS</string>
<key>CFBundleVersion</key>
<string>1922</string>
<string>1923</string>
<key>CFBundleShortVersionString</key>
<string>1.3.3</string>
<string>1.3.4</string>
</dict>
</plist>

View File

@ -11,7 +11,6 @@
5B11328927B94CFB00E58451 /* AppleKeyboardConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */; };
5B2DB16F27AF6891006D874E /* data-chs.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B2DB16D27AF6891006D874E /* data-chs.txt */; };
5B2DB17027AF6891006D874E /* data-cht.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B2DB16E27AF6891006D874E /* data-cht.txt */; };
5B30F11327BA568800484E24 /* vChewingKeyLayout.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */; };
5B62A31727AE73A700A19448 /* unzip.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A30927AE73A700A19448 /* unzip.m */; };
5B62A31827AE73A700A19448 /* zip.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A30A27AE73A700A19448 /* zip.m */; };
5B62A31927AE73A700A19448 /* ioapi.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A30B27AE73A700A19448 /* ioapi.m */; };
@ -50,6 +49,12 @@
5BD05C6827B2BBEF004C4F1D /* Content.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD05C6327B2BBEF004C4F1D /* Content.swift */; };
5BD05C6927B2BBEF004C4F1D /* WindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD05C6427B2BBEF004C4F1D /* WindowController.swift */; };
5BD05C6A27B2BBEF004C4F1D /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD05C6527B2BBEF004C4F1D /* ViewController.swift */; };
5BDC5CAB27C2873D00E1CCE2 /* Grid.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5BDC5CAA27C2873D00E1CCE2 /* Grid.mm */; };
5BDC5CB327C28E8B00E1CCE2 /* icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 5BDC5CB227C28E8B00E1CCE2 /* icon.icns */; };
5BDC5CB527C28E8B00E1CCE2 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDC5CB427C28E8B00E1CCE2 /* ShareViewController.swift */; };
5BDC5CB827C28E8B00E1CCE2 /* ShareViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BDC5CB627C28E8B00E1CCE2 /* ShareViewController.xib */; };
5BDC5CBD27C28E8B00E1CCE2 /* KeyboardExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 5BDC5CB027C28E8B00E1CCE2 /* KeyboardExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
5BDC5CC227C2941F00E1CCE2 /* vChewingKeyLayout.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */; };
5BDCBB2E27B4E67A00D0CC59 /* vChewingPhraseEditor.app in Resources */ = {isa = PBXBuildFile; fileRef = 5BD05BB827B2A429004C4F1D /* vChewingPhraseEditor.app */; };
5BE78BD927B3775B005EA1BE /* ctlAboutWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BE78BD827B37750005EA1BE /* ctlAboutWindow.swift */; };
5BE78BDD27B3776D005EA1BE /* frmAboutWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BE78BDA27B37764005EA1BE /* frmAboutWindow.xib */; };
@ -68,7 +73,7 @@
6ACC3D442793701600F1B140 /* ParselessPhraseDB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6ACC3D402793701600F1B140 /* ParselessPhraseDB.cpp */; };
6ACC3D452793701600F1B140 /* ParselessLM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6ACC3D422793701600F1B140 /* ParselessLM.cpp */; };
D41355D8278D74B5005E5CBD /* mgrLangModel.mm in Sources */ = {isa = PBXBuildFile; fileRef = D41355D7278D7409005E5CBD /* mgrLangModel.mm */; };
D41355DB278E6D17005E5CBD /* vChewingLM.mm in Sources */ = {isa = PBXBuildFile; fileRef = D41355D9278E6D17005E5CBD /* vChewingLM.mm */; };
D41355DB278E6D17005E5CBD /* LMInstantiator.mm in Sources */ = {isa = PBXBuildFile; fileRef = D41355D9278E6D17005E5CBD /* LMInstantiator.mm */; };
D41355DE278EA3ED005E5CBD /* UserPhrasesLM.mm in Sources */ = {isa = PBXBuildFile; fileRef = D41355DC278EA3ED005E5CBD /* UserPhrasesLM.mm */; };
D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D427F76B278CA1BA004A2160 /* AppDelegate.swift */; };
D44FB74D2792189A003C80A6 /* PhraseReplacementMap.mm in Sources */ = {isa = PBXBuildFile; fileRef = D44FB74B2792189A003C80A6 /* PhraseReplacementMap.mm */; };
@ -96,6 +101,13 @@
remoteGlobalIDString = 5BD05BB727B2A429004C4F1D;
remoteInfo = vChewingPhraseEditor;
};
5BDC5CBB27C28E8B00E1CCE2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 6A0D4E9415FC0CFA00ABF4B3 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 5BDC5CAF27C28E8B00E1CCE2;
remoteInfo = KeyboardExtension;
};
6A38BC2515FC131100A8A51F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 6A0D4E9415FC0CFA00ABF4B3 /* Project object */;
@ -112,6 +124,20 @@
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
5BDC5CBE27C28E8B00E1CCE2 /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
5BDC5CBD27C28E8B00E1CCE2 /* KeyboardExtension.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
5B04305327B529D800CB65BC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
5B04305427B529D800CB65BC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
@ -195,6 +221,13 @@
5BD05C6327B2BBEF004C4F1D /* Content.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Content.swift; sourceTree = "<group>"; };
5BD05C6427B2BBEF004C4F1D /* WindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowController.swift; sourceTree = "<group>"; };
5BD05C6527B2BBEF004C4F1D /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
5BDC5CAA27C2873D00E1CCE2 /* Grid.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Grid.mm; sourceTree = "<group>"; };
5BDC5CB027C28E8B00E1CCE2 /* KeyboardExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = KeyboardExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
5BDC5CB227C28E8B00E1CCE2 /* icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = icon.icns; sourceTree = "<group>"; };
5BDC5CB427C28E8B00E1CCE2 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
5BDC5CB727C28E8B00E1CCE2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/ShareViewController.xib; sourceTree = "<group>"; };
5BDC5CB927C28E8B00E1CCE2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
5BDC5CBA27C28E8B00E1CCE2 /* KeyboardExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = KeyboardExtension.entitlements; sourceTree = "<group>"; };
5BDCBB4227B4F6C600D0CC59 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/MainMenu.strings"; sourceTree = "<group>"; };
5BDCBB4327B4F6C600D0CC59 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/frmAboutWindow.strings"; sourceTree = "<group>"; };
5BDCBB4527B4F6C600D0CC59 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings"; sourceTree = "<group>"; };
@ -243,8 +276,8 @@
6ACC3D432793701600F1B140 /* ParselessLM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParselessLM.h; sourceTree = "<group>"; };
D41355D6278D7409005E5CBD /* mgrLangModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mgrLangModel.h; sourceTree = "<group>"; };
D41355D7278D7409005E5CBD /* mgrLangModel.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = mgrLangModel.mm; sourceTree = "<group>"; };
D41355D9278E6D17005E5CBD /* vChewingLM.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = vChewingLM.mm; sourceTree = "<group>"; };
D41355DA278E6D17005E5CBD /* vChewingLM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = vChewingLM.h; sourceTree = "<group>"; };
D41355D9278E6D17005E5CBD /* LMInstantiator.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LMInstantiator.mm; sourceTree = "<group>"; };
D41355DA278E6D17005E5CBD /* LMInstantiator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LMInstantiator.h; sourceTree = "<group>"; };
D41355DC278EA3ED005E5CBD /* UserPhrasesLM.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UserPhrasesLM.mm; sourceTree = "<group>"; };
D41355DD278EA3ED005E5CBD /* UserPhrasesLM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UserPhrasesLM.h; sourceTree = "<group>"; };
D427A9BF25ED28CC005D43E0 /* vChewing-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "vChewing-Bridging-Header.h"; sourceTree = "<group>"; };
@ -280,6 +313,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
5BDC5CAD27C28E8B00E1CCE2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
6A0D4E9F15FC0D2D00ABF4B3 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -297,14 +337,6 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
5B30F10727BA501900484E24 /* KeyLayouts */ = {
isa = PBXGroup;
children = (
5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */,
);
path = KeyLayouts;
sourceTree = "<group>";
};
5B62A30127AE732800A19448 /* 3rdParty */ = {
isa = PBXGroup;
children = (
@ -423,12 +455,12 @@
5B62A32427AE757300A19448 /* LangModelRelated */ = {
isa = PBXGroup;
children = (
D41355D9278E6D17005E5CBD /* LMInstantiator.mm */,
D41355DA278E6D17005E5CBD /* LMInstantiator.h */,
D41355D6278D7409005E5CBD /* mgrLangModel.h */,
D495583A27A5C6C4006ADE1C /* mgrLangModel_Privates.h */,
D41355D7278D7409005E5CBD /* mgrLangModel.mm */,
5B62A32527AE758000A19448 /* SubLanguageModels */,
D41355D9278E6D17005E5CBD /* vChewingLM.mm */,
D41355DA278E6D17005E5CBD /* vChewingLM.h */,
);
path = LangModelRelated;
sourceTree = "<group>";
@ -459,7 +491,6 @@
5B62A33027AE78E500A19448 /* Resources */ = {
isa = PBXGroup;
children = (
5B30F10727BA501900484E24 /* KeyLayouts */,
6A0D4EEE15FC0DA600ABF4B3 /* Images */,
5BBBB76E27AED70B0023B93A /* MenuIcons */,
5BBBB75C27AED54C0023B93A /* SoundFiles */,
@ -596,6 +627,19 @@
path = Resources;
sourceTree = "<group>";
};
5BDC5CB127C28E8B00E1CCE2 /* KeyboardExtension */ = {
isa = PBXGroup;
children = (
5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */,
5BDC5CB227C28E8B00E1CCE2 /* icon.icns */,
5BDC5CB427C28E8B00E1CCE2 /* ShareViewController.swift */,
5BDC5CB627C28E8B00E1CCE2 /* ShareViewController.xib */,
5BDC5CB927C28E8B00E1CCE2 /* Info.plist */,
5BDC5CBA27C28E8B00E1CCE2 /* KeyboardExtension.entitlements */,
);
path = KeyboardExtension;
sourceTree = "<group>";
};
6A0D4E9215FC0CFA00ABF4B3 = {
isa = PBXGroup;
children = (
@ -603,6 +647,7 @@
6ACA41E715FC1D9000935EF6 /* Installer */,
6A0D4EC215FC0D3C00ABF4B3 /* Source */,
5BD05BB927B2A429004C4F1D /* UserPhraseEditor */,
5BDC5CB127C28E8B00E1CCE2 /* KeyboardExtension */,
6A0D4EA315FC0D2D00ABF4B3 /* Products */,
D47D73C127A7200500255A50 /* Frameworks */,
);
@ -614,6 +659,7 @@
6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */,
6ACA41CB15FC1D7500935EF6 /* vChewingInstaller.app */,
5BD05BB827B2A429004C4F1D /* vChewingPhraseEditor.app */,
5BDC5CB027C28E8B00E1CCE2 /* KeyboardExtension.appex */,
);
name = Products;
sourceTree = "<group>";
@ -663,6 +709,7 @@
6A0D4F1515FC0EB100ABF4B3 /* BlockReadingBuilder.h */,
6A0D4F1615FC0EB100ABF4B3 /* Gramambular.h */,
6A0D4F1715FC0EB100ABF4B3 /* Grid.h */,
5BDC5CAA27C2873D00E1CCE2 /* Grid.mm */,
6A0D4F1815FC0EB100ABF4B3 /* KeyValuePair.h */,
6A0D4F1915FC0EB100ABF4B3 /* LanguageModel.h */,
6A0D4F1A15FC0EB100ABF4B3 /* Node.h */,
@ -734,6 +781,23 @@
productReference = 5BD05BB827B2A429004C4F1D /* vChewingPhraseEditor.app */;
productType = "com.apple.product-type.application";
};
5BDC5CAF27C28E8B00E1CCE2 /* KeyboardExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5BDC5CC127C28E8B00E1CCE2 /* Build configuration list for PBXNativeTarget "KeyboardExtension" */;
buildPhases = (
5BDC5CAC27C28E8B00E1CCE2 /* Sources */,
5BDC5CAD27C28E8B00E1CCE2 /* Frameworks */,
5BDC5CAE27C28E8B00E1CCE2 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = KeyboardExtension;
productName = KeyboardExtension;
productReference = 5BDC5CB027C28E8B00E1CCE2 /* KeyboardExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
6A0D4EA115FC0D2D00ABF4B3 /* vChewing */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6A0D4EC015FC0D2E00ABF4B3 /* Build configuration list for PBXNativeTarget "vChewing" */;
@ -741,12 +805,14 @@
6A0D4E9E15FC0D2D00ABF4B3 /* Sources */,
6A0D4E9F15FC0D2D00ABF4B3 /* Frameworks */,
6A0D4EA015FC0D2D00ABF4B3 /* Resources */,
5BDC5CBE27C28E8B00E1CCE2 /* Embed App Extensions */,
);
buildRules = (
);
dependencies = (
5B0AF8B327B2C4E20096FE54 /* PBXTargetDependency */,
6A38BC2615FC131100A8A51F /* PBXTargetDependency */,
5BDC5CBC27C28E8B00E1CCE2 /* PBXTargetDependency */,
);
name = vChewing;
packageProductDependencies = (
@ -790,6 +856,10 @@
LastSwiftMigration = 1320;
ProvisioningStyle = Automatic;
};
5BDC5CAF27C28E8B00E1CCE2 = {
CreatedOnToolsVersion = 13.2;
ProvisioningStyle = Automatic;
};
6A0D4EA115FC0D2D00ABF4B3 = {
LastSwiftMigration = 1240;
ProvisioningStyle = Automatic;
@ -821,6 +891,7 @@
6A0D4EA115FC0D2D00ABF4B3 /* vChewing */,
6ACA41CA15FC1D7500935EF6 /* vChewingInstaller */,
5BD05BB727B2A429004C4F1D /* vChewingPhraseEditor */,
5BDC5CAF27C28E8B00E1CCE2 /* KeyboardExtension */,
6A38BC2115FC12FD00A8A51F /* Data */,
);
};
@ -838,6 +909,16 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
5BDC5CAE27C28E8B00E1CCE2 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5BDC5CB827C28E8B00E1CCE2 /* ShareViewController.xib in Resources */,
5BDC5CC227C2941F00E1CCE2 /* vChewingKeyLayout.bundle in Resources */,
5BDC5CB327C28E8B00E1CCE2 /* icon.icns in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
6A0D4EA015FC0D2D00ABF4B3 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -858,7 +939,6 @@
5BBBB77627AED70B0023B93A /* MenuIcon-TCVIM.png in Resources */,
6A187E2616004C5900466B2E /* MainMenu.xib in Resources */,
5BBBB75F27AED54C0023B93A /* Beep.m4a in Resources */,
5B30F11327BA568800484E24 /* vChewingKeyLayout.bundle in Resources */,
5B2DB16F27AF6891006D874E /* data-chs.txt in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -913,6 +993,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
5BDC5CAC27C28E8B00E1CCE2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5BDC5CB527C28E8B00E1CCE2 /* ShareViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
6A0D4E9E15FC0D2D00ABF4B3 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -937,12 +1025,13 @@
5B11328927B94CFB00E58451 /* AppleKeyboardConverter.swift in Sources */,
5B62A31827AE73A700A19448 /* zip.m in Sources */,
5B62A32E27AE78B000A19448 /* CNSLM.mm in Sources */,
D41355DB278E6D17005E5CBD /* vChewingLM.mm in Sources */,
D41355DB278E6D17005E5CBD /* LMInstantiator.mm in Sources */,
5B62A31A27AE73A700A19448 /* mztools.m in Sources */,
5B62A32927AE77D100A19448 /* FSEventStreamHelper.swift in Sources */,
D47F7DD3278C1263002F9DD7 /* UserOverrideModel.cpp in Sources */,
5B62A33627AE795800A19448 /* PreferencesModule.swift in Sources */,
5B62A33827AE79CD00A19448 /* NSStringUtils.swift in Sources */,
5BDC5CAB27C2873D00E1CCE2 /* Grid.mm in Sources */,
5B62A33227AE792F00A19448 /* InputSourceHelper.swift in Sources */,
5B62A34927AE7CD900A19448 /* TooltipController.swift in Sources */,
6A0D4F4515FC0EB100ABF4B3 /* Mandarin.cpp in Sources */,
@ -979,6 +1068,11 @@
target = 5BD05BB727B2A429004C4F1D /* vChewingPhraseEditor */;
targetProxy = 5B0AF8B227B2C4E20096FE54 /* PBXContainerItemProxy */;
};
5BDC5CBC27C28E8B00E1CCE2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5BDC5CAF27C28E8B00E1CCE2 /* KeyboardExtension */;
targetProxy = 5BDC5CBB27C28E8B00E1CCE2 /* PBXContainerItemProxy */;
};
6A38BC2615FC131100A8A51F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 6A38BC2115FC12FD00A8A51F /* Data */;
@ -1046,6 +1140,14 @@
name = Main.storyboard;
sourceTree = "<group>";
};
5BDC5CB627C28E8B00E1CCE2 /* ShareViewController.xib */ = {
isa = PBXVariantGroup;
children = (
5BDC5CB727C28E8B00E1CCE2 /* Base */,
);
name = ShareViewController.xib;
sourceTree = "<group>";
};
5BE78BDA27B37764005EA1BE /* frmAboutWindow.xib */ = {
isa = PBXVariantGroup;
children = (
@ -1147,7 +1249,7 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1922;
CURRENT_PROJECT_VERSION = 1923;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
@ -1166,7 +1268,7 @@
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.3.3;
MARKETING_VERSION = 1.3.4;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1199,7 +1301,7 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1922;
CURRENT_PROJECT_VERSION = 1923;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1213,7 +1315,7 @@
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.3.3;
MARKETING_VERSION = 1.3.4;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1225,6 +1327,102 @@
};
name = Release;
};
5BDC5CBF27C28E8B00E1CCE2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = KeyboardExtension/KeyboardExtension.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1923;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_ASSET_PATHS = KeyboardExtension/vChewingKeyLayout.bundle;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = KeyboardExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = KeyboardExtension;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 12.1;
MARKETING_VERSION = 1.3.4;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing.KeyboardExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
5BDC5CC027C28E8B00E1CCE2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = KeyboardExtension/KeyboardExtension.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1923;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_ASSET_PATHS = KeyboardExtension/vChewingKeyLayout.bundle;
DEVELOPMENT_TEAM = "";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = KeyboardExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = KeyboardExtension;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 12.1;
MARKETING_VERSION = 1.3.4;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing.KeyboardExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
};
name = Release;
};
6A0D4E9915FC0CFA00ABF4B3 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -1311,6 +1509,7 @@
6A0D4EBE15FC0D2E00ABF4B3 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
@ -1327,8 +1526,8 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1922;
DEVELOPMENT_ASSET_PATHS = Source/Resources/KeyLayouts/vChewingKeyLayout.bundle;
CURRENT_PROJECT_VERSION = 1923;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
@ -1359,7 +1558,7 @@
INFOPLIST_FILE = "Source/Resources/IME-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.3.3;
MARKETING_VERSION = 1.3.4;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1375,6 +1574,7 @@
6A0D4EBF15FC0D2E00ABF4B3 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
@ -1391,9 +1591,9 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1922;
CURRENT_PROJECT_VERSION = 1923;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_ASSET_PATHS = Source/Resources/KeyLayouts/vChewingKeyLayout.bundle;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
@ -1417,7 +1617,7 @@
INFOPLIST_FILE = "Source/Resources/IME-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.3.3;
MARKETING_VERSION = 1.3.4;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -1500,7 +1700,7 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1922;
CURRENT_PROJECT_VERSION = 1923;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
@ -1522,7 +1722,7 @@
INFOPLIST_FILE = "Installer/Installer-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.3.3;
MARKETING_VERSION = 1.3.4;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1550,7 +1750,7 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1922;
CURRENT_PROJECT_VERSION = 1923;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1566,7 +1766,7 @@
INFOPLIST_FILE = "Installer/Installer-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
MARKETING_VERSION = 1.3.3;
MARKETING_VERSION = 1.3.4;
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -1589,6 +1789,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
5BDC5CC127C28E8B00E1CCE2 /* Build configuration list for PBXNativeTarget "KeyboardExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5BDC5CBF27C28E8B00E1CCE2 /* Debug */,
5BDC5CC027C28E8B00E1CCE2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6A0D4E9715FC0CFA00ABF4B3 /* Build configuration list for PBXProject "vChewing" */ = {
isa = XCConfigurationList;
buildConfigurations = (