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 f7116ad260
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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"> <window title="vChewing Installer" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" animationBehavior="default" titlebarAppearsTransparent="YES" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/> <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<rect key="contentRect" x="335" y="390" width="533" height="457"/> <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="minSize" type="size" width="533" height="457"/>
<value key="maxSize" type="size" width="533" height="457"/> <value key="maxSize" type="size" width="533" height="457"/>
<view key="contentView" id="372"> <view key="contentView" id="372">
@ -271,7 +271,6 @@ Gw
<connections> <connections>
<outlet property="appCopyrightLabel" destination="03l-rN-zf9" id="XS5-cZ-k9H"/> <outlet property="appCopyrightLabel" destination="03l-rN-zf9" id="XS5-cZ-k9H"/>
<outlet property="appEULAContent" destination="47J-tO-8TZ" id="kRU-X2-8kX"/> <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="appVersionLabel" destination="z1m-8k-Z63" id="75X-uy-0Iz"/>
<outlet property="cancelButton" destination="592" id="710"/> <outlet property="cancelButton" destination="592" id="710"/>
<outlet property="installButton" destination="575" id="709"/> <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"> <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"/> <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="283" y="305" width="480" height="180"/> <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"> <view key="contentView" id="wAe-c8-Vh9">
<rect key="frame" x="0.0" y="0.0" width="480" height="180"/> <rect key="frame" x="0.0" y="0.0" width="480" height="180"/>
<autoresizingMask key="autoresizingMask"/> <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> <string>vChewingKeyLayout</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0</string> <string>1.0</string>
<key>KLInfo_Zhuyin Dachen</key> <key>KLInfo_vChewingDachen</key>
<dict> <dict>
<key>TICapsLockLanguageSwitchCapable</key> <key>TICapsLockLanguageSwitchCapable</key>
<false/> <false/>
<key>TISInputSourceID</key> <key>TISInputSourceID</key>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyindachen</string> <string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingDachen</string>
<key>TISIntendedLanguage</key> <key>TISIntendedLanguage</key>
<string>zh-Hanb</string> <string>zh-Hanb</string>
</dict> </dict>
<key>KLInfo_Zhuyin ETen</key> <key>KLInfo_vChewingETen</key>
<dict> <dict>
<key>TICapsLockLanguageSwitchCapable</key> <key>TICapsLockLanguageSwitchCapable</key>
<false/> <false/>
<key>TISInputSourceID</key> <key>TISInputSourceID</key>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyineten</string> <string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingETen</string>
<key>TISIntendedLanguage</key> <key>TISIntendedLanguage</key>
<string>zh-Hanb</string> <string>zh-Hanb</string>
</dict> </dict>
<key>KLInfo_Zhuyin IBM</key> <key>KLInfo_vChewingIBM</key>
<dict> <dict>
<key>TICapsLockLanguageSwitchCapable</key> <key>TICapsLockLanguageSwitchCapable</key>
<false/> <false/>
<key>TISInputSourceID</key> <key>TISInputSourceID</key>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyinibm</string> <string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingIBM</string>
<key>TISIntendedLanguage</key> <key>TISIntendedLanguage</key>
<string>zh-Hanb</string> <string>zh-Hanb</string>
</dict> </dict>
<key>KLInfo_Zhuyin MiTAC</key> <key>KLInfo_vChewingMiTAC</key>
<dict> <dict>
<key>TICapsLockLanguageSwitchCapable</key> <key>TICapsLockLanguageSwitchCapable</key>
<false/> <false/>
<key>TISInputSourceID</key> <key>TISInputSourceID</key>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyinmitac</string> <string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingMiTAC</string>
<key>TISIntendedLanguage</key> <key>TISIntendedLanguage</key>
<string>zh-Hanb</string> <string>zh-Hanb</string>
</dict> </dict>
<key>KLInfo_Zhuyin Seigyou</key> <key>KLInfo_vChewingSeigyou</key>
<dict> <dict>
<key>TICapsLockLanguageSwitchCapable</key> <key>TICapsLockLanguageSwitchCapable</key>
<false/> <false/>
<key>TISInputSourceID</key> <key>TISInputSourceID</key>
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyinseigyou</string> <string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingSeigyou</string>
<key>TISIntendedLanguage</key> <key>TISIntendedLanguage</key>
<string>zh-Hanb</string> <string>zh-Hanb</string>
</dict> </dict>

View File

@ -1,7 +1,7 @@
<?xml version="1.1" encoding="UTF-8"?> <?xml version="1.1" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd"> <!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)--> <!--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> <layouts>
<layout first="0" last="17" mapSet="16c" modifiers="f4"/> <layout first="0" last="17" mapSet="16c" modifiers="f4"/>
<layout first="18" last="18" mapSet="a88" modifiers="f4"/> <layout first="18" last="18" mapSet="a88" modifiers="f4"/>

View File

@ -1,7 +1,7 @@
<?xml version="1.1" encoding="UTF-8"?> <?xml version="1.1" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd"> <!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)--> <!--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> <layouts>
<layout first="0" last="17" mapSet="16c" modifiers="f4"/> <layout first="0" last="17" mapSet="16c" modifiers="f4"/>
<layout first="18" last="18" mapSet="a88" modifiers="f4"/> <layout first="18" last="18" mapSet="a88" modifiers="f4"/>

View File

@ -1,7 +1,7 @@
<?xml version="1.1" encoding="UTF-8"?> <?xml version="1.1" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd"> <!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)--> <!--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> <layouts>
<layout first="0" last="17" mapSet="16c" modifiers="f4"/> <layout first="0" last="17" mapSet="16c" modifiers="f4"/>
<layout first="18" last="18" mapSet="a88" modifiers="f4"/> <layout first="18" last="18" mapSet="a88" modifiers="f4"/>

View File

@ -1,7 +1,7 @@
<?xml version="1.1" encoding="UTF-8"?> <?xml version="1.1" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd"> <!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)--> <!--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> <layouts>
<layout first="0" last="17" mapSet="16c" modifiers="f4"/> <layout first="0" last="17" mapSet="16c" modifiers="f4"/>
<layout first="18" last="18" mapSet="a88" modifiers="f4"/> <layout first="18" last="18" mapSet="a88" modifiers="f4"/>

View File

@ -1,7 +1,7 @@
<?xml version="1.1" encoding="UTF-8"?> <?xml version="1.1" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd"> <!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)--> <!--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> <layouts>
<layout first="0" last="17" mapSet="16c" modifiers="f4"/> <layout first="0" last="17" mapSet="16c" modifiers="f4"/>
<layout first="18" last="18" mapSet="a88" 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) @objc(AppDelegate)
class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelegate, FSEventStreamHelperDelegate { class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelegate, FSEventStreamHelperDelegate {
func helper(_ helper: FSEventStreamHelper, didReceive events: [FSEventStreamHelper.Event]) { func helper(_ helper: FSEventStreamHelper, didReceive events: [FSEventStreamHelper.Event]) {
// 使使 // 100ms 使使
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) {
if Preferences.shouldAutoReloadUserDataFiles { if Preferences.shouldAutoReloadUserDataFiles {
mgrLangModel.loadUserPhrases() mgrLangModel.loadUserPhrases()
mgrLangModel.loadUserPhraseReplacement() mgrLangModel.loadUserPhraseReplacement()
@ -159,7 +159,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega
private var ctlAboutWindowInstance: ctlAboutWindow? // New About Window private var ctlAboutWindowInstance: ctlAboutWindow? // New About Window
private var checkTask: URLSessionTask? private var checkTask: URLSessionTask?
private var updateNextStepURL: URL? 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 // dealloc
deinit { deinit {

View File

@ -182,9 +182,9 @@ class InputState: NSObject {
let (exactEnd, _) = (composingBuffer as NSString).characterIndex(from: markedRange.location + markedRange.length) let (exactEnd, _) = (composingBuffer as NSString).characterIndex(from: markedRange.location + markedRange.length)
let selectedReadings = readings[exactBegin..<exactEnd] let selectedReadings = readings[exactBegin..<exactEnd]
let joined = selectedReadings.joined(separator: "-") 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 { 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) return String(format: NSLocalizedString("\"%@\" selected. ENTER to add user phrase.", comment: ""), text)
@ -246,12 +246,16 @@ class InputState: NSObject {
if markedRange.length > kMaxMarkRangeLength { if markedRange.length > kMaxMarkRangeLength {
return false return false
} }
return markedRange.length >= kMinMarkRangeLength && markedRange.length <= kMaxMarkRangeLength
}
@objc var chkIfUserPhraseExists: Bool {
let text = (composingBuffer as NSString).substring(with: markedRange) let text = (composingBuffer as NSString).substring(with: markedRange)
let (exactBegin, _) = (composingBuffer as NSString).characterIndex(from: markedRange.location) let (exactBegin, _) = (composingBuffer as NSString).characterIndex(from: markedRange.location)
let (exactEnd, _) = (composingBuffer as NSString).characterIndex(from: markedRange.location + markedRange.length) let (exactEnd, _) = (composingBuffer as NSString).characterIndex(from: markedRange.location + markedRange.length)
let selectedReadings = readings[exactBegin..<exactEnd] let selectedReadings = readings[exactBegin..<exactEnd]
let joined = selectedReadings.joined(separator: "-") 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 { @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. 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 "Gramambular.h"
#import "vChewingLM.h"
#import "UserOverrideModel.h"
#import "mgrLangModel_Privates.h"
#import "KeyHandler.h" #import "KeyHandler.h"
#import "LMInstantiator.h"
#import "Mandarin.h"
#import "mgrLangModel_Privates.h"
#import "UserOverrideModel.h"
#import "vChewing-Swift.h" #import "vChewing-Swift.h"
#import <string> #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 imeModeCHT = @"org.atelierInmu.inputmethod.vChewing.IMECHT";
InputMode imeModeCHS = @"org.atelierInmu.inputmethod.vChewing.IMECHS"; InputMode imeModeCHS = @"org.atelierInmu.inputmethod.vChewing.IMECHS";
InputMode imeModeNULL = @"org.atelierInmu.inputmethod.vChewing.IMENULL"; InputMode imeModeNULL = @"org.atelierInmu.inputmethod.vChewing.IMENULL";
static const double kEpsilon = 0.000001; 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; double highestScore = 0.0;
for (auto ni = nodes.begin(), ne = nodes.end(); ni != ne; ++ni) { for (auto ni = nodes.begin(), ne = nodes.end(); ni != ne; ++ni) {
double score = ni->node->highestUnigramScore(); double score = ni->node->highestUnigramScore();
@ -49,16 +44,15 @@ static double FindHighestScore(const vector<NodeAnchor> &nodes, double epsilon)
return highestScore + epsilon; return highestScore + epsilon;
} }
// sort helper class NodeAnchorDescendingSorter {
class NodeAnchorDescendingSorter
{
public: 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(); 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 // specified path every time the grid is walked
#if DEBUG #if DEBUG
static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
@ -71,7 +65,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
Taiyan::Mandarin::BopomofoReadingBuffer *_bpmfReadingBuffer; Taiyan::Mandarin::BopomofoReadingBuffer *_bpmfReadingBuffer;
// language model // language model
vChewing::vChewingLM *_languageModel; vChewing::LMInstantiator *_languageModel;
// user override model // user override model
vChewing::UserOverrideModel *_userOverrideModel; vChewing::UserOverrideModel *_userOverrideModel;
@ -96,8 +90,8 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
- (void)setInputMode:(NSString *)value - (void)setInputMode:(NSString *)value
{ {
NSString *newInputMode; NSString *newInputMode;
vChewingLM *newLanguageModel; vChewing::LMInstantiator *newLanguageModel;
UserOverrideModel *newUserOverrideModel; vChewing::UserOverrideModel *newUserOverrideModel;
if ([value isKindOfClass:[NSString class]] && [value isEqual:imeModeCHS]) { if ([value isKindOfClass:[NSString class]] && [value isEqual:imeModeCHS]) {
newInputMode = imeModeCHS; newInputMode = imeModeCHS;
@ -120,7 +114,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
if (_builder) { if (_builder) {
delete _builder; delete _builder;
_builder = new BlockReadingBuilder(_languageModel); _builder = new Taiyan::Gramambular::BlockReadingBuilder(_languageModel);
_builder->setJoinSeparator("-"); _builder->setJoinSeparator("-");
} }
@ -146,7 +140,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
{ {
self = [super init]; self = [super init];
if (self) { if (self) {
_bpmfReadingBuffer = new BopomofoReadingBuffer(BopomofoKeyboardLayout::StandardLayout()); _bpmfReadingBuffer = new Taiyan::Mandarin::BopomofoReadingBuffer(Taiyan::Mandarin::BopomofoKeyboardLayout::StandardLayout());
// create the lattice builder // create the lattice builder
_languageModel = [mgrLangModel lmCHT]; _languageModel = [mgrLangModel lmCHT];
@ -154,7 +148,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
_languageModel->setCNSEnabled(Preferences.cns11643Enabled); _languageModel->setCNSEnabled(Preferences.cns11643Enabled);
_userOverrideModel = [mgrLangModel userOverrideModelCHT]; _userOverrideModel = [mgrLangModel userOverrideModelCHT];
_builder = new BlockReadingBuilder(_languageModel); _builder = new Taiyan::Gramambular::BlockReadingBuilder(_languageModel);
// each Mandarin syllable is separated by a hyphen // each Mandarin syllable is separated by a hyphen
_builder->setJoinSeparator("-"); _builder->setJoinSeparator("-");
@ -168,31 +162,31 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
NSInteger layout = Preferences.keyboardLayout; NSInteger layout = Preferences.keyboardLayout;
switch (layout) { switch (layout) {
case KeyboardLayoutStandard: case KeyboardLayoutStandard:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::StandardLayout()); _bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::StandardLayout());
break; break;
case KeyboardLayoutEten: case KeyboardLayoutEten:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::ETenLayout()); _bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::ETenLayout());
break; break;
case KeyboardLayoutHsu: case KeyboardLayoutHsu:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::HsuLayout()); _bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::HsuLayout());
break; break;
case KeyboardLayoutEten26: case KeyboardLayoutEten26:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::ETen26Layout()); _bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::ETen26Layout());
break; break;
case KeyboardLayoutIBM: case KeyboardLayoutIBM:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::IBMLayout()); _bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::IBMLayout());
break; break;
case KeyboardLayoutMiTAC: case KeyboardLayoutMiTAC:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::MiTACLayout()); _bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::MiTACLayout());
break; break;
case KeyboardLayoutFakeSeigyou: case KeyboardLayoutFakeSeigyou:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::FakeSeigyouLayout()); _bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::FakeSeigyouLayout());
break; break;
case KeyboardLayoutHanyuPinyin: case KeyboardLayoutHanyuPinyin:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::HanyuPinyinLayout()); _bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::HanyuPinyinLayout());
break; break;
default: default:
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::StandardLayout()); _bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::StandardLayout());
Preferences.keyboardLayout = KeyboardLayoutStandard; Preferences.keyboardLayout = KeyboardLayoutStandard;
} }
} }
@ -200,8 +194,8 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
- (void)fixNodeWithValue:(NSString *)value - (void)fixNodeWithValue:(NSString *)value
{ {
size_t cursorIndex = [self _actualCandidateCursorIndex]; size_t cursorIndex = [self _actualCandidateCursorIndex];
string stringValue = [value UTF8String]; std::string stringValue(value.UTF8String);
NodeAnchor selectedNode = _builder->grid().fixNodeSelectedCandidate(cursorIndex, stringValue); Taiyan::Gramambular::NodeAnchor selectedNode = _builder->grid().fixNodeSelectedCandidate(cursorIndex, stringValue);
if (!Preferences.useSCPCTypingMode) { // 不要針對逐字選字模式啟用臨時半衰記憶模型。 if (!Preferences.useSCPCTypingMode) { // 不要針對逐字選字模式啟用臨時半衰記憶模型。
// If the length of the readings and the characters do not match, // 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 // 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(); _walkedNodes.clear();
} }
- (string)_currentLayout - (std::string)_currentLayout
{ {
NSString *keyboardLayoutName = Preferences.keyboardLayoutName; NSString *keyboardLayoutName = Preferences.keyboardLayoutName;
string layout = string(keyboardLayoutName.UTF8String) + string("_"); std::string layout = std::string(keyboardLayoutName.UTF8String) + std::string("_");
return layout; return layout;
} }
@ -348,7 +342,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
composeReading |= (!_bpmfReadingBuffer->isEmpty() && ([input isSpace] || [input isEnterCharCode] || [input isEnter])); composeReading |= (!_bpmfReadingBuffer->isEmpty() && ([input isSpace] || [input isEnterCharCode] || [input isEnter]));
if (composeReading) { if (composeReading) {
// combine the reading // combine the reading
string reading = _bpmfReadingBuffer->syllable().composedString(); std::string reading = _bpmfReadingBuffer->syllable().composedString();
// see if we have a unigram for this // see if we have a unigram for this
if (!_languageModel->hasUnigramsForKey(reading)) { if (!_languageModel->hasUnigramsForKey(reading)) {
@ -365,12 +359,12 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
NSString *poppedText = [self _popOverflowComposingTextAndWalk]; NSString *poppedText = [self _popOverflowComposingTextAndWalk];
// get user override model suggestion // get user override model suggestion
string overrideValue = (Preferences.useSCPCTypingMode) ? "" : std::string overrideValue = (Preferences.useSCPCTypingMode) ? "" :
_userOverrideModel->suggest(_walkedNodes, _builder->cursorIndex(), [[NSDate date] timeIntervalSince1970]); _userOverrideModel->suggest(_walkedNodes, _builder->cursorIndex(), [[NSDate date] timeIntervalSince1970]);
if (!overrideValue.empty()) { if (!overrideValue.empty()) {
size_t cursorIndex = [self _actualCandidateCursorIndex]; 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); double highestScore = FindHighestScore(nodes, kEpsilon);
_builder->grid().overrideNodeScoreForSelectedCandidate(cursorIndex, overrideValue, static_cast<float>(highestScore)); _builder->grid().overrideNodeScoreForSelectedCandidate(cursorIndex, overrideValue, static_cast<float>(highestScore));
} }
@ -521,7 +515,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
InputStateSymbolTable *symbolState = [[InputStateSymbolTable alloc] initWithNode:root useVerticalMode:input.useVerticalMode]; InputStateSymbolTable *symbolState = [[InputStateSymbolTable alloc] initWithNode:root useVerticalMode:input.useVerticalMode];
stateCallback(symbolState); stateCallback(symbolState);
return YES; return YES;
// if (_languageModel->hasUnigramsForKey(string("_punctuation_list"))) { // if (_languageModel->hasUnigramsForKey("_punctuation_list"))) {
// if (_bpmfReadingBuffer->isEmpty()) { // if (_bpmfReadingBuffer->isEmpty()) {
// _builder->insertReadingAtCursor(string("_punctuation_list")); // _builder->insertReadingAtCursor(string("_punctuation_list"));
// NSString *poppedText = [self _popOverflowComposingTextAndWalk]; // NSString *poppedText = [self _popOverflowComposingTextAndWalk];
@ -540,28 +534,30 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
// MARK: Punctuation // MARK: Punctuation
// if nothing is matched, see if it's a punctuation key for current layout. // if nothing is matched, see if it's a punctuation key for current layout.
string punctuationNamePrefix; std::string punctuationNamePrefix;
if ([input isControlHold]) { if ([input isControlHold]) {
punctuationNamePrefix = string("_ctrl_punctuation_"); punctuationNamePrefix = std::string("_ctrl_punctuation_");
} else if (Preferences.halfWidthPunctuationEnabled) { } else if (Preferences.halfWidthPunctuationEnabled) {
punctuationNamePrefix = string("_half_punctuation_"); punctuationNamePrefix = std::string("_half_punctuation_");
} else { } else {
punctuationNamePrefix = string("_punctuation_"); punctuationNamePrefix = std::string("_punctuation_");
} }
string layout = [self _currentLayout]; std::string layout = [self _currentLayout];
string customPunctuation = punctuationNamePrefix + layout + string(1, (char) charCode); std::string customPunctuation = punctuationNamePrefix + layout + std::string(1, (char) charCode);
if ([self _handlePunctuation:customPunctuation state:state usingVerticalMode:input.useVerticalMode stateCallback:stateCallback errorCallback:errorCallback]) { if ([self _handlePunctuation:customPunctuation state:state usingVerticalMode:input.useVerticalMode stateCallback:stateCallback errorCallback:errorCallback]) {
return YES; return YES;
} }
// if nothing is matched, see if it's a punctuation key. // 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]) { if ([self _handlePunctuation:punctuation state:state usingVerticalMode:input.useVerticalMode stateCallback:stateCallback errorCallback:errorCallback]) {
return YES; return YES;
} }
if ((char) charCode >= 'A' && (char) charCode <= 'Z') { // Lukhnos 這裡的處理反而會使得 Apple 倚天注音動態鍵盤佈局「敲不了半形大寫英文」的缺點曝露無疑,所以注釋掉。
string letter = string("_letter_") + string(1, (char) charCode); // 至於他試圖用這種處理來解決的上游 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]) { if ([self _handlePunctuation:letter state:state usingVerticalMode:input.useVerticalMode stateCallback:stateCallback errorCallback:errorCallback]) {
return YES; return YES;
} }
@ -845,7 +841,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
return YES; 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)) { if (!_languageModel->hasUnigramsForKey(customPunctuation)) {
return NO; return NO;
@ -1150,23 +1146,23 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
} }
if (Preferences.useSCPCTypingMode) { if (Preferences.useSCPCTypingMode) {
string layout = [self _currentLayout]; std::string layout = [self _currentLayout];
string punctuationNamePrefix; std::string punctuationNamePrefix;
if ([input isControlHold]) { if ([input isControlHold]) {
punctuationNamePrefix = string("_ctrl_punctuation_"); punctuationNamePrefix = std::string("_ctrl_punctuation_");
} else if (Preferences.halfWidthPunctuationEnabled) { } else if (Preferences.halfWidthPunctuationEnabled) {
punctuationNamePrefix = string("_half_punctuation_"); punctuationNamePrefix = std::string("_half_punctuation_");
} else { } else {
punctuationNamePrefix = string("_punctuation_"); punctuationNamePrefix = std::string("_punctuation_");
} }
string customPunctuation = punctuationNamePrefix + layout + string(1, (char) charCode); std::string customPunctuation = punctuationNamePrefix + layout + std::string(1, (char) charCode);
string punctuation = punctuationNamePrefix + string(1, (char) charCode); std::string punctuation = punctuationNamePrefix + std::string(1, (char) charCode);
BOOL shouldAutoSelectCandidate = _bpmfReadingBuffer->isValidKey((char) charCode) || _languageModel->hasUnigramsForKey(customPunctuation) || BOOL shouldAutoSelectCandidate = _bpmfReadingBuffer->isValidKey((char) charCode) || _languageModel->hasUnigramsForKey(customPunctuation) ||
_languageModel->hasUnigramsForKey(punctuation); _languageModel->hasUnigramsForKey(punctuation);
if (!shouldAutoSelectCandidate && (char) charCode >= 'A' && (char) charCode <= 'Z') { 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)) { if (_languageModel->hasUnigramsForKey(letter)) {
shouldAutoSelectCandidate = YES; 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 // 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 // i.e. we need to take UTF-16 into consideration, for which a surrogate pair takes 2 UniChars
// locations // 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) { if ((*wi).node) {
string nodeStr = (*wi).node->currentKeyValue().value; std::string nodeStr = (*wi).node->currentKeyValue().value;
NSString *valueString = [NSString stringWithUTF8String:nodeStr.c_str()]; NSString *valueString = [NSString stringWithUTF8String:nodeStr.c_str()];
[composingBuffer appendString:valueString]; [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 // retrieve the most likely trellis, i.e. a Maximum Likelihood Estimation
// of the best possible Mandarain characters given the input syllables, // of the best possible Mandarain characters given the input syllables,
// using the Viterbi algorithm implemented in the Gramambular library // 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 // the reverse walk traces the trellis from the end
_walkedNodes = walker.reverseWalk(_builder->grid().width()); _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 is defined, a GraphViz file is written to kGraphVizOutputfile
#if DEBUG #if DEBUG
string dotDump = _builder->grid().dumpDOT(); std::string dotDump = _builder->grid().dumpDOT();
NSString *dotStr = [NSString stringWithUTF8String:dotDump.c_str()]; NSString *dotStr = [NSString stringWithUTF8String:dotDump.c_str()];
NSError *error = nil; NSError *error = nil;
@ -1307,7 +1303,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
if (_builder->grid().width() > (size_t) composingBufferSize) { if (_builder->grid().width() > (size_t) composingBufferSize) {
if (_walkedNodes.size() > 0) { if (_walkedNodes.size() > 0) {
NodeAnchor &anchor = _walkedNodes[0]; Taiyan::Gramambular::NodeAnchor &anchor = _walkedNodes[0];
poppedText = [NSString stringWithUTF8String:anchor.node->currentKeyValue().value.c_str()]; poppedText = [NSString stringWithUTF8String:anchor.node->currentKeyValue().value.c_str()];
_builder->removeHeadReadings(anchor.spanningLength); _builder->removeHeadReadings(anchor.spanningLength);
} }
@ -1322,15 +1318,15 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
NSMutableArray *candidatesArray = [[NSMutableArray alloc] init]; NSMutableArray *candidatesArray = [[NSMutableArray alloc] init];
size_t cursorIndex = [self _actualCandidateCursorIndex]; 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 // 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()); stable_sort(nodes.begin(), nodes.end(), NodeAnchorDescendingSorter());
// then use the C++ trick to retrieve the candidates for each node at/crossing the cursor // 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) { for (std::vector<Taiyan::Gramambular::NodeAnchor>::iterator ni = nodes.begin(), ne = nodes.end(); ni != ne; ++ni) {
const vector<KeyValuePair> &candidates = (*ni).node->candidates(); const std::vector<Taiyan::Gramambular::KeyValuePair> &candidates = (*ni).node->candidates();
for (vector<KeyValuePair>::const_iterator ci = candidates.begin(), ce = candidates.end(); ci != ce; ++ci) { 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()]]; [candidatesArray addObject:[NSString stringWithUTF8String:(*ci).value.c_str()]];
} }
} }
@ -1359,8 +1355,8 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
- (NSArray *)_currentReadings - (NSArray *)_currentReadings
{ {
NSMutableArray *readingsArray = [[NSMutableArray alloc] init]; NSMutableArray *readingsArray = [[NSMutableArray alloc] init];
vector<std::string> v = _builder->readings(); std::vector<std::string> v = _builder->readings();
for (vector<std::string>::iterator it_i = v.begin(); it_i != v.end(); ++it_i) { for (std::vector<std::string>::iterator it_i = v.begin(); it_i != v.end(); ++it_i) {
[readingsArray addObject:[NSString stringWithUTF8String:it_i->c_str()]]; [readingsArray addObject:[NSString stringWithUTF8String:it_i->c_str()]];
} }
return readingsArray; return readingsArray;
@ -1368,9 +1364,9 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
- (nullable InputState *)buildAssociatePhraseStateWithKey:(NSString *)key useVerticalMode:(BOOL)useVerticalMode - (nullable InputState *)buildAssociatePhraseStateWithKey:(NSString *)key useVerticalMode:(BOOL)useVerticalMode
{ {
string cppKey = string(key.UTF8String); std::string cppKey = std::string(key.UTF8String);
if (_languageModel->hasAssociatedPhrasesForKey(cppKey)) { if (_languageModel->hasAssociatedPhrasesForKey(cppKey)) {
vector<string> phrases = _languageModel->associatedPhrasesForKey(cppKey); std::vector<std::string> phrases = _languageModel->associatedPhrasesForKey(cppKey);
NSMutableArray <NSString *> *array = [NSMutableArray array]; NSMutableArray <NSString *> *array = [NSMutableArray array];
for (auto phrase: phrases) { for (auto phrase: phrases) {
NSString *item = [[NSString alloc] initWithUTF8String:phrase.c_str()]; NSString *item = [[NSString alloc] initWithUTF8String:phrase.c_str()];

View File

@ -37,7 +37,7 @@ class LMConsolidator
public: public:
static bool CheckPragma(const char *path); static bool CheckPragma(const char *path);
static bool FixEOF(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 } // namespace vChewing

View File

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

View File

@ -47,6 +47,13 @@ class ctlInputMethod: IMKInputController {
private var keyHandler: KeyHandler = KeyHandler() private var keyHandler: KeyHandler = KeyHandler()
private var state: InputState = InputState.Empty() private var state: InputState = InputState.Empty()
// keyHandler 調 keyHandler
// InputState ctlInputMethod
// keyHandler keyHandlerInput
// currentKeyHandler keyHandler
// currentKeyHandler
static var currentKeyHandler: KeyHandler = KeyHandler()
// MARK: - IMKInputController methods // MARK: - IMKInputController methods
override init!(server: IMKServer!, delegate: Any!, client inputClient: Any!) { override init!(server: IMKServer!, delegate: Any!, client inputClient: Any!) {
@ -157,6 +164,8 @@ class ctlInputMethod: IMKInputController {
keyHandler.inputMode = newInputMode keyHandler.inputMode = newInputMode
self.handle(state: .Empty(), client: client) self.handle(state: .Empty(), client: client)
} }
//
ctlInputMethod.currentKeyHandler.inputMode = keyHandler.inputMode
} }
// MARK: - IMKServerInput protocol methods // MARK: - IMKServerInput protocol methods
@ -603,7 +612,7 @@ extension ctlInputMethod: KeyHandlerDelegate {
if !state.validToWrite { if !state.validToWrite {
return false return false
} }
mgrLangModel.writeUserPhrase(state.userPhrase, inputMode: keyHandler.inputMode) mgrLangModel.writeUserPhrase(state.userPhrase, inputMode: keyHandler.inputMode, areWeDuplicating: state.chkIfUserPhraseExists)
return true 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. 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 #ifndef LMInstantiator_H
#define VCHEWINGLM_H #define LMInstantiator_H
#include <stdio.h>
#include "UserPhrasesLM.h"
#include "ParselessLM.h"
#include "CNSLM.h"
#include "PhraseReplacementMap.h"
#include "AssociatedPhrases.h" #include "AssociatedPhrases.h"
#include "CNSLM.h"
#include "ParselessLM.h"
#include "PhraseReplacementMap.h"
#include "UserPhrasesLM.h"
#include <stdio.h>
#include <unordered_set> #include <unordered_set>
namespace vChewing { namespace vChewing {
using namespace Taiyan::Gramambular; 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. /// the input method language model, user phrases and excluded phrases.
/// ///
/// It is the primary model class that the input controller and grammar builder /// 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 /// if there are valid unigrams, and use returned unigrams to produce the final
/// results. /// 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 /// model and user phrases. The process is
/// ///
/// 1) Get the original unigrams. /// 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 /// 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 /// 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. /// you have to pass the paths when you ask it to do loading.
class vChewingLM : public LanguageModel { class LMInstantiator : public Taiyan::Gramambular::LanguageModel {
public: public:
vChewingLM(); LMInstantiator();
~vChewingLM(); ~LMInstantiator();
/// Asks to load the primary language model at the given path. /// Asks to load the primary language model at the given path.
/// @param languageModelPath The path of the language model. /// @param languageModelPath The path of the language model.
@ -83,14 +83,14 @@ public:
void loadPhraseReplacementMap(const char* phraseReplacementPath); void loadPhraseReplacementMap(const char* phraseReplacementPath);
/// Not implemented since we do not have data to provide bigram function. /// 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. /// 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. /// 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. /// If the model has unigrams for the given key.
/// @param key The key. /// @param key The key.
bool hasUnigramsForKey(const string& key); bool hasUnigramsForKey(const std::string& key);
/// Enables or disables phrase replacement. /// Enables or disables phrase replacement.
void setPhraseReplacementEnabled(bool enabled); void setPhraseReplacementEnabled(bool enabled);
@ -107,10 +107,10 @@ public:
/// If the external converted is enabled or not. /// If the external converted is enabled or not.
bool externalConverterEnabled(); bool externalConverterEnabled();
/// Sets a lambda to let the values of unigrams could be converted by it. /// 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); const std::vector<std::string> associatedPhrasesForKey(const std::string& key);
bool hasAssociatedPhrasesForKey(const string& key); bool hasAssociatedPhrasesForKey(const std::string& key);
protected: protected:
@ -121,9 +121,9 @@ protected:
/// @param insertedValues The values for unigrams already in the results. /// @param insertedValues The values for unigrams already in the results.
/// It helps to prevent duplicated unigrams. Please note that the method /// It helps to prevent duplicated unigrams. Please note that the method
/// has a side effect that it inserts values to `insertedValues`. /// has a side effect that it inserts values to `insertedValues`.
const vector<Unigram> filterAndTransformUnigrams(const vector<Unigram> unigrams, const std::vector<Taiyan::Gramambular::Unigram> filterAndTransformUnigrams(const std::vector<Taiyan::Gramambular::Unigram> unigrams,
const std::unordered_set<string>& excludedValues, const std::unordered_set<std::string>& excludedValues,
std::unordered_set<string>& insertedValues); std::unordered_set<std::string>& insertedValues);
ParselessLM m_languageModel; ParselessLM m_languageModel;
CNSLM m_cnsModel; CNSLM m_cnsModel;
@ -134,7 +134,7 @@ protected:
bool m_phraseReplacementEnabled; bool m_phraseReplacementEnabled;
bool m_cnsEnabled; bool m_cnsEnabled;
bool m_externalConverterEnabled; 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. 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 <algorithm>
#include <iterator> #include <iterator>
using namespace vChewing; namespace vChewing {
vChewingLM::vChewingLM() LMInstantiator::LMInstantiator()
{ {
} }
vChewingLM::~vChewingLM() LMInstantiator::~LMInstantiator()
{ {
m_languageModel.close(); m_languageModel.close();
m_userPhrases.close(); m_userPhrases.close();
@ -37,7 +37,7 @@ vChewingLM::~vChewingLM()
m_associatedPhrases.close(); m_associatedPhrases.close();
} }
void vChewingLM::loadLanguageModel(const char* languageModelDataPath) void LMInstantiator::loadLanguageModel(const char* languageModelDataPath)
{ {
if (languageModelDataPath) { if (languageModelDataPath) {
m_languageModel.close(); m_languageModel.close();
@ -45,12 +45,12 @@ void vChewingLM::loadLanguageModel(const char* languageModelDataPath)
} }
} }
bool vChewingLM::isDataModelLoaded() bool LMInstantiator::isDataModelLoaded()
{ {
return m_languageModel.isLoaded(); return m_languageModel.isLoaded();
} }
void vChewingLM::loadCNSData(const char* cnsDataPath) void LMInstantiator::loadCNSData(const char* cnsDataPath)
{ {
if (cnsDataPath) { if (cnsDataPath) {
m_cnsModel.close(); m_cnsModel.close();
@ -58,12 +58,12 @@ void vChewingLM::loadCNSData(const char* cnsDataPath)
} }
} }
bool vChewingLM::isCNSDataLoaded() bool LMInstantiator::isCNSDataLoaded()
{ {
return m_cnsModel.isLoaded(); return m_cnsModel.isLoaded();
} }
void vChewingLM::loadUserPhrases(const char* userPhrasesDataPath, void LMInstantiator::loadUserPhrases(const char* userPhrasesDataPath,
const char* excludedPhrasesDataPath) const char* excludedPhrasesDataPath)
{ {
if (userPhrasesDataPath) { 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) { if (userAssociatedPhrasesPath) {
m_associatedPhrases.close(); 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) { if (phraseReplacementPath) {
m_phraseReplacement.close(); m_phraseReplacement.close();
@ -92,16 +92,16 @@ 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 == " ") { if (key == " ") {
vector<Unigram> spaceUnigrams; std::vector<Taiyan::Gramambular::Unigram> spaceUnigrams;
Unigram g; Taiyan::Gramambular::Unigram g;
g.keyValue.key = " "; g.keyValue.key = " ";
g.keyValue.value = " "; g.keyValue.value = " ";
g.score = 0; g.score = 0;
@ -109,32 +109,32 @@ const vector<Unigram> vChewingLM::unigramsForKey(const string& key)
return spaceUnigrams; return spaceUnigrams;
} }
vector<Unigram> allUnigrams; std::vector<Taiyan::Gramambular::Unigram> allUnigrams;
vector<Unigram> userUnigrams; std::vector<Taiyan::Gramambular::Unigram> userUnigrams;
vector<Unigram> cnsUnigrams; std::vector<Taiyan::Gramambular::Unigram> cnsUnigrams;
unordered_set<string> excludedValues; std::unordered_set<std::string> excludedValues;
unordered_set<string> insertedValues; std::unordered_set<std::string> insertedValues;
if (m_excludedPhrases.hasUnigramsForKey(key)) { 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(), transform(excludedUnigrams.begin(), excludedUnigrams.end(),
inserter(excludedValues, excludedValues.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)) { 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); userUnigrams = filterAndTransformUnigrams(rawUserUnigrams, excludedValues, insertedValues);
} }
if (m_languageModel.hasUnigramsForKey(key)) { 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); allUnigrams = filterAndTransformUnigrams(rawGlobalUnigrams, excludedValues, insertedValues);
} }
if (m_cnsModel.hasUnigramsForKey(key) && m_cnsEnabled) { 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); cnsUnigrams = filterAndTransformUnigrams(rawCNSUnigrams, excludedValues, insertedValues);
} }
@ -143,7 +143,7 @@ const vector<Unigram> vChewingLM::unigramsForKey(const string& key)
return allUnigrams; return allUnigrams;
} }
bool vChewingLM::hasUnigramsForKey(const string& key) bool LMInstantiator::hasUnigramsForKey(const std::string& key)
{ {
if (key == " ") { if (key == " ") {
return true; return true;
@ -156,65 +156,65 @@ bool vChewingLM::hasUnigramsForKey(const string& key)
return unigramsForKey(key).size() > 0; return unigramsForKey(key).size() > 0;
} }
void vChewingLM::setPhraseReplacementEnabled(bool enabled) void LMInstantiator::setPhraseReplacementEnabled(bool enabled)
{ {
m_phraseReplacementEnabled = enabled; m_phraseReplacementEnabled = enabled;
} }
bool vChewingLM::phraseReplacementEnabled() bool LMInstantiator::phraseReplacementEnabled()
{ {
return m_phraseReplacementEnabled; return m_phraseReplacementEnabled;
} }
void vChewingLM::setCNSEnabled(bool enabled) void LMInstantiator::setCNSEnabled(bool enabled)
{ {
m_cnsEnabled = enabled; m_cnsEnabled = enabled;
} }
bool vChewingLM::cnsEnabled() bool LMInstantiator::cnsEnabled()
{ {
return m_cnsEnabled; return m_cnsEnabled;
} }
void vChewingLM::setExternalConverterEnabled(bool enabled) void LMInstantiator::setExternalConverterEnabled(bool enabled)
{ {
m_externalConverterEnabled = enabled; m_externalConverterEnabled = enabled;
} }
bool vChewingLM::externalConverterEnabled() bool LMInstantiator::externalConverterEnabled()
{ {
return m_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; 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) { for (auto&& unigram : unigrams) {
// excludedValues filters out the unigrams with the original value. // excludedValues filters out the unigrams with the original value.
// insertedValues filters out the ones with the converted 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()) { if (excludedValues.find(originalValue) != excludedValues.end()) {
continue; continue;
} }
string value = originalValue; std::string value = originalValue;
if (m_phraseReplacementEnabled) { if (m_phraseReplacementEnabled) {
string replacement = m_phraseReplacement.valueForKey(value); std::string replacement = m_phraseReplacement.valueForKey(value);
if (replacement != "") { if (replacement != "") {
value = replacement; value = replacement;
} }
} }
if (m_externalConverterEnabled && m_externalConverter) { if (m_externalConverterEnabled && m_externalConverter) {
string replacement = m_externalConverter(value); std::string replacement = m_externalConverter(value);
value = replacement; value = replacement;
} }
if (insertedValues.find(value) == insertedValues.end()) { if (insertedValues.find(value) == insertedValues.end()) {
Unigram g; Taiyan::Gramambular::Unigram g;
g.keyValue.value = value; g.keyValue.value = value;
g.keyValue.key = unigram.keyValue.key; g.keyValue.key = unigram.keyValue.key;
g.score = unigram.score; g.score = unigram.score;
@ -225,12 +225,14 @@ const vector<Unigram> vChewingLM::filterAndTransformUnigrams(const vector<Unigra
return results; 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); return m_associatedPhrases.valuesForKey(key);
} }
bool vChewingLM::hasAssociatedPhrasesForKey(const string& key) bool LMInstantiator::hasAssociatedPhrasesForKey(const std::string& key)
{ {
return m_associatedPhrases.hasValuesForKey(key); return m_associatedPhrases.hasValuesForKey(key);
} }
} // namespace vChewing

View File

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

View File

@ -45,8 +45,8 @@ public:
void close(); void close();
void dump(); void dump();
virtual const vector<Bigram> bigramsForKeys(const string& preceedingKey, const string& key); virtual const std::vector<Taiyan::Gramambular::Bigram> bigramsForKeys(const string& preceedingKey, const string& key);
virtual const vector<Unigram> unigramsForKey(const string& key); virtual const std::vector<Taiyan::Gramambular::Unigram> unigramsForKey(const string& key);
virtual bool hasUnigramsForKey(const string& key); virtual bool hasUnigramsForKey(const string& key);
protected: 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()); map<const char *, vector<Row> >::const_iterator i = keyRowMap.find(key.c_str());
if (i != keyRowMap.end()) { if (i != keyRowMap.end()) {

View File

@ -54,12 +54,7 @@ bool PhraseReplacementMap::open(const char *path)
} }
LMConsolidator::FixEOF(path); LMConsolidator::FixEOF(path);
LMConsolidator::ConsolidateContent(path, Preferences.shouldAutoSortPhraseReplacementMapOnLoad, true);
if (Preferences.shouldAutoSortPhraseReplacementMapOnLoad) {
LMConsolidator::ConsolidateContent(path, true);
} else {
LMConsolidator::ConsolidateContent(path, false);
}
fd = ::open(path, O_RDONLY); fd = ::open(path, O_RDONLY);
if (fd == -1) { 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 <cmath>
#include <sstream> #include <sstream>
using namespace vChewing; namespace vChewing {
// About 20 generations. // About 20 generations.
static const double DecayThreshould = 1.0 / 1048576.0; static const double DecayThreshould = 1.0 / 1048576.0;
@ -33,8 +33,8 @@ static double Score(size_t eventCount,
double eventTimestamp, double eventTimestamp,
double timestamp, double timestamp,
double lambda); double lambda);
static bool IsEndingPunctuation(const string& value); static bool IsEndingPunctuation(const std::string& value);
static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes, static std::string WalkedNodesToKey(const std::vector<Taiyan::Gramambular::NodeAnchor>& walkedNodes,
size_t cursorIndex); size_t cursorIndex);
UserOverrideModel::UserOverrideModel(size_t capacity, double decayConstant) UserOverrideModel::UserOverrideModel(size_t capacity, double decayConstant)
@ -43,11 +43,11 @@ UserOverrideModel::UserOverrideModel(size_t capacity, double decayConstant)
m_decayExponent = log(0.5) / 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, size_t cursorIndex,
const string& candidate, const std::string& candidate,
double timestamp) { double timestamp) {
string key = WalkedNodesToKey(walkedNodes, cursorIndex); std::string key = WalkedNodesToKey(walkedNodes, cursorIndex);
auto mapIter = m_lruMap.find(key); auto mapIter = m_lruMap.find(key);
if (mapIter == m_lruMap.end()) { if (mapIter == m_lruMap.end()) {
auto keyValuePair = KeyObservationPair(key, Observation()); 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, size_t cursorIndex,
double timestamp) { double timestamp) {
string key = WalkedNodesToKey(walkedNodes, cursorIndex); std::string key = WalkedNodesToKey(walkedNodes, cursorIndex);
auto mapIter = m_lruMap.find(key); auto mapIter = m_lruMap.find(key);
if (mapIter == m_lruMap.end()) { if (mapIter == m_lruMap.end()) {
return string(); return std::string();
} }
auto listIter = mapIter->second; auto listIter = mapIter->second;
auto& keyValuePair = *listIter; auto& keyValuePair = *listIter;
const Observation& observation = keyValuePair.second; const Observation& observation = keyValuePair.second;
string candidate; std::string candidate;
double score = 0.0; double score = 0.0;
for (auto i = observation.overrides.begin(); for (auto i = observation.overrides.begin();
i != observation.overrides.end(); i != observation.overrides.end();
@ -112,7 +112,7 @@ string UserOverrideModel::suggest(const std::vector<NodeAnchor>& walkedNodes,
return candidate; return candidate;
} }
void UserOverrideModel::Observation::update(const string& candidate, void UserOverrideModel::Observation::update(const std::string& candidate,
double timestamp) { double timestamp) {
count++; count++;
auto& o = overrides[candidate]; auto& o = overrides[candidate];
@ -134,16 +134,16 @@ static double Score(size_t eventCount,
return prob * decay; return prob * decay;
} }
static bool IsEndingPunctuation(const string& value) { static bool IsEndingPunctuation(const std::string& value) {
return value == "" || value == "" || value== "" || value == "" || return value == "" || value == "" || value== "" || value == "" ||
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) { size_t cursorIndex) {
std::stringstream s; std::stringstream s;
std::vector<NodeAnchor> n; std::vector<Taiyan::Gramambular::NodeAnchor> n;
size_t ll = 0; 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 != walkedNodes.end();
++i) { ++i) {
const auto& nn = *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()) { if (r == n.rend()) {
return ""; return "";
} }
string current = (*r).node->currentKeyValue().key; std::string current = (*r).node->currentKeyValue().key;
++r; ++r;
s.clear(); s.clear();
s.str(std::string()); s.str(std::string());
if (r != n.rend()) { if (r != n.rend()) {
string value = (*r).node->currentKeyValue().value; std::string value = (*r).node->currentKeyValue().value;
if (IsEndingPunctuation(value)) { if (IsEndingPunctuation(value)) {
s << "()"; s << "()";
r = n.rend(); r = n.rend();
@ -181,12 +181,12 @@ static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
} else { } else {
s << "()"; s << "()";
} }
string prev = s.str(); std::string prev = s.str();
s.clear(); s.clear();
s.str(std::string()); s.str(std::string());
if (r != n.rend()) { if (r != n.rend()) {
string value = (*r).node->currentKeyValue().value; std::string value = (*r).node->currentKeyValue().value;
if (IsEndingPunctuation(value)) { if (IsEndingPunctuation(value)) {
s << "()"; s << "()";
r = n.rend(); r = n.rend();
@ -201,7 +201,7 @@ static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
} else { } else {
s << "()"; s << "()";
} }
string anterior = s.str(); std::string anterior = s.str();
s.clear(); s.clear();
s.str(std::string()); s.str(std::string());
@ -209,3 +209,5 @@ static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
return s.str(); 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 <list>
#include <map> #include <map>
#include <string>
#include "Gramambular.h" #include "Gramambular.h"
@ -34,12 +33,12 @@ class UserOverrideModel {
public: public:
UserOverrideModel(size_t capacity, double decayConstant); 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, size_t cursorIndex,
const string& candidate, const std::string& candidate,
double timestamp); double timestamp);
string suggest(const std::vector<NodeAnchor>& walkedNodes, std::string suggest(const std::vector<Taiyan::Gramambular::NodeAnchor>& walkedNodes,
size_t cursorIndex, size_t cursorIndex,
double timestamp); double timestamp);
@ -56,7 +55,7 @@ private:
std::map<std::string, Override> overrides; std::map<std::string, Override> overrides;
Observation() : count(0) {} 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; typedef std::pair<std::string, Observation> KeyObservationPair;

View File

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

View File

@ -32,8 +32,8 @@ NS_ASSUME_NONNULL_BEGIN
+ (BOOL)checkIfUserLanguageModelFilesExist; + (BOOL)checkIfUserLanguageModelFilesExist;
+ (BOOL)checkIfUserDataFolderExists; + (BOOL)checkIfUserDataFolderExists;
+ (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:));
+ (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode; + (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode areWeDuplicating:(BOOL)areWeDuplicating;
+ (void)setPhraseReplacementEnabled:(BOOL)phraseReplacementEnabled; + (void)setPhraseReplacementEnabled:(BOOL)phraseReplacementEnabled;
+ (void)setCNSEnabled:(BOOL)cnsEnabled; + (void)setCNSEnabled:(BOOL)cnsEnabled;
+ (NSString *)userPhrasesDataPath:(InputMode)mode; + (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.h"
#import "mgrLangModel_Privates.h" #import "mgrLangModel_Privates.h"
#import "vChewing-Swift.h" #import "vChewing-Swift.h"
#import "LMConsolidator.h"
using namespace std;
using namespace vChewing;
static const int kUserOverrideModelCapacity = 500; static const int kUserOverrideModelCapacity = 500;
static const double kObservedOverrideHalflife = 5400.0; static const double kObservedOverrideHalflife = 5400.0;
static vChewingLM gLangModelCHT; static vChewing::LMInstantiator gLangModelCHT;
static vChewingLM gLangModelCHS; static vChewing::LMInstantiator gLangModelCHS;
static UserOverrideModel gUserOverrideModelCHT(kUserOverrideModelCapacity, kObservedOverrideHalflife); static vChewing::UserOverrideModel gUserOverrideModelCHT(kUserOverrideModelCapacity, kObservedOverrideHalflife);
static UserOverrideModel gUserOverrideModelCHS(kUserOverrideModelCapacity, kObservedOverrideHalflife); static vChewing::UserOverrideModel gUserOverrideModelCHS(kUserOverrideModelCapacity, kObservedOverrideHalflife);
static NSString *const kUserDataTemplateName = @"template-data"; static NSString *const kUserDataTemplateName = @"template-data";
static NSString *const kUserAssDataTemplateName = @"template-data"; static NSString *const kUserAssDataTemplateName = @"template-data";
@ -40,7 +38,7 @@ static NSString *const kTemplateExtension = @".txt";
@implementation mgrLangModel @implementation mgrLangModel
static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewingLM &lm) static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing::LMInstantiator &lm)
{ {
Class cls = NSClassFromString(@"ctlInputMethod"); Class cls = NSClassFromString(@"ctlInputMethod");
NSString *dataPath = [[NSBundle bundleForClass:cls] pathForResource:filenameWithoutExtension ofType:@"txt"]; NSString *dataPath = [[NSBundle bundleForClass:cls] pathForResource:filenameWithoutExtension ofType:@"txt"];
@ -206,10 +204,10 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
return YES; 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); 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); string userPhraseString = string(userPhrase.UTF8String);
for (auto unigram: unigrams) { for (auto unigram: unigrams) {
if (unigram.keyValue.value == userPhraseString) { if (unigram.keyValue.value == userPhraseString) {
@ -219,7 +217,7 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
return NO; return NO;
} }
+ (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode; + (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode areWeDuplicating:(BOOL)areWeDuplicating
{ {
if (![self checkIfUserLanguageModelFilesExist]) { if (![self checkIfUserLanguageModelFilesExist]) {
return NO; return NO;
@ -251,6 +249,11 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
// [currentMarkedPhrase appendString:@"\n"]; // [currentMarkedPhrase appendString:@"\n"];
// } // }
[currentMarkedPhrase appendString:userPhrase]; [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"]; [currentMarkedPhrase appendString:@"\n"];
NSFileHandle *writeFile = [NSFileHandle fileHandleForUpdatingAtPath:path]; NSFileHandle *writeFile = [NSFileHandle fileHandleForUpdatingAtPath:path];
@ -262,9 +265,14 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
[writeFile writeData:data]; [writeFile writeData:data];
[writeFile closeFile]; [writeFile closeFile];
// 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, // We use FSEventStream to monitor the change of the user phrase folder,
// so we don't have to load data here. // so we don't have to load data here unless FSEventStream is disabled by user.
// [self loadUserPhrases]; if (!Preferences.shouldAutoReloadUserDataFiles) {
[self loadUserPhrases];
}
return YES; return YES;
} }
@ -306,12 +314,12 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
return [[NSBundle bundleForClass:cls] pathForResource:@"char-kanji-cns" ofType:@"txt"]; return [[NSBundle bundleForClass:cls] pathForResource:@"char-kanji-cns" ofType:@"txt"];
} }
+ (vChewingLM *)lmCHT + (vChewing::LMInstantiator *)lmCHT
{ {
return &gLangModelCHT; return &gLangModelCHT;
} }
+ (vChewingLM *)lmCHS + (vChewing::LMInstantiator *)lmCHS
{ {
return &gLangModelCHS; 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 "mgrLangModel.h"
#import "UserOverrideModel.h" #import "UserOverrideModel.h"
#import "vChewingLM.h" #import "LMInstantiator.h"
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@interface mgrLangModel () @interface mgrLangModel ()
@property (class, readonly, nonatomic) vChewing::vChewingLM *lmCHT; @property (class, readonly, nonatomic) vChewing::LMInstantiator *lmCHT;
@property (class, readonly, nonatomic) vChewing::vChewingLM *lmCHS; @property (class, readonly, nonatomic) vChewing::LMInstantiator *lmCHS;
@property (class, readonly, nonatomic) vChewing::UserOverrideModel *userOverrideModelCHS; @property (class, readonly, nonatomic) vChewing::UserOverrideModel *userOverrideModelCHS;
@property (class, readonly, nonatomic) vChewing::UserOverrideModel *userOverrideModelCHT; @property (class, readonly, nonatomic) vChewing::UserOverrideModel *userOverrideModelCHT;
@end @end

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. 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 #ifndef BIGRAM_H_
#define Bigram_h #define BIGRAM_H_
#include <vector> #include <vector>
@ -34,65 +34,60 @@ namespace Taiyan {
KeyValuePair keyValue; KeyValuePair keyValue;
double score; double score;
bool operator==(const Bigram& inAnother) const; bool operator==(const Bigram& another) const;
bool operator<(const Bigram& inAnother) const; bool operator<(const Bigram& another) const;
}; };
inline ostream& operator<<(ostream& inStream, const Bigram& inGram) inline std::ostream& operator<<(std::ostream& stream, const Bigram& gram) {
{ std::streamsize p = stream.precision();
streamsize p = inStream.precision(); stream.precision(6);
inStream.precision(6); stream << "(" << gram.keyValue << "|" << gram.preceedingKeyValue << ","
inStream << "(" << inGram.keyValue << "|" <<inGram.preceedingKeyValue << "," << inGram.score << ")"; << gram.score << ")";
inStream.precision(p); stream.precision(p);
return inStream; return stream;
} }
inline ostream& operator<<(ostream& inStream, const vector<Bigram>& inGrams) inline std::ostream& operator<<(std::ostream& stream,
{ const std::vector<Bigram>& grams) {
inStream << "[" << inGrams.size() << "]=>{"; stream << "[" << grams.size() << "]=>{";
size_t index = 0; size_t index = 0;
for (vector<Bigram>::const_iterator gi = inGrams.begin() ; gi != inGrams.end() ; ++gi, ++index) { for (std::vector<Bigram>::const_iterator gi = grams.begin();
inStream << index << "=>"; gi != grams.end(); ++gi, ++index) {
inStream << *gi; stream << index << "=>";
if (gi + 1 != inGrams.end()) { stream << *gi;
inStream << ","; if (gi + 1 != grams.end()) {
stream << ",";
} }
} }
inStream << "}"; stream << "}";
return inStream; return stream;
} }
inline Bigram::Bigram() inline Bigram::Bigram() : score(0.0) {}
: 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& inAnother) const inline bool Bigram::operator<(const Bigram& another) const {
{ if (preceedingKeyValue < another.preceedingKeyValue) {
return preceedingKeyValue == inAnother.preceedingKeyValue && keyValue == inAnother.keyValue && score == inAnother.score;
}
inline bool Bigram::operator<(const Bigram& inAnother) const
{
if (preceedingKeyValue < inAnother.preceedingKeyValue) {
return true; return true;
} } else if (preceedingKeyValue == another.preceedingKeyValue) {
else if (preceedingKeyValue == inAnother.preceedingKeyValue) { if (keyValue < another.keyValue) {
if (keyValue < inAnother.keyValue) {
return true; return true;
} } else if (keyValue == another.keyValue) {
else if (keyValue == inAnother.keyValue) { return score < another.score;
return score < inAnother.score;
} }
return false; return false;
} }
return false; return false;
} }
} } // namespace Gramambular
} } // namespace Taiyan
#endif #endif

View File

@ -17,123 +17,113 @@ 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. 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 #ifndef BLOCKREADINGBUILDER_H_
#define BlockReadingBuilder_h #define BLOCKREADINGBUILDER_H_
#include <string>
#include <vector> #include <vector>
#include "Grid.h" #include "Grid.h"
#include "LanguageModel.h" #include "LanguageModel.h"
namespace Taiyan { namespace Taiyan {
namespace Gramambular { namespace Gramambular {
using namespace std;
class BlockReadingBuilder { class BlockReadingBuilder {
public: public:
BlockReadingBuilder(LanguageModel *inLM); explicit BlockReadingBuilder(LanguageModel* lm);
void clear(); void clear();
size_t length() const; size_t length() const;
size_t cursorIndex() const; size_t cursorIndex() const;
void setCursorIndex(size_t inNewIndex); void setCursorIndex(size_t newIndex);
void insertReadingAtCursor(const string& inReading); void insertReadingAtCursor(const std::string& reading);
bool deleteReadingBeforeCursor(); // backspace bool deleteReadingBeforeCursor(); // backspace
bool deleteReadingAfterCursor(); // delete bool deleteReadingAfterCursor(); // delete
bool removeHeadReadings(size_t count); bool removeHeadReadings(size_t count);
void setJoinSeparator(const string& separator); void setJoinSeparator(const std::string& separator);
const string joinSeparator() const; const std::string joinSeparator() const;
vector<string> readings() const; std::vector<std::string> readings() const;
Grid& grid(); Grid& grid();
protected: protected:
void build(); 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; size_t m_cursorIndex;
vector<string> m_readings; std::vector<std::string> m_readings;
Grid m_grid; Grid m_grid;
LanguageModel* m_LM; LanguageModel* m_LM;
string m_joinSeparator; std::string m_joinSeparator;
}; };
inline BlockReadingBuilder::BlockReadingBuilder(LanguageModel *inLM) inline BlockReadingBuilder::BlockReadingBuilder(LanguageModel* lm)
: m_LM(inLM) : m_LM(lm), m_cursorIndex(0) {}
, m_cursorIndex(0)
{
}
inline void BlockReadingBuilder::clear() inline void BlockReadingBuilder::clear() {
{
m_cursorIndex = 0; m_cursorIndex = 0;
m_readings.clear(); m_readings.clear();
m_grid.clear(); m_grid.clear();
} }
inline size_t BlockReadingBuilder::length() const inline size_t BlockReadingBuilder::length() const { return m_readings.size(); }
{
return m_readings.size(); inline size_t BlockReadingBuilder::cursorIndex() const { return m_cursorIndex; }
inline void BlockReadingBuilder::setCursorIndex(size_t newIndex) {
m_cursorIndex = newIndex > m_readings.size() ? m_readings.size() : newIndex;
} }
inline size_t BlockReadingBuilder::cursorIndex() const inline void BlockReadingBuilder::insertReadingAtCursor(
{ const std::string& reading) {
return m_cursorIndex; m_readings.insert(m_readings.begin() + m_cursorIndex, reading);
}
inline void BlockReadingBuilder::setCursorIndex(size_t inNewIndex)
{
m_cursorIndex = inNewIndex > m_readings.size() ? m_readings.size() : inNewIndex;
}
inline void BlockReadingBuilder::insertReadingAtCursor(const string& inReading)
{
m_readings.insert(m_readings.begin() + m_cursorIndex, inReading);
m_grid.expandGridByOneAtLocation(m_cursorIndex); m_grid.expandGridByOneAtLocation(m_cursorIndex);
build(); build();
m_cursorIndex++; m_cursorIndex++;
} }
inline vector<string> BlockReadingBuilder::readings() const inline std::vector<std::string> BlockReadingBuilder::readings() const {
{
return m_readings; return m_readings;
} }
inline bool BlockReadingBuilder::deleteReadingBeforeCursor() inline bool BlockReadingBuilder::deleteReadingBeforeCursor() {
{
if (!m_cursorIndex) { if (!m_cursorIndex) {
return false; 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_cursorIndex--;
m_grid.shrinkGridByOneAtLocation(m_cursorIndex); m_grid.shrinkGridByOneAtLocation(m_cursorIndex);
build(); build();
return true; return true;
} }
inline bool BlockReadingBuilder::deleteReadingAfterCursor() inline bool BlockReadingBuilder::deleteReadingAfterCursor() {
{
if (m_cursorIndex == m_readings.size()) { if (m_cursorIndex == m_readings.size()) {
return false; return false;
} }
m_readings.erase(m_readings.begin() + m_cursorIndex, m_readings.begin() + m_cursorIndex + 1); m_readings.erase(m_readings.begin() + m_cursorIndex,
m_readings.begin() + m_cursorIndex + 1);
m_grid.shrinkGridByOneAtLocation(m_cursorIndex); m_grid.shrinkGridByOneAtLocation(m_cursorIndex);
build(); build();
return true; return true;
} }
inline bool BlockReadingBuilder::removeHeadReadings(size_t count) inline bool BlockReadingBuilder::removeHeadReadings(size_t count) {
{
if (count > length()) { if (count > length()) {
return false; return false;
} }
@ -150,23 +140,18 @@ namespace Taiyan {
return true; return true;
} }
inline void BlockReadingBuilder::setJoinSeparator(const string& separator) inline void BlockReadingBuilder::setJoinSeparator(
{ const std::string& separator) {
m_joinSeparator = separator; m_joinSeparator = separator;
} }
inline const string BlockReadingBuilder::joinSeparator() const inline const std::string BlockReadingBuilder::joinSeparator() const {
{
return m_joinSeparator; return m_joinSeparator;
} }
inline Grid& BlockReadingBuilder::grid() inline Grid& BlockReadingBuilder::grid() { return m_grid; }
{
return m_grid;
}
inline void BlockReadingBuilder::build() inline void BlockReadingBuilder::build() {
{
if (!m_LM) { if (!m_LM) {
return; return;
} }
@ -176,8 +161,7 @@ namespace Taiyan {
if (m_cursorIndex < MaximumBuildSpanLength) { if (m_cursorIndex < MaximumBuildSpanLength) {
begin = 0; begin = 0;
} } else {
else {
begin = m_cursorIndex - MaximumBuildSpanLength; begin = m_cursorIndex - MaximumBuildSpanLength;
} }
@ -187,12 +171,14 @@ namespace Taiyan {
for (size_t p = begin; p < end; p++) { for (size_t p = begin; p < end; p++) {
for (size_t q = 1; q <= MaximumBuildSpanLength && p + q <= end; q++) { 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); std::string combinedReading = Join(
if (!m_grid.hasNodeAtLocationSpanningLengthMatchingKey(p, q, combinedReading)) { m_readings.begin() + p, m_readings.begin() + p + q, m_joinSeparator);
vector<Unigram> unigrams = m_LM->unigramsForKey(combinedReading); if (!m_grid.hasNodeAtLocationSpanningLengthMatchingKey(p, q,
combinedReading)) {
std::vector<Unigram> unigrams = m_LM->unigramsForKey(combinedReading);
if (unigrams.size() > 0) { if (unigrams.size() > 0) {
Node n(combinedReading, unigrams, vector<Bigram>()); Node n(combinedReading, unigrams, std::vector<Bigram>());
m_grid.insertNode(n, p, q); m_grid.insertNode(n, p, q);
} }
} }
@ -200,10 +186,12 @@ namespace Taiyan {
} }
} }
inline const string BlockReadingBuilder::Join(vector<string>::const_iterator begin, vector<string>::const_iterator end, const string& separator) inline const std::string BlockReadingBuilder::Join(
{ std::vector<std::string>::const_iterator begin,
string result; std::vector<std::string>::const_iterator end,
for (vector<string>::const_iterator iter = begin ; iter != end ; ) { const std::string& separator) {
std::string result;
for (std::vector<std::string>::const_iterator iter = begin; iter != end;) {
result += *iter; result += *iter;
++iter; ++iter;
if (iter != end) { if (iter != end) {
@ -212,7 +200,7 @@ namespace Taiyan {
} }
return result; return result;
} }
} } // namespace Gramambular
} } // namespace Taiyan
#endif #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. 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 #ifndef GRAMAMBULAR_H_
#define Gramambular_h #define GRAMAMBULAR_H_
#include "Bigram.h" #include "Bigram.h"
#include "BlockReadingBuilder.h" #include "BlockReadingBuilder.h"

View File

@ -17,10 +17,13 @@ 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. 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 #ifndef GRID_H_
#define Grid_h #define GRID_H_
#include <map> #include <map>
#include <string>
#include <vector>
#include "NodeAnchor.h" #include "NodeAnchor.h"
#include "Span.h" #include "Span.h"
@ -30,112 +33,108 @@ namespace Taiyan {
class Grid { class Grid {
public: public:
void clear(); void clear();
void insertNode(const Node& inNode, size_t inLocation, size_t inSpanningLength); void insertNode(const Node& node, size_t location, size_t spanningLength);
bool hasNodeAtLocationSpanningLengthMatchingKey(size_t inLocation, size_t inSpanningLength, const string& inKey); bool hasNodeAtLocationSpanningLengthMatchingKey(size_t location,
size_t spanningLength,
const std::string& key);
void expandGridByOneAtLocation(size_t inLocation); void expandGridByOneAtLocation(size_t location);
void shrinkGridByOneAtLocation(size_t inLocation); void shrinkGridByOneAtLocation(size_t location);
size_t width() const; size_t width() const;
vector<NodeAnchor> nodesEndingAt(size_t inLocation); std::vector<NodeAnchor> nodesEndingAt(size_t location);
vector<NodeAnchor> nodesCrossingOrEndingAt(size_t inLocation); std::vector<NodeAnchor> nodesCrossingOrEndingAt(size_t location);
// "Freeze" the node with the unigram that represents the selected candidate value. // "Freeze" the node with the unigram that represents the selected candidate
// After this, the node that contains the unigram will always be evaluated to that // value. After this, the node that contains the unigram will always be
// unigram, while all other overlapping nodes will be reset to their initial state // evaluated to that unigram, while all other overlapping nodes will be reset
// (that is, if any of those nodes were "frozen" or fixed, they will be unfrozen.) // to their initial state (that is, if any of those nodes were "frozen" or
NodeAnchor fixNodeSelectedCandidate(size_t location, const string& value); // fixed, they will be unfrozen.)
NodeAnchor fixNodeSelectedCandidate(size_t location,
const std::string& value);
// Similar to fixNodeSelectedCandidate, but instead of "freezing" the node, only // Similar to fixNodeSelectedCandidate, but instead of "freezing" the node,
// boost the unigram that represents the value with an overriding score. This // only boost the unigram that represents the value with an overriding score.
// has the same side effect as fixNodeSelectedCandidate, which is that all other // This has the same side effect as fixNodeSelectedCandidate, which is that
// overlapping nodes will be reset to their initial state. // all other overlapping nodes will be reset to their initial state.
void overrideNodeScoreForSelectedCandidate(size_t location, const string& value, float overridingScore); void overrideNodeScoreForSelectedCandidate(size_t location,
const std::string& value,
float overridingScore);
const string dumpDOT(); std::string dumpDOT();
protected: protected:
vector<Span> m_spans; std::vector<Span> m_spans;
}; };
inline void Grid::clear() inline void Grid::clear() { m_spans.clear(); }
{
m_spans.clear();
}
inline void Grid::insertNode(const Node& inNode, size_t inLocation, size_t inSpanningLength) inline void Grid::insertNode(const Node& node, size_t location,
{ size_t spanningLength) {
if (inLocation >= m_spans.size()) { if (location >= m_spans.size()) {
size_t diff = inLocation - m_spans.size() + 1; size_t diff = location - m_spans.size() + 1;
for (size_t i = 0; i < diff; i++) { for (size_t i = 0; i < diff; i++) {
m_spans.push_back(Span()); m_spans.push_back(Span());
} }
} }
m_spans[inLocation].insertNodeOfLength(inNode, inSpanningLength); m_spans[location].insertNodeOfLength(node, spanningLength);
} }
inline bool Grid::hasNodeAtLocationSpanningLengthMatchingKey(size_t inLocation, size_t inSpanningLength, const string& inKey) inline bool Grid::hasNodeAtLocationSpanningLengthMatchingKey(
{ size_t location, size_t spanningLength, const std::string& key) {
if (inLocation > m_spans.size()) { if (location > m_spans.size()) {
return false; return false;
} }
const Node *n = m_spans[inLocation].nodeOfLength(inSpanningLength); const Node* n = m_spans[location].nodeOfLength(spanningLength);
if (!n) { if (!n) {
return false; return false;
} }
return inKey == n->key(); return key == n->key();
} }
inline void Grid::expandGridByOneAtLocation(size_t inLocation) inline void Grid::expandGridByOneAtLocation(size_t location) {
{ if (!location || location == m_spans.size()) {
if (!inLocation || inLocation == m_spans.size()) { m_spans.insert(m_spans.begin() + location, Span());
m_spans.insert(m_spans.begin() + inLocation, Span()); } else {
} m_spans.insert(m_spans.begin() + location, Span());
else { for (size_t i = 0; i < location; i++) {
m_spans.insert(m_spans.begin() + inLocation, Span());
for (size_t i = 0 ; i < inLocation ; i++) {
// zaps overlapping spans // zaps overlapping spans
m_spans[i].removeNodeOfLengthGreaterThan(inLocation - i); m_spans[i].removeNodeOfLengthGreaterThan(location - i);
} }
} }
} }
inline void Grid::shrinkGridByOneAtLocation(size_t inLocation) inline void Grid::shrinkGridByOneAtLocation(size_t location) {
{ if (location >= m_spans.size()) {
if (inLocation >= m_spans.size()) {
return; return;
} }
m_spans.erase(m_spans.begin() + inLocation); m_spans.erase(m_spans.begin() + location);
for (size_t i = 0 ; i < inLocation ; i++) { for (size_t i = 0; i < location; i++) {
// zaps overlapping spans // zaps overlapping spans
m_spans[i].removeNodeOfLengthGreaterThan(inLocation - i); m_spans[i].removeNodeOfLengthGreaterThan(location - i);
} }
} }
inline size_t Grid::width() const inline size_t Grid::width() const { return m_spans.size(); }
{
return m_spans.size();
}
inline vector<NodeAnchor> Grid::nodesEndingAt(size_t inLocation) inline std::vector<NodeAnchor> Grid::nodesEndingAt(size_t location) {
{ std::vector<NodeAnchor> result;
vector<NodeAnchor> result;
if (m_spans.size() && inLocation <= m_spans.size()) { if (m_spans.size() && location <= m_spans.size()) {
for (size_t i = 0 ; i < inLocation ; i++) { for (size_t i = 0; i < location; i++) {
Span& span = m_spans[i]; Span& span = m_spans[i];
if (i + span.maximumLength() >= inLocation) { if (i + span.maximumLength() >= location) {
Node *np = span.nodeOfLength(inLocation - i); Node* np = span.nodeOfLength(location - i);
if (np) { if (np) {
NodeAnchor na; NodeAnchor na;
na.node = np; na.node = np;
na.location = i; na.location = i;
na.spanningLength = inLocation - i; na.spanningLength = location - i;
result.push_back(na); result.push_back(na);
} }
@ -146,19 +145,16 @@ namespace Taiyan {
return result; return result;
} }
inline vector<NodeAnchor> Grid::nodesCrossingOrEndingAt(size_t inLocation) inline std::vector<NodeAnchor> Grid::nodesCrossingOrEndingAt(size_t location) {
{ std::vector<NodeAnchor> result;
vector<NodeAnchor> result;
if (m_spans.size() && inLocation <= m_spans.size()) { if (m_spans.size() && location <= m_spans.size()) {
for (size_t i = 0 ; i < inLocation ; i++) { for (size_t i = 0; i < location; i++) {
Span& span = m_spans[i]; Span& span = m_spans[i];
if (i + span.maximumLength() >= inLocation) { if (i + span.maximumLength() >= location) {
for (size_t j = 1, m = span.maximumLength(); j <= m; j++) { for (size_t j = 1, m = span.maximumLength(); j <= m; j++) {
if (i + j < location) {
if (i + j < inLocation) {
continue; continue;
} }
@ -167,7 +163,7 @@ namespace Taiyan {
NodeAnchor na; NodeAnchor na;
na.node = np; na.node = np;
na.location = i; na.location = i;
na.spanningLength = inLocation - i; na.spanningLength = location - i;
result.push_back(na); result.push_back(na);
} }
@ -179,10 +175,11 @@ namespace Taiyan {
return result; return result;
} }
// For nodes found at the location, fix their currently-selected candidate using the supplied string value. // For nodes found at the location, fix their currently-selected candidate using
inline NodeAnchor Grid::fixNodeSelectedCandidate(size_t location, const string& value) // the supplied string value.
{ inline NodeAnchor Grid::fixNodeSelectedCandidate(size_t location,
vector<NodeAnchor> nodes = nodesCrossingOrEndingAt(location); const std::string& value) {
std::vector<NodeAnchor> nodes = nodesCrossingOrEndingAt(location);
NodeAnchor node; NodeAnchor node;
for (auto nodeAnchor : nodes) { for (auto nodeAnchor : nodes) {
auto candidates = nodeAnchor.node->candidates(); auto candidates = nodeAnchor.node->candidates();
@ -194,16 +191,16 @@ namespace Taiyan {
if (candidates[i].value == value) { if (candidates[i].value == value) {
const_cast<Node*>(nodeAnchor.node)->selectCandidateAtIndex(i); const_cast<Node*>(nodeAnchor.node)->selectCandidateAtIndex(i);
node = nodeAnchor; node = nodeAnchor;
break;; break;
} }
} }
} }
return node; return node;
} }
inline void Grid::overrideNodeScoreForSelectedCandidate(size_t location, const string& value, float overridingScore) inline void Grid::overrideNodeScoreForSelectedCandidate(
{ size_t location, const std::string& value, float overridingScore) {
vector<NodeAnchor> nodes = nodesCrossingOrEndingAt(location); std::vector<NodeAnchor> nodes = nodesCrossingOrEndingAt(location);
for (auto nodeAnchor : nodes) { for (auto nodeAnchor : nodes) {
auto candidates = nodeAnchor.node->candidates(); auto candidates = nodeAnchor.node->candidates();
@ -212,53 +209,15 @@ namespace Taiyan {
for (size_t i = 0, c = candidates.size(); i < c; ++i) { for (size_t i = 0, c = candidates.size(); i < c; ++i) {
if (candidates[i].value == value) { if (candidates[i].value == value) {
const_cast<Node*>(nodeAnchor.node)->selectFloatingCandidateAtIndex(i, overridingScore); const_cast<Node*>(nodeAnchor.node)
->selectFloatingCandidateAtIndex(i, overridingScore);
break; break;
} }
} }
} }
} }
inline const string Grid::dumpDOT() } // namespace Gramambular
{ } // namespace Taiyan
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();
}
}
}
#endif #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. 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 #ifndef KEYVALUEPAIR_H_
#define KeyValuePair_h #define KEYVALUEPAIR_H_
#include <ostream> #include <ostream>
#include <string> #include <string>
namespace Taiyan { namespace Taiyan {
namespace Gramambular { namespace Gramambular {
using namespace std;
class KeyValuePair { class KeyValuePair {
public: public:
string key; std::string key;
string value; std::string value;
bool operator==(const KeyValuePair& inAnother) const; bool operator==(const KeyValuePair& another) const;
bool operator<(const KeyValuePair& inAnother) const; bool operator<(const KeyValuePair& another) const;
}; };
inline ostream& operator<<(ostream& inStream, const KeyValuePair& inPair) inline std::ostream& operator<<(std::ostream& stream,
{ const KeyValuePair& pair) {
inStream << "(" << inPair.key << "," << inPair.value << ")"; stream << "(" << pair.key << "," << pair.value << ")";
return inStream; return stream;
} }
inline bool KeyValuePair::operator==(const KeyValuePair& inAnother) const inline bool KeyValuePair::operator==(const KeyValuePair& another) const {
{ return key == another.key && value == another.value;
return key == inAnother.key && value == inAnother.value;
} }
inline bool KeyValuePair::operator<(const KeyValuePair& inAnother) const inline bool KeyValuePair::operator<(const KeyValuePair& another) const {
{ if (key < another.key) {
if (key < inAnother.key) {
return true; return true;
} } else if (key == another.key) {
else if (key == inAnother.key) { return value < another.value;
return value < inAnother.value;
} }
return false; return false;
} }
} } // namespace Gramambular
} } // namespace Taiyan
#endif #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. 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 #ifndef LANGUAGEMODEL_H_
#define LanguageModel_h #define LANGUAGEMODEL_H_
#include <string>
#include <vector> #include <vector>
#include "Bigram.h" #include "Bigram.h"
#include "Unigram.h" #include "Unigram.h"
namespace Taiyan { namespace Taiyan {
namespace Gramambular { namespace Gramambular {
using namespace std;
class LanguageModel { class LanguageModel {
public: public:
virtual ~LanguageModel() {} virtual ~LanguageModel() {}
virtual const vector<Bigram> bigramsForKeys(const string &preceedingKey, const string& key) = 0; virtual const std::vector<Bigram> bigramsForKeys(
virtual const vector<Unigram> unigramsForKey(const string &key) = 0; const std::string& preceedingKey, const std::string& key) = 0;
virtual bool hasUnigramsForKey(const 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 #endif

View File

@ -17,75 +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. 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 #ifndef NODE_H_
#define Node_h #define NODE_H_
#include <limits> #include <limits>
#include <map>
#include <string>
#include <vector> #include <vector>
#include "LanguageModel.h" #include "LanguageModel.h"
namespace Taiyan { namespace Taiyan {
namespace Gramambular { namespace Gramambular {
using namespace std;
class Node { class Node {
public: public:
Node(); Node();
Node(const string& inKey, const vector<Unigram>& inUnigrams, const vector<Bigram>& inBigrams); 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; bool isCandidateFixed() const;
const vector<KeyValuePair>& candidates() const; const std::vector<KeyValuePair>& candidates() const;
void selectCandidateAtIndex(size_t inIndex = 0, bool inFix = true); void selectCandidateAtIndex(size_t index = 0, bool fix = true);
void resetCandidate(); void resetCandidate();
void selectFloatingCandidateAtIndex(size_t index, double score); void selectFloatingCandidateAtIndex(size_t index, double score);
const string& key() const; const std::string& key() const;
double score() const; double score() const;
// double scoreForCandidate(string &candidate) const; // Prevents the override model to remember symbols with scode -X or lower. double scoreForCandidate(const std::string& candidate) const;
const KeyValuePair currentKeyValue() const; const KeyValuePair currentKeyValue() const;
double highestUnigramScore() const; double highestUnigramScore() const;
protected: protected:
const LanguageModel* m_LM; const LanguageModel* m_LM;
string m_key; std::string m_key;
double m_score; double m_score;
vector<Unigram> m_unigrams; std::vector<Unigram> m_unigrams;
vector<KeyValuePair> m_candidates; std::vector<KeyValuePair> m_candidates;
map<string, size_t> m_valueUnigramIndexMap; std::map<std::string, size_t> m_valueUnigramIndexMap;
map<KeyValuePair, vector<Bigram> > m_preceedingGramBigramMap; std::map<KeyValuePair, std::vector<Bigram> > m_preceedingGramBigramMap;
bool m_candidateFixed; bool m_candidateFixed;
size_t m_selectedUnigramIndex; 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) inline std::ostream& operator<<(std::ostream& stream, const Node& node) {
{ stream << "(node,key:" << node.m_key
inStream << "(node,key:" << inNode.m_key << ",fixed:" << (inNode.m_candidateFixed ? "true" : "false") << ",fixed:" << (node.m_candidateFixed ? "true" : "false")
<< ",selected:" << inNode.m_selectedUnigramIndex << ",selected:" << node.m_selectedUnigramIndex << ","
<< "," << inNode.m_unigrams << ")"; << node.m_unigrams << ")";
return inStream; return stream;
} }
inline Node::Node() inline Node::Node()
: m_candidateFixed(false) : m_candidateFixed(false), m_selectedUnigramIndex(0), m_score(0.0) {}
, m_selectedUnigramIndex(0)
, m_score(0.0)
{
}
inline Node::Node(const string& inKey, const vector<Unigram>& inUnigrams, const vector<Bigram>& inBigrams) inline Node::Node(const std::string& key, const std::vector<Unigram>& unigrams,
: m_key(inKey) const std::vector<Bigram>& bigrams)
, m_unigrams(inUnigrams) : m_key(key),
, m_candidateFixed(false) m_unigrams(unigrams),
, m_selectedUnigramIndex(0) m_candidateFixed(false),
, m_score(0.0) m_selectedUnigramIndex(0),
{ m_score(0.0) {
stable_sort(m_unigrams.begin(), m_unigrams.end(), Unigram::ScoreCompare); stable_sort(m_unigrams.begin(), m_unigrams.end(), Unigram::ScoreCompare);
if (m_unigrams.size()) { if (m_unigrams.size()) {
@ -93,33 +93,39 @@ namespace Taiyan {
} }
size_t i = 0; size_t i = 0;
for (vector<Unigram>::const_iterator ui = m_unigrams.begin() ; ui != m_unigrams.end() ; ++ui) { for (std::vector<Unigram>::const_iterator ui = m_unigrams.begin();
ui != m_unigrams.end(); ++ui) {
m_valueUnigramIndexMap[(*ui).keyValue.value] = i; m_valueUnigramIndexMap[(*ui).keyValue.value] = i;
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) { for (std::vector<Bigram>::const_iterator bi = bigrams.begin();
bi != bigrams.end(); ++bi) {
m_preceedingGramBigramMap[(*bi).preceedingKeyValue].push_back(*bi); m_preceedingGramBigramMap[(*bi).preceedingKeyValue].push_back(*bi);
} }
} }
inline void Node::primeNodeWithPreceedingKeyValues(const vector<KeyValuePair>& inKeyValues) inline void Node::primeNodeWithPreceedingKeyValues(
{ const std::vector<KeyValuePair>& keyValues) {
size_t newIndex = m_selectedUnigramIndex; size_t newIndex = m_selectedUnigramIndex;
double max = m_score; double max = m_score;
if (!isCandidateFixed()) { if (!isCandidateFixed()) {
for (vector<KeyValuePair>::const_iterator kvi = inKeyValues.begin() ; kvi != inKeyValues.end() ; ++kvi) { for (std::vector<KeyValuePair>::const_iterator kvi = keyValues.begin();
map<KeyValuePair, vector<Bigram> >::const_iterator f = m_preceedingGramBigramMap.find(*kvi); kvi != keyValues.end(); ++kvi) {
std::map<KeyValuePair, std::vector<Bigram> >::const_iterator f =
m_preceedingGramBigramMap.find(*kvi);
if (f != m_preceedingGramBigramMap.end()) { if (f != m_preceedingGramBigramMap.end()) {
const vector<Bigram>& bigrams = (*f).second; const std::vector<Bigram>& bigrams = (*f).second;
for (vector<Bigram>::const_iterator bi = bigrams.begin() ; bi != bigrams.end() ; ++bi) { for (std::vector<Bigram>::const_iterator bi = bigrams.begin();
bi != bigrams.end(); ++bi) {
const Bigram& bigram = *bi; const Bigram& bigram = *bi;
if (bigram.score > max) { if (bigram.score > max) {
map<string, size_t>::const_iterator uf = m_valueUnigramIndexMap.find((*bi).keyValue.value); std::map<std::string, size_t>::const_iterator uf =
m_valueUnigramIndexMap.find((*bi).keyValue.value);
if (uf != m_valueUnigramIndexMap.end()) { if (uf != m_valueUnigramIndexMap.end()) {
newIndex = (*uf).second; newIndex = (*uf).second;
max = bigram.score; max = bigram.score;
@ -139,31 +145,24 @@ namespace Taiyan {
} }
} }
inline bool Node::isCandidateFixed() const inline bool Node::isCandidateFixed() const { return m_candidateFixed; }
{
return m_candidateFixed;
}
inline const vector<KeyValuePair>& Node::candidates() const inline const std::vector<KeyValuePair>& Node::candidates() const {
{
return m_candidates; return m_candidates;
} }
inline void Node::selectCandidateAtIndex(size_t inIndex, bool inFix) inline void Node::selectCandidateAtIndex(size_t index, bool fix) {
{ if (index >= m_unigrams.size()) {
if (inIndex >= m_unigrams.size()) {
m_selectedUnigramIndex = 0; m_selectedUnigramIndex = 0;
} } else {
else { m_selectedUnigramIndex = index;
m_selectedUnigramIndex = inIndex;
} }
m_candidateFixed = inFix; m_candidateFixed = fix;
m_score = 99; m_score = 99;
} }
inline void Node::resetCandidate() inline void Node::resetCandidate() {
{
m_selectedUnigramIndex = 0; m_selectedUnigramIndex = 0;
m_candidateFixed = 0; m_candidateFixed = 0;
if (m_unigrams.size()) { if (m_unigrams.size()) {
@ -181,19 +180,12 @@ namespace Taiyan {
m_score = score; m_score = score;
} }
inline const string& Node::key() const inline const std::string& Node::key() const { return m_key; }
{
return m_key;
}
inline double Node::score() const inline double Node::score() const { return m_score; }
{
return m_score;
}
// Prevents the override model to remember symbols with scode -X or lower. // Prevents the override model to remember symbols with scode -X or lower.
// inline double Node::scoreForCandidate(string &candidate) const //inline double Node::scoreForCandidate(const std::string& candidate) const {
// {
// for (auto unigram : m_unigrams) { // for (auto unigram : m_unigrams) {
// if (unigram.keyValue.value == candidate) { // if (unigram.keyValue.value == candidate) {
// return unigram.score; // return unigram.score;
@ -209,16 +201,14 @@ namespace Taiyan {
return m_unigrams[0].score; return m_unigrams[0].score;
} }
inline const KeyValuePair Node::currentKeyValue() const inline const KeyValuePair Node::currentKeyValue() const {
{
if (m_selectedUnigramIndex >= m_unigrams.size()) { if (m_selectedUnigramIndex >= m_unigrams.size()) {
return KeyValuePair(); return KeyValuePair();
} } else {
else {
return m_candidates[m_selectedUnigramIndex]; return m_candidates[m_selectedUnigramIndex];
} }
} }
} } // namespace Gramambular
} } // namespace Taiyan
#endif #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. 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 #ifndef NODEANCHOR_H_
#define NodeAnchor_h #define NODEANCHOR_H_
#include <vector>
#include "Node.h" #include "Node.h"
namespace Taiyan { namespace Taiyan {
namespace Gramambular { namespace Gramambular {
class NodeAnchor {
public: struct NodeAnchor {
NodeAnchor(); const Node* node = nullptr;
const Node *node; size_t location = 0;
size_t location; size_t spanningLength = 0;
size_t spanningLength; double accumulatedScore = 0.0;
double accumulatedScore;
}; };
inline NodeAnchor::NodeAnchor() inline std::ostream& operator<<(std::ostream& stream,
: node(0) const NodeAnchor& anchor) {
, location(0) stream << "{@(" << anchor.location << "," << anchor.spanningLength << "),";
, spanningLength(0) if (anchor.node) {
, accumulatedScore(0.0) stream << *(anchor.node);
{ } else {
stream << "null";
}
stream << "}";
return stream;
} }
inline ostream& operator<<(ostream& inStream, const NodeAnchor& inAnchor) inline std::ostream& operator<<(std::ostream& stream,
{ const std::vector<NodeAnchor>& anchor) {
inStream << "{@(" << inAnchor.location << "," << inAnchor.spanningLength << "),"; for (std::vector<NodeAnchor>::const_iterator i = anchor.begin();
if (inAnchor.node) { i != anchor.end(); ++i) {
inStream << *(inAnchor.node); stream << *i;
} if (i + 1 != anchor.end()) {
else { stream << "<-";
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; return stream;
}
}
} }
} // namespace Gramambular
} // namespace Taiyan
#endif #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. 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 #ifndef SPAN_H_
#define Span_h #define SPAN_H_
#include <map> #include <map>
#include <set> #include <set>
#include <sstream> #include <sstream>
#include "Node.h" #include "Node.h"
namespace Taiyan { namespace Taiyan {
namespace Gramambular { namespace Gramambular {
class Span { class Span {
public: public:
Span();
void clear(); void clear();
void insertNodeOfLength(const Node& inNode, size_t inLength); void insertNodeOfLength(const Node& node, size_t length);
void removeNodeOfLengthGreaterThan(size_t inLength); void removeNodeOfLengthGreaterThan(size_t length);
Node* nodeOfLength(size_t inLength); Node* nodeOfLength(size_t length);
size_t maximumLength() const; size_t maximumLength() const;
protected: protected:
map<size_t, Node> m_lengthNodeMap; std::map<size_t, Node> m_lengthNodeMap;
size_t m_maximumLength; size_t m_maximumLength = 0;
}; };
inline Span::Span() inline void Span::clear() {
: m_maximumLength(0)
{
}
inline void Span::clear()
{
m_lengthNodeMap.clear(); m_lengthNodeMap.clear();
m_maximumLength = 0; m_maximumLength = 0;
} }
inline void Span::insertNodeOfLength(const Node& inNode, size_t inLength) inline void Span::insertNodeOfLength(const Node& node, size_t length) {
{ m_lengthNodeMap[length] = node;
m_lengthNodeMap[inLength] = inNode; if (length > m_maximumLength) {
if (inLength > m_maximumLength) { m_maximumLength = length;
m_maximumLength = inLength;
} }
} }
inline void Span::removeNodeOfLengthGreaterThan(size_t inLength) inline void Span::removeNodeOfLengthGreaterThan(size_t length) {
{ if (length > m_maximumLength) {
if (inLength > m_maximumLength) {
return; return;
} }
size_t max = 0; size_t max = 0;
set<size_t> removeSet; std::set<size_t> removeSet;
for (map<size_t, Node>::iterator i = m_lengthNodeMap.begin(), e = m_lengthNodeMap.end() ; i != e ; ++i) { for (std::map<size_t, Node>::iterator i = m_lengthNodeMap.begin(),
if ((*i).first > inLength) { e = m_lengthNodeMap.end();
i != e; ++i) {
if ((*i).first > length) {
removeSet.insert((*i).first); removeSet.insert((*i).first);
} } else {
else {
if ((*i).first > max) { if ((*i).first > max) {
max = (*i).first; max = (*i).first;
} }
} }
} }
for (set<size_t>::iterator i = removeSet.begin(), e = removeSet.end(); i != e; ++i) { for (std::set<size_t>::iterator i = removeSet.begin(), e = removeSet.end();
i != e; ++i) {
m_lengthNodeMap.erase(*i); m_lengthNodeMap.erase(*i);
} }
m_maximumLength = max; m_maximumLength = max;
} }
inline Node* Span::nodeOfLength(size_t inLength) inline Node* Span::nodeOfLength(size_t length) {
{ std::map<size_t, Node>::iterator f = m_lengthNodeMap.find(length);
map<size_t, Node>::iterator f = m_lengthNodeMap.find(inLength);
return f == m_lengthNodeMap.end() ? 0 : &(*f).second; return f == m_lengthNodeMap.end() ? 0 : &(*f).second;
} }
inline size_t Span::maximumLength() const inline size_t Span::maximumLength() const { return m_maximumLength; }
{ } // namespace Gramambular
return m_maximumLength; } // namespace Taiyan
}
}
}
#endif #endif

View File

@ -17,14 +17,16 @@ 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. 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 #ifndef UNIGRAM_H_
#define Unigram_h #define UNIGRAM_H_
#include <vector> #include <vector>
#include "KeyValuePair.h" #include "KeyValuePair.h"
namespace Taiyan { namespace Taiyan {
namespace Gramambular { namespace Gramambular {
class Unigram { class Unigram {
public: public:
Unigram(); Unigram();
@ -32,65 +34,58 @@ namespace Taiyan {
KeyValuePair keyValue; KeyValuePair keyValue;
double score; double score;
bool operator==(const Unigram& inAnother) const; bool operator==(const Unigram& another) const;
bool operator<(const Unigram& inAnother) const; bool operator<(const Unigram& another) const;
static bool ScoreCompare(const Unigram& a, const Unigram& b); static bool ScoreCompare(const Unigram& a, const Unigram& b);
}; };
inline ostream& operator<<(ostream& inStream, const Unigram& inGram) inline std::ostream& operator<<(std::ostream& stream, const Unigram& gram) {
{ std::streamsize p = stream.precision();
streamsize p = inStream.precision(); stream.precision(6);
inStream.precision(6); stream << "(" << gram.keyValue << "," << gram.score << ")";
inStream << "(" << inGram.keyValue << "," << inGram.score << ")"; stream.precision(p);
inStream.precision(p); return stream;
return inStream;
} }
inline ostream& operator<<(ostream& inStream, const vector<Unigram>& inGrams) inline std::ostream& operator<<(std::ostream& stream,
{ const std::vector<Unigram>& grams) {
inStream << "[" << inGrams.size() << "]=>{"; stream << "[" << grams.size() << "]=>{";
size_t index = 0; size_t index = 0;
for (vector<Unigram>::const_iterator gi = inGrams.begin() ; gi != inGrams.end() ; ++gi, ++index) { for (std::vector<Unigram>::const_iterator gi = grams.begin();
inStream << index << "=>"; gi != grams.end(); ++gi, ++index) {
inStream << *gi; stream << index << "=>";
if (gi + 1 != inGrams.end()) { stream << *gi;
inStream << ","; if (gi + 1 != grams.end()) {
stream << ",";
} }
} }
inStream << "}"; stream << "}";
return inStream; return stream;
} }
inline Unigram::Unigram() inline Unigram::Unigram() : score(0.0) {}
: score(0.0)
{ inline bool Unigram::operator==(const Unigram& another) const {
return keyValue == another.keyValue && score == another.score;
} }
inline bool Unigram::operator==(const Unigram& inAnother) const inline bool Unigram::operator<(const Unigram& another) const {
{ if (keyValue < another.keyValue) {
return keyValue == inAnother.keyValue && score == inAnother.score;
}
inline bool Unigram::operator<(const Unigram& inAnother) const
{
if (keyValue < inAnother.keyValue) {
return true; return true;
} } else if (keyValue == another.keyValue) {
else if (keyValue == inAnother.keyValue) { return score < another.score;
return score < inAnother.score;
} }
return false; return false;
} }
inline bool Unigram::ScoreCompare(const Unigram& a, const Unigram& b) inline bool Unigram::ScoreCompare(const Unigram& a, const Unigram& b) {
{
return a.score > b.score; return a.score > b.score;
} }
} } // namespace Gramambular
} } // namespace Taiyan
#endif #endif

View File

@ -17,59 +17,61 @@ 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. 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 #ifndef WALKER_H_
#define Walker_h #define WALKER_H_
#include <algorithm> #include <algorithm>
#include <vector>
#include "Grid.h" #include "Grid.h"
namespace Taiyan { namespace Taiyan {
namespace Gramambular { namespace Gramambular {
using namespace std;
class Walker { class Walker {
public: public:
Walker(Grid* inGrid); explicit Walker(Grid* inGrid);
const vector<NodeAnchor> reverseWalk(size_t inLocation, double inAccumulatedScore = 0.0); const std::vector<NodeAnchor> reverseWalk(size_t location,
double accumulatedScore = 0.0);
protected: protected:
Grid* m_grid; Grid* m_grid;
}; };
inline Walker::Walker(Grid* inGrid) inline Walker::Walker(Grid* inGrid) : m_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>();
} }
inline const vector<NodeAnchor> Walker::reverseWalk(size_t inLocation, double inAccumulatedScore) std::vector<std::vector<NodeAnchor> > paths;
{
if (!inLocation || inLocation > m_grid->width()) {
return vector<NodeAnchor>();
}
vector<vector<NodeAnchor> > paths; std::vector<NodeAnchor> nodes = m_grid->nodesEndingAt(location);
vector<NodeAnchor> nodes = m_grid->nodesEndingAt(inLocation); for (std::vector<NodeAnchor>::iterator ni = nodes.begin(); ni != nodes.end();
++ni) {
for (vector<NodeAnchor>::iterator ni = nodes.begin() ; ni != nodes.end() ; ++ni) {
if (!(*ni).node) { if (!(*ni).node) {
continue; continue;
} }
(*ni).accumulatedScore = inAccumulatedScore + (*ni).node->score(); (*ni).accumulatedScore = accumulatedScore + (*ni).node->score();
vector<NodeAnchor> path = reverseWalk(inLocation - (*ni).spanningLength, (*ni).accumulatedScore); std::vector<NodeAnchor> path =
reverseWalk(location - (*ni).spanningLength, (*ni).accumulatedScore);
path.insert(path.begin(), *ni); path.insert(path.begin(), *ni);
paths.push_back(path); paths.push_back(path);
} }
if (!paths.size()) { if (!paths.size()) {
return vector<NodeAnchor>(); return std::vector<NodeAnchor>();
} }
vector<NodeAnchor>* result = &*(paths.begin()); std::vector<NodeAnchor>* result = &*(paths.begin());
for (vector<vector<NodeAnchor> >::iterator pi = paths.begin() ; pi != paths.end() ; ++pi) { for (std::vector<std::vector<NodeAnchor> >::iterator pi = paths.begin();
pi != paths.end(); ++pi) {
if ((*pi).back().accumulatedScore > result->back().accumulatedScore) { if ((*pi).back().accumulatedScore > result->back().accumulatedScore) {
result = &*pi; result = &*pi;
} }
@ -77,7 +79,7 @@ namespace Taiyan {
return *result; return *result;
} }
} } // namespace Gramambular
} } // namespace Taiyan
#endif #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 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."; "\"%@\" 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."; "\"%@\" 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…"; "Edit Phrase Replacement Table…" = "Edit Phrase Replacement Table…";
"Use Phrase Replacement" = "Use Phrase Replacement"; "Use Phrase Replacement" = "Use Phrase Replacement";
"Candidates keys cannot be empty." = "Candidates keys cannot be empty."; "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 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."; "\"%@\" 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."; "\"%@\" 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…"; "Edit Phrase Replacement Table…" = "Edit Phrase Replacement Table…";
"Use Phrase Replacement" = "Use Phrase Replacement"; "Use Phrase Replacement" = "Use Phrase Replacement";
"Candidates keys cannot be empty." = "Candidates keys cannot be empty."; "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 must ≥ 2 for a user phrase." = "「%@」もう1つ文字のお選びを。";
"\"%@\" length should ≤ %d for a user phrase." = "「%@」文字数過剰で登録不可、%d 文字以内にして下さい。"; "\"%@\" length should ≤ %d for a user phrase." = "「%@」文字数過剰で登録不可、%d 文字以内にして下さい。";
"\"%@\" selected. ENTER to add user phrase." = "「%@」を ENTER で辞書に登録。"; "\"%@\" selected. ENTER to add user phrase." = "「%@」を ENTER で辞書に登録。";
"\"%@\" already exists." = "「%@」は既存語彙である。"; "\"%@\" already exists, ENTER to boost its priority." = "「%@」は既存語彙であり、ENTER で最優先にする。";
"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." = "「%@」字数超过 %d、无法自订。"; "\"%@\" length should ≤ %d for a user phrase." = "「%@」字数超过 %d、无法自订。";
"\"%@\" selected. ENTER to add user phrase." = "「%@」敲 Enter 添入自订语汇。"; "\"%@\" selected. ENTER to add user phrase." = "「%@」敲 Enter 添入自订语汇。";
"\"%@\" already exists." = "「%@」已存在。"; "\"%@\" already exists, ENTER to boost its priority." = "「%@」已存在,敲 ENTER 以提升其权重。";
"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." = "「%@」字數超過 %d、無法自訂。"; "\"%@\" length should ≤ %d for a user phrase." = "「%@」字數超過 %d、無法自訂。";
"\"%@\" selected. ENTER to add user phrase." = "「%@」敲 Enter 添入自訂語彙。"; "\"%@\" selected. ENTER to add user phrase." = "「%@」敲 Enter 添入自訂語彙。";
"\"%@\" already exists." = "「%@」已存在。"; "\"%@\" already exists, ENTER to boost its priority." = "「%@」已存在,敲 ENTER 以提升其權重。";
"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

@ -86,7 +86,7 @@ extension RangeReplaceableCollection where Element: Hashable {
let menuItem_vChewingDachen = NSMenuItem() let menuItem_vChewingDachen = NSMenuItem()
menuItem_vChewingDachen.title = String(format: NSLocalizedString("vChewing Dachen (Not Finished Yet)", comment: "")) 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) basisKeyboardLayoutButton.menu?.addItem(menuItem_vChewingDachen)
let basisKeyboardLayoutID = Preferences.basisKeyboardLayout let basisKeyboardLayoutID = Preferences.basisKeyboardLayout

View File

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

View File

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