Tomotaka SUWA
t-suw****@users*****
2007年 8月 19日 (日) 19:00:32 JST
Index: AquaSKK/src/component/BIM.cpp diff -u /dev/null AquaSKK/src/component/BIM.cpp:1.1.2.1 --- /dev/null Sun Aug 19 19:00:32 2007 +++ AquaSKK/src/component/BIM.cpp Sun Aug 19 19:00:32 2007 @@ -0,0 +1,40 @@ +/* + $Id: BIM.cpp,v 1.1.2.1 2007/08/19 10:00:32 t-suwa Exp $ + + MacOS X implementation of the SKK input method. + + Copyright (C) 2002-2004 phonohawk + Copyright (C) 2005-2007 Tomotaka SUWA <t.suw****@mac*****> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <Carbon/Carbon.h> + +#include "SKKComponent.h" + +// éçã¡ãã¥ã¼ã®ã¢ã¤ã³ã³ãè¨å®ããã +void BIMSetPencilMenuIcon(int menu_icon_index) { + CFStringRef inputModes[] = { + kTextServiceInputModeJapanese, + kTextServiceInputModeJapaneseKatakana, + kTextServiceInputModeJapaneseHalfWidthKana, + kTextServiceInputModeJapaneseFullWidthRoman, + kTextServiceInputModeRoman, + 0 + }; + + SKKComponent::theInstance().NotifyInputMode(inputModes[menu_icon_index]); +} Index: AquaSKK/src/component/BIMInputEvents.cpp diff -u /dev/null AquaSKK/src/component/BIMInputEvents.cpp:1.1.2.1 --- /dev/null Sun Aug 19 19:00:32 2007 +++ AquaSKK/src/component/BIMInputEvents.cpp Sun Aug 19 19:00:32 2007 @@ -0,0 +1,36 @@ +/* + $Id: BIMInputEvents.cpp,v 1.1.2.1 2007/08/19 10:00:32 t-suwa Exp $ + + MacOS X implementation of the SKK input method. + + Copyright (C) 2002 phonohawk + Copyright (C) 2006-2007 Tomotaka SUWA <t.suw****@mac*****> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <Carbon/Carbon.h> +#include "BIMClientServer.h" +#include "BIMInputEvents.h" +#include "SKKComponent.h" +#include "SKKSession.h" + +// ã¤ã³ãããã¨ãªã¢ã®å種æ å ±ãå¾ãã +void BIMHandleOffsetToPos(struct OffsetToPosParams* params) { + Point pt = SKKComponent::theInstance().Session().GetInputPosition(); + + params->fReplyPoint.h = pt.h; + params->fReplyPoint.v = pt.v; +} Index: AquaSKK/src/component/BIMInputEvents.h diff -u /dev/null AquaSKK/src/component/BIMInputEvents.h:1.1.2.1 --- /dev/null Sun Aug 19 19:00:32 2007 +++ AquaSKK/src/component/BIMInputEvents.h Sun Aug 19 19:00:32 2007 @@ -0,0 +1,29 @@ +/* + $Id: BIMInputEvents.h,v 1.1.2.1 2007/08/19 10:00:32 t-suwa Exp $ + + MacOS X implementation of the SKK input method. + + Copyright (C) 2002 phonohawk + Copyright (C) 2005-2006 Tomotaka SUWA <t.suw****@mac*****> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef INC__BIMInputEvents__ +#define INC__BIMInputEvents__ + +void BIMHandleOffsetToPos(struct OffsetToPosParams *offsetToPosParams); + +#endif Index: AquaSKK/src/component/IMSessionInputMode.cpp diff -u /dev/null AquaSKK/src/component/IMSessionInputMode.cpp:1.1.2.1 --- /dev/null Sun Aug 19 19:00:32 2007 +++ AquaSKK/src/component/IMSessionInputMode.cpp Sun Aug 19 19:00:32 2007 @@ -0,0 +1,62 @@ +/* + $Id: IMSessionInputMode.cpp,v 1.1.2.1 2007/08/19 10:00:32 t-suwa Exp $ + + MacOS X implementation of the SKK input method. + + Copyright (C) 2002-2004 phonohawk + Copyright (C) 2005-2007 Tomotaka SUWA <t.suw****@mac*****> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "SKKComponent.h" +#include "SKKSession.h" +#include "IMSessionInputMode.h" + +void IMSessionInputMode::terminate() { + ParentInputMode::terminate(); + + SKKComponent::theInstance().Session().Terminate(); +} + +void IMSessionInputMode::fix(const CppCFString& str) { + int caretpos = str.indexOf(kCaret); + + if(caretpos != -1 && (unsigned)caretpos < str.length() - 1) { + CppCFString tmp; + + tmp.append(str.substring(0, caretpos)); + tmp.append(str.substring(caretpos + 1)); + + SKKComponent::theInstance().Session().FixString(tmp.getString()); + } else { + SKKComponent::theInstance().Session().FixString(str.getString()); + } +} + +void IMSessionInputMode::display(const CppCFString& str) { + int caretpos = str.indexOf(kCaret); + + if(caretpos != -1 && (unsigned)caretpos < str.length() - 1) { + CppCFString tmp; + + tmp.append(str.substring(0, caretpos)); + tmp.append(str.substring(caretpos + 1)); + + SKKComponent::theInstance().Session().DisplayString(tmp.getString(), 0, caretpos); + } else { + SKKComponent::theInstance().Session().DisplayString(str.getString(), 0, str.length()); + } +} Index: AquaSKK/src/component/IMSessionInputMode.h diff -u /dev/null AquaSKK/src/component/IMSessionInputMode.h:1.1.2.1 --- /dev/null Sun Aug 19 19:00:32 2007 +++ AquaSKK/src/component/IMSessionInputMode.h Sun Aug 19 19:00:32 2007 @@ -0,0 +1,38 @@ +/* + $Id: IMSessionInputMode.h,v 1.1.2.1 2007/08/19 10:00:32 t-suwa Exp $ + + MacOS X implementation of the SKK input method. + + Copyright (C) 2002 phonohawk + Copyright (C) 2006-2007 Tomotaka SUWA <t.suw****@mac*****> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef INC__IMSessionInputMode__ +#define INC__IMSessionInputMode__ + +#include "ParentInputMode.h" + +class CppCFString; + +class IMSessionInputMode: public ParentInputMode { +public: + virtual void terminate(); + virtual void fix(const CppCFString& str); + virtual void display(const CppCFString& str); +}; + +#endif Index: AquaSKK/src/component/SKK.h diff -u /dev/null AquaSKK/src/component/SKK.h:1.1.2.1 --- /dev/null Sun Aug 19 19:00:32 2007 +++ AquaSKK/src/component/SKK.h Sun Aug 19 19:00:32 2007 @@ -0,0 +1,36 @@ +/* -*- C++ -*- + $Id: SKK.h,v 1.1.2.1 2007/08/19 10:00:32 t-suwa Exp $ + + MacOS X implementation of the SKK input method. + + Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef INC__SKK__ +#define INC__SKK__ + +namespace SKK { + enum InputMode { + Hirakana, + Katakana, + Jisx0201Kana, + Jisx0208Latin, + Ascii + }; +} + +#endif Index: AquaSKK/src/component/SKK.r diff -u /dev/null AquaSKK/src/component/SKK.r:1.1.2.1 --- /dev/null Sun Aug 19 19:00:32 2007 +++ AquaSKK/src/component/SKK.r Sun Aug 19 19:00:32 2007 @@ -0,0 +1,148 @@ +/* + $Id: SKK.r,v 1.1.2.1 2007/08/19 10:00:32 t-suwa Exp $ + + MacOS X implementation of the SKK input method. + + Copyright (C) 2002 phonohawk + Copyright (C) 2006-2007 Tomotaka SUWA <t.suw****@mac*****> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define thng_RezTemplateVersion 1 + +#include <Carbon/Carbon.r> + +#ifdef ppc_YES + #define TARGET_REZ_MAC_PPC 1 +#endif + +#ifdef i386_YES + #define TARGET_REZ_MAC_X86 1 +#endif + +#if !defined(TARGET_REZ_MAC_X86) + #define TARGET_REZ_MAC_X86 0 +#endif + +#if !(TARGET_REZ_MAC_PPC || TARGET_REZ_MAC_X86) + #if TARGET_CPU_X86 + #undef TARGET_REZ_MAC_X86 + #define TARGET_REZ_MAC_X86 1 + #elif TARGET_CPU_PPC + #undef TARGET_REZ_MAC_PPC + #define TARGET_REZ_MAC_PPC 1 + #endif +#endif + +#if TARGET_REZ_MAC_PPC && TARGET_REZ_MAC_X86 + #define TARGET_REZ_UNIVERSAL_COMPONENTS + #define Target_PlatformType platformPowerPCNativeEntryPoint + #define Target_SecondPlatformType platformIA32NativeEntryPoint +#elif TARGET_REZ_MAC_X86 + #define Target_PlatformType platformIA32NativeEntryPoint +#else + #define Target_PlatformType platformPowerPCNativeEntryPoint +#endif + +#define kAquaSKKBaseResouceID 16384 +#define kAquaSKKComponentFlags 0x8000 + smJapanese * 0x100 + langJapanese + +// "jp.sourceforge.AquaSKKInputMethod" Ì pascal ¶ñ +data 'cbnm' (0) { + $"216a 702e 736f 7572 6365 666f 7267 652e" + $"4171 7561 534b 4b49 6e70 7574 4d65 7468" + $"6f64" +}; + +resource 'thng' (kAquaSKKBaseResouceID) { + 'tsvc', // type + 'inpm', // subtype + 'askk', // manufacturer + 0, // component flags + 0, // component flags mask + 0, // code type + 0, // code ID + 'STR ', // name type + kAquaSKKBaseResouceID, // name ID + 'STR ', // info type + kAquaSKKBaseResouceID + 1, // info ID + 'kcs8', // icon type + kAquaSKKBaseResouceID, // icon ID + 0x00010000, // version + componentHasMultiplePlatforms, // registration flags + 0, // resource ID of icon family + { // component platform information + kAquaSKKComponentFlags, + 'dlle', + kAquaSKKBaseResouceID, + Target_PlatformType, +#ifdef TARGET_REZ_UNIVERSAL_COMPONENTS + kAquaSKKComponentFlags, + 'dlle', + kAquaSKKBaseResouceID, + Target_SecondPlatformType +#endif + }; +}; + +resource 'dlle' (kAquaSKKBaseResouceID) { + "SKKEntryPoint" +}; + +resource 'STR ' (kAquaSKKBaseResouceID) { + "AquaSKK" +}; + +resource 'STR ' (kAquaSKKBaseResouceID + 1) { + "AquaSKK Input Method for Mac OS X" +}; + +data 'kcs#' (kAquaSKKBaseResouceID) { + $"FEFE FE82 7C44 7C44 3828 3828 1010 0000" + $"FEFE 82FE 447C 447C 2838 2838 1010 0000" + $"FEFE FEFE 7C7C 7C7C 3838 3838 1010 0000" + $"FEFE FEFE 7C7C 7C7C 3838 3838 1010 0000" +}; + +data 'kcs4' (kAquaSKKBaseResouceID) { + $"EEEE EEE0 DDDD DDD0 EDDE EFE0 D00C CCD0" + $"0EEE FE00 0DCC CD00 0EEE FE00 0DCC CD00" + $"00EF E000 00DC D000 00EF E000 00DC D000" + $"000E 0000 000D 0000 0000 0000 0000 0000" + $"DDDD DDD0 EEEE EEE0 D00C CCD0 EDDE EFE0" + $"0DCC CD00 0EEE FE00 0DCC CD00 0EEE FE00" + $"00DC D000 00EF E000 00DC D000 00EF E000" + $"000D 0000 000E 0000 0000 0000 0000 0000" +}; + +data 'kcs8' (kAquaSKKBaseResouceID) { + $"FBFB FBFB FBFB FB00 F9F9 F9F9 F9F9 F900" + $"FAF9 FAFB FCFD FA00 F800 F5F6 2BF7 F800" + $"00FB FBFC FDFB 0000 00F9 F62B F7F9 0000" + $"00FA FBFC FDFA 0000 00F8 F62B F7F8 0000" + $"0000 FBFD FB00 0000 0000 F9F7 F900 0000" + $"0000 FAFD FA00 0000 0000 F8F7 F800 0000" + $"0000 00FB 0000 0000 0000 00F9 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"F9F9 F9F9 F9F9 F900 FBFB FBFB FBFB FB00" + $"F800 F5F6 2BF7 F800 FAF9 FAFB FCFD FA00" + $"00F9 F62B F7F9 0000 00FB FBFC FDFB 0000" + $"00F8 F62B F7F8 0000 00FA FBFC FDFA 0000" + $"0000 F9F7 F900 0000 0000 FBFD FB00 0000" + $"0000 F8F7 F800 0000 0000 FAFD FA00 0000" + $"0000 00F9 0000 0000 0000 00FB 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" +}; Index: AquaSKK/src/component/SKKComponent.cpp diff -u /dev/null AquaSKK/src/component/SKKComponent.cpp:1.1.2.1 --- /dev/null Sun Aug 19 19:00:32 2007 +++ AquaSKK/src/component/SKKComponent.cpp Sun Aug 19 19:00:32 2007 @@ -0,0 +1,347 @@ +/* -*- C++ -*- + $Id: SKKComponent.cpp,v 1.1.2.1 2007/08/19 10:00:32 t-suwa Exp $ + + MacOS X implementation of the SKK input method. + + Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <iostream> +#include <map> +#include <sstream> +#include <algorithm> + +#include "CppCFData.h" + +#include "BIMClientServer.h" +#include "ClientConfiguration.h" +#include "ClientMessageReceiver.h" +#include "ServerConnectionFactory.h" +#include "SKKConfig.h" + +#include "SKKComponent.h" +#include "SKKSession.h" + +enum { + kAboutCommand = 'abou', + kPreferencesCommand = 'pref', + kProjectWebCommand = 'sfjp', + kTipsCommand = 'tips', + kUseBrandNewEngine = 'bnew', + kUseLegacyEngine = 'lgcy' +}; + +static CFStringRef project_web_url = CFSTR("http://aquaskk.sourceforge.jp/"); +static CFStringRef tips_url = CFSTR("http://aquaskk.sourceforge.jp/inside_aquaskk/"); + +// ====================================================================== +// ã¦ã¼ãã£ãªã㣠+// ====================================================================== +static void InitializeKeyboardLayout() { + KeyboardLayoutIdentifier id = ClientConfiguration::theInstance().kbdLayoutId(); + KeyboardLayoutRef kbd; + + KLGetKeyboardLayoutWithIdentifier(id, &kbd); + KLSetCurrentKeyboardLayout(kbd); +} + +static void OpenURL(const CFStringRef str) { + CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, str, 0); + + LSOpenCFURLRef(url, 0); + + CFRelease(url); +} + +// ====================================================================== +// åé¤ãã¡ã³ã¯ã¿ +// ====================================================================== +struct DeleteSession { + void operator()(const std::pair<ComponentInstance, SKKSession*>& obj) const { + delete obj.second; + } +}; + +SKKComponent& SKKComponent::theInstance() { + static SKKComponent obj; + return obj; +} + +SKKComponent::SKKComponent() : active_(0), menu_(0) { + // Nib ãã¡ã¤ã«ããã¡ãã¥ã¼ããã¼ããã + CFBundleRef bundle = CFBundleGetBundleWithIdentifier(CFSTR(kIMBundleIdentifier)); + if(bundle) { + IBNibRef nib; + + OSStatus err = CreateNibReferenceWithCFBundle(bundle, CFSTR("Menu"), &nib); + if(err == noErr) { + err = CreateMenuFromNib(nib, CFSTR("AquaSKK"), &menu_); + DisposeNibReference(nib); + CFRetain(menu_); + } + + // éçã¡ãã¥ã¼ã®ã¤ãã³ããã³ãã©ãã¤ã³ã¹ãã¼ã«ããã + EventTypeSpec spec = { kEventClassCommand, kEventProcessCommand }; + InstallEventHandler(GetMenuEventTarget(menu_), &SKKComponent::menuEventHandler, 1, &spec, 0, 0); + } + + // ã¡ãã»ã¼ã¸åä¿¡æ©æ§ãåæå + ClientMessageReceiver::start(kAquaSKKClientRunLoopMode); + + // AquaSKKServer ã®èµ·å + ServerConnectionFactory::theInstance().prepareServer(); +} + +SKKComponent::~SKKComponent() { + std::for_each(sessions_.begin(), sessions_.end(), DeleteSession()); + + if(menu_) CFRelease(menu_); +} + +SKKSession& SKKComponent::Session() { + return *active_; +} + +// ====================================================================== +// Carbon ã³ã³ãã¼ãã³ãã¤ã³ã¿ãã§ã¼ã¹ +// ====================================================================== +ComponentResult SKKComponent::ComponentOpen(const ComponentInstance instance) { + // è¨å®ããªãã¼ã + ClientConfiguration::theInstance().reloadConfiguration(); + + sessions_[instance] = new SKKSession(instance); + + InitializeKeyboardLayout(); + + return noErr; +} + +ComponentResult SKKComponent::ComponentClose(const ComponentInstance instance) { + delete sessions_[instance]; + sessions_.erase(instance); + + return noErr; +} + +ComponentResult SKKComponent::ComponentCanDo(SInt16 selector) const { + switch(selector) { + case kComponentOpenSelect: + case kComponentCloseSelect: + case kComponentCanDoSelect: + case kComponentVersionSelect: + case kCMGetScriptLangSupport: + case kCMInitiateTextService: + case kCMTerminateTextService: + case kCMActivateTextService: + case kCMDeactivateTextService: + case kCMTextServiceEvent: + case kCMGetTextServiceMenu: + case kCMFixTextService: + case kCMHidePaletteWindows: + case kCMCopyTextServiceInputModeList: + case kCMSetTextServiceProperty: + return true; + } + + return false; +} + +ComponentResult SKKComponent::ComponentVersion() const { + return 0x00010000; +} + +// ====================================================================== +// TSM ã³ã³ãã¼ãã³ãã¤ã³ã¿ãã§ã¼ã¹ +// ====================================================================== +ComponentResult SKKComponent::GetScriptLangSupport(ScriptLanguageSupportHandle* script) const { + if(!*script) { + *script = (ScriptLanguageSupportHandle)NewHandle(sizeof(SInt16)); + if(!*script) return memFullErr; + } else { + SetHandleSize((Handle)*script, sizeof(SInt16)); + } + + OSStatus result = MemError(); + if(result == noErr) { + (**script)->fScriptLanguageCount = 0; + } + + ScriptLanguageRecord slr = { kTextEncodingUnicodeDefault, langJapanese }; + result = PtrAndHand(&slr, (Handle)*script, sizeof(ScriptLanguageRecord)); + + if(result == noErr) { + (**script)->fScriptLanguageCount ++; + } else { + DisposeHandle((Handle)*script ); + *script = 0; + } + + return result; +} + +ComponentResult SKKComponent::InitiateTextService(const ComponentInstance) { + return noErr; +} + +ComponentResult SKKComponent::TerminateTextService(const ComponentInstance) { + return noErr; +} + +ComponentResult SKKComponent::ActivateTextService(const ComponentInstance instance) { + active_ = sessions_[instance]; + + // è¨å®ããªãã¼ã + ClientConfiguration::theInstance().reloadConfiguration(); + + // ã¢ã¯ãã£ãã«ãªã£ãäºããµã¼ãã¼ã«ä¼ãã + ServerConnectionFactory::theInstance().newConnection().send(kBasicMessageActivated); + + // ãã¼ãã¼ãã¬ã¤ã¢ã¦ããåæåãã + InitializeKeyboardLayout(); + + return noErr; +} + +ComponentResult SKKComponent::DeactivateTextService(const ComponentInstance) { + return noErr; +} + +ComponentResult SKKComponent::TextServiceEvent(const EventRef event) { + // ãã¼å ¥åå¦ç + return active_->HandleInput(event); +} + +ComponentResult SKKComponent::GetTextServiceMenu(MenuRef* menu) const { + *menu = menu_; + + return noErr; +} + +ComponentResult SKKComponent::FixTextService() { + active_->FixString(CFSTR("")); + + return noErr; +} + +ComponentResult SKKComponent::HidePaletteWindows() { + ServerConnectionFactory::theInstance().newConnection().send(kBasicMessageHidePalettes); + + return noErr; +} + +ComponentResult SKKComponent::CopyTextServiceInputModeList(CFDictionaryRef* modes) { + CFBundleRef bundle = CFBundleGetBundleWithIdentifier(CFSTR(kIMBundleIdentifier)); + if(!bundle) { + return noErr; + } + + CFDictionaryRef dict = CFBundleGetInfoDictionary(bundle); + if(!dict) { + return noErr; + } + + CFRetain(dict); + CFDictionaryRef tmp = (CFDictionaryRef)CFDictionaryGetValue(dict, kComponentBundleInputModeDictKey); + if(tmp) { + *modes = CFDictionaryCreateCopy(kCFAllocatorDefault, tmp); + } + CFRelease(dict); + + return noErr; +} + +ComponentResult SKKComponent::SetTextServiceProperty(TextServicePropertyTag tag, TextServicePropertyValue value) { + if(tag != kTextServiceInputModePropertyTag) { + return tsmComponentPropertyUnsupportedErr; + } + + static const struct { + SKK::InputMode skk; + CFStringRef tsm; + } modes[] = { + { SKK::Hirakana, kTextServiceInputModeJapanese }, + { SKK::Katakana, kTextServiceInputModeJapaneseKatakana }, + { SKK::Jisx0201Kana, kTextServiceInputModeJapaneseHalfWidthKana }, + { SKK::Jisx0208Latin, kTextServiceInputModeJapaneseFullWidthRoman }, + { SKK::Ascii, kTextServiceInputModeRoman }, + { SKK::Hirakana, 0 } + }; + + CFStringRef str = (CFStringRef)value; + for(int i = 0; modes[i].tsm != 0; ++ i) { + if(CFStringCompare(str, modes[i].tsm, 0) == 0) { + active_->SelectInputMode(modes[i].skk); + break; + } + } + + return noErr; +} + +// ====================================================================== +// ã¦ã¼ãã£ãªã㣠+// ====================================================================== +void SKKComponent::NotifyInputMode(const CFStringRef mode) const { + ComponentDescription cd; + + cd.componentType = kTextService; + cd.componentSubType = kKeyboardInputMethodClass; + cd.componentManufacturer = 'askk'; + cd.componentFlags = 0; + cd.componentFlagsMask = 0; + + // éçã¡ãã¥ã¼ã®å ¥åã¢ã¼ãã¢ã¤ã³ã³ãå¤æ´ãã + TSMSelectInputMode(FindNextComponent(0, &cd), mode); +} + +// ====================================================================== +// ã¡ãã¥ã¼ã¤ãã³ããã³ãã© +// ====================================================================== +OSStatus SKKComponent::menuEventHandler(EventHandlerCallRef, EventRef event, void*) { + HICommand cmd; + + OSStatus result = GetEventParameter(event, kEventParamDirectObject, typeHICommand, 0, sizeof(cmd), 0, &cmd); + if(result == noErr) { + switch(cmd.commandID) { + case kAboutCommand: + ServerConnectionFactory::theInstance().newConnection().send(kSKKShowAboutBox); + break; + + case kPreferencesCommand: + ServerConnectionFactory::theInstance().newConnection().send(kSKKShowPreferencesBox); + break; + + case kProjectWebCommand: + OpenURL(project_web_url); + break; + + case kTipsCommand: + OpenURL(tips_url); + break; + + default: + std::cerr << "unknown menu event[" << cmd.commandID << "], " + << "index[" << cmd.menu.menuItemIndex << "]" << std::endl; + result = eventNotHandledErr; + break; + } + } else { + result = eventNotHandledErr; + } + + return result; +} Index: AquaSKK/src/component/SKKComponent.h diff -u /dev/null AquaSKK/src/component/SKKComponent.h:1.1.2.1 --- /dev/null Sun Aug 19 19:00:32 2007 +++ AquaSKK/src/component/SKKComponent.h Sun Aug 19 19:00:32 2007 @@ -0,0 +1,71 @@ +/* -*- C++ -*- + $Id: SKKComponent.h,v 1.1.2.1 2007/08/19 10:00:32 t-suwa Exp $ + + MacOS X implementation of the SKK input method. + + Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef INC__SKKComponent__ +#define INC__SKKComponent__ + +#include <Carbon/Carbon.h> +#include <map> +#include "SKK.h" + +class SKKSession; + +// TSM ã³ã³ãã¼ãã³ã +class SKKComponent { + std::map<ComponentInstance, SKKSession*> sessions_; + SKKSession* active_; + MenuRef menu_; + + SKKComponent(); + static OSStatus menuEventHandler(EventHandlerCallRef chain, EventRef event, void* data); + +public: + static SKKComponent& theInstance(); + ~SKKComponent(); + + // ã¢ã¯ãã£ããªã»ãã·ã§ã³ + SKKSession& Session(); + + // Carbon ã³ã³ãã¼ãã³ãã¤ã³ã¿ãã§ã¼ã¹ + ComponentResult ComponentOpen(const ComponentInstance instance); + ComponentResult ComponentClose(const ComponentInstance instance); + ComponentResult ComponentCanDo(SInt16 selector) const; + ComponentResult ComponentVersion() const; + + // TSM ã³ã³ãã¼ãã³ãã¤ã³ã¿ãã§ã¼ã¹ + ComponentResult GetScriptLangSupport(ScriptLanguageSupportHandle* script) const; + ComponentResult InitiateTextService(const ComponentInstance instance); + ComponentResult TerminateTextService(const ComponentInstance instance); + ComponentResult ActivateTextService(const ComponentInstance instance); + ComponentResult DeactivateTextService(const ComponentInstance instance); + ComponentResult TextServiceEvent(const EventRef event); + ComponentResult GetTextServiceMenu(MenuRef* menu) const; + ComponentResult FixTextService(); + ComponentResult HidePaletteWindows(); + ComponentResult CopyTextServiceInputModeList(CFDictionaryRef* modes); + ComponentResult SetTextServiceProperty(TextServicePropertyTag tag, TextServicePropertyValue value); + + // ã¦ã¼ãã£ãªã㣠+ void NotifyInputMode(const CFStringRef mode) const; +}; + +#endif Index: AquaSKK/src/component/SKKEntryPoint.cpp diff -u /dev/null AquaSKK/src/component/SKKEntryPoint.cpp:1.1.2.1 --- /dev/null Sun Aug 19 19:00:32 2007 +++ AquaSKK/src/component/SKKEntryPoint.cpp Sun Aug 19 19:00:32 2007 @@ -0,0 +1,215 @@ +/* + $Id: SKKEntryPoint.cpp,v 1.1.2.1 2007/08/19 10:00:32 t-suwa Exp $ + + MacOS X implementation of the SKK input method. + + Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <Carbon/Carbon.h> +#include "SKKComponent.h" + +// ====================================================================== +// ã³ã³ãã¼ãã³ãé¢æ°èµ·åãã«ã +// ====================================================================== +class Invoke { + ComponentFunctionUPP function_; + +public: + Invoke(ProcPtr proc, ProcInfoType info) { + function_ = NewComponentFunctionUPP(proc, info); + } + + ~Invoke() { + DisposeComponentFunctionUPP(function_); + } + + ComponentResult operator()(ComponentParameters* params) { + return CallComponentFunction(params, function_); + } +}; + +// ====================================================================== +// ã³ã³ãã¼ãã³ãé¢æ°ç¾¤ +// ====================================================================== +pascal ComponentResult ComponentOpen_(ComponentInstance instance) { + return SKKComponent::theInstance().ComponentOpen(instance); +} + +pascal ComponentResult ComponentClose_(ComponentInstance instance) { + return SKKComponent::theInstance().ComponentClose(instance); +} + +pascal ComponentResult ComponentCanDo_(SInt16 selector) { + return SKKComponent::theInstance().ComponentCanDo(selector); +} + +pascal ComponentResult ComponentVersion_() { + return SKKComponent::theInstance().ComponentVersion(); +} + +pascal ComponentResult GetScriptLangSupport_(ScriptLanguageSupportHandle* ptr) { + return SKKComponent::theInstance().GetScriptLangSupport(ptr); +} + +pascal ComponentResult InitiateTextService_(const ComponentInstance instance) { + return SKKComponent::theInstance().InitiateTextService(instance); +} + +pascal ComponentResult TerminateTextService_(const ComponentInstance instance) { + return SKKComponent::theInstance().TerminateTextService(instance); +} + +pascal ComponentResult ActivateTextService_(const ComponentInstance instance) { + return SKKComponent::theInstance().ActivateTextService(instance); +} + +pascal ComponentResult DeactivateTextService_(const ComponentInstance instance) { + return SKKComponent::theInstance().DeactivateTextService(instance); +} + +pascal ComponentResult TextServiceEvent_(const EventRef event) { + return SKKComponent::theInstance().TextServiceEvent(event); +} + +pascal ComponentResult GetTextServiceMenu_(MenuRef* menu_ptr) { + return SKKComponent::theInstance().GetTextServiceMenu(menu_ptr); +} + +pascal ComponentResult FixTextService_() { + return SKKComponent::theInstance().FixTextService(); +} + +pascal ComponentResult HidePaletteWindows_() { + return SKKComponent::theInstance().HidePaletteWindows(); +} + +pascal ComponentResult CopyTextServiceInputModeList_(CFDictionaryRef* mode) { + return SKKComponent::theInstance().CopyTextServiceInputModeList(mode); +} + +pascal ComponentResult SetTextServiceProperty_(TextServicePropertyTag tag, TextServicePropertyValue value) { + return SKKComponent::theInstance().SetTextServiceProperty(tag, value); +} + +// ====================================================================== +// ã³ã³ãã¼ãã³ãé¢æ°æ å ±ç¾¤ãã¾ãã¯é»éè¡ ;-) +// ====================================================================== +enum { + uppComponentOpen = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentInstance))), + + uppComponentClose = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentInstance))), + + uppComponentCanDo = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(SInt16))), + + uppComponentVersion = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))), + + uppGetScriptLangSupport = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ScriptLanguageSupportHandle*))), + + uppInitiateTextService = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentInstance))), + + uppTerminateTextService = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentInstance))), + + uppActivateTextService = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentInstance))), + + uppDeactivateTextService = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentInstance))), + + uppTextServiceEvent = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(EventRef))), + + uppGetTextServiceMenu = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(MenuRef*))), + + uppFixTextService = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))), + + uppHidePaletteWindows = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))), + + uppCopyTextServiceInputModeList = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(CFDictionaryRef*))), + + uppSetTextServiceProperty = kPascalStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(TextServicePropertyTag))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(TextServicePropertyValue))) +}; + +// ====================================================================== +// ã³ã¼ã«ããã¯ç¨æ§é ä½ +// ====================================================================== +struct callback { + int selector; + ProcPtr addr; + ProcInfoType info; +}; + +// ====================================================================== +// ã³ã¼ã«ããã¯ãã¼ãã« +// ====================================================================== +static callback table[] = { + { kComponentOpenSelect, (ProcPtr)ComponentOpen_, uppComponentOpen }, + { kComponentCloseSelect, (ProcPtr)ComponentClose_, uppComponentClose }, + { kComponentCanDoSelect, (ProcPtr)ComponentCanDo_, uppComponentCanDo }, + { kComponentVersionSelect, (ProcPtr)ComponentVersion_, uppComponentVersion }, + { kCMGetScriptLangSupport, (ProcPtr)GetScriptLangSupport_, uppGetScriptLangSupport }, + { kCMInitiateTextService, (ProcPtr)InitiateTextService_, uppInitiateTextService }, + { kCMTerminateTextService, (ProcPtr)TerminateTextService_, uppTerminateTextService }, + { kCMActivateTextService, (ProcPtr)ActivateTextService_, uppActivateTextService }, + { kCMDeactivateTextService, (ProcPtr)DeactivateTextService_, uppDeactivateTextService }, + { kCMTextServiceEvent, (ProcPtr)TextServiceEvent_, uppTextServiceEvent }, + { kCMGetTextServiceMenu, (ProcPtr)GetTextServiceMenu_, uppGetTextServiceMenu }, + { kCMFixTextService, (ProcPtr)FixTextService_, uppFixTextService }, + { kCMHidePaletteWindows, (ProcPtr)HidePaletteWindows_, uppHidePaletteWindows }, + { kCMCopyTextServiceInputModeList, (ProcPtr)CopyTextServiceInputModeList_, uppCopyTextServiceInputModeList }, + { kCMSetTextServiceProperty, (ProcPtr)SetTextServiceProperty_, uppSetTextServiceProperty }, + { 0, 0, 0 } +}; + +// ====================================================================== +// ã¨ã³ããªãã¤ã³ã +// ====================================================================== +extern "C" +pascal ComponentResult SKKEntryPoint(ComponentParameters* params, Handle) { + for(callback* func = table; func->addr != 0; ++ func) { + if(params->what == func->selector) { + return Invoke(func->addr, func->info)(params); + } + } + + return badComponentSelector; +} Index: AquaSKK/src/component/SKKSession.cpp diff -u /dev/null AquaSKK/src/component/SKKSession.cpp:1.1.2.1 --- /dev/null Sun Aug 19 19:00:32 2007 +++ AquaSKK/src/component/SKKSession.cpp Sun Aug 19 19:00:32 2007 @@ -0,0 +1,420 @@ +/* -*- C++ -*- + $Id: SKKSession.cpp,v 1.1.2.1 2007/08/19 10:00:32 t-suwa Exp $ + + MacOS X implementation of the SKK input method. + + Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ClientConfiguration.h" + +#include "BIM.h" +#include "SKKComponent.h" +#include "SKKSession.h" +#include "SKKConfig.h" + +SKKSession::SKKSession(const ComponentInstance instance) : instance_(instance) { +} + +// ã¤ãã³ã +bool SKKSession::HandleInput(const EventRef event) { + // ã¬ã¬ã·ã¼ã¨ã³ã¸ã³ + SKKEvent legacy_event(event); + + // å¦çãã¹ãã¤ãã³ãã§ã¯ãªãï¼ + if(!legacy_event) { + return false; + } + + // å¦çãã¹ããã¼ã§ã¯ãªãï¼ + if(legacy_event.Modifier() & cmdKey) { + return false; + } + + // å¦çãã¹ããã¼ã§ã¯ãªãï¼ + if((legacy_event.Modifier() & controlKey) && !SKKConfig::IsMappedKey(legacy_event)) { + return false; + } + + bool handled = legacyInput(legacy_event); + + //ãããã¡ã®å¤ã0ãªãå¼·å¶çã«ããã¼ãã£ã³ã°ã¦ã£ã³ãã¦ãéãã + if(bufsize_.curr == 0) { + hideFloatingWindow(); + } + + return handled; +} + +// å ¥åã¢ã¼ãå¤æ´ +void SKKSession::SelectInputMode(SKK::InputMode mode) { + // å ¥åã¢ã¼ããå¤æ´ãã + switch(mode) { + case SKK::Hirakana: + if(!legacy_.isHiraganaInputMode()) { + legacy_.goHiraganaInputMode(); + } + break; + + case SKK::Katakana: + if(!legacy_.isZenKataInputMode()) { + legacy_.goZenKataInputMode(); + } + break; + + case SKK::Jisx0201Kana: + if(!legacy_.isHanKataInputMode()) { + legacy_.goHanKataInputMode(); + } + break; + + case SKK::Jisx0208Latin: + if(!legacy_.isZenAscInputMode()) { + legacy_.goZenAscInputMode(); + } + break; + + case SKK::Ascii: + if(!legacy_.isHanAscInputMode()) { + legacy_.goHanAscInputMode(); + } + break; + } +} + +Point SKKSession::GetInputPosition(long offset) const { + EventRef event = 0; + + // ã¤ãã³ããä½æãã + OSStatus status = CreateEvent(0, kEventClassTextInput, kEventTextInputOffsetToPos, 0, + kEventAttributeUserEvent, &event); + + // ã³ã³ãã¼ãã³ãã¤ã³ã¹ã¿ã³ã¹ + if(status == noErr) { + status = SetEventParameter(event, kEventParamTextInputSendComponentInstance, typeComponentInstance, + sizeof(ComponentInstance), &instance_); + } + + // ãªãã¡ã¬ã³ã¹ã«ã¦ã³ã¿ + if(status == noErr) { + long refcon = 1; + status = SetEventParameter(event, kEventParamTextInputSendRefCon, typeLongInteger, + sizeof(long), &refcon); + } + + // ããã¹ãä½ç½® + if(status == noErr) { + status = SetEventParameter(event, kEventParamTextInputSendTextOffset, typeLongInteger, + sizeof(long), &offset); + } + + // éä¿¡ + if(status == noErr) { + status = SendTextInputEvent(event); + } + + // ä½ç½®ã® QD ã°ãã¼ãã«åº§æ¨ãåå¾ + Point pt; + if(status == noErr) { + status = GetEventParameter(event, kEventParamTextInputReplyPoint, typeQDPoint, 0, + sizeof(Point), 0, &pt); + } + + if(event) { + ReleaseEvent(event); + } + + // 座æ¨ã®èª¿æ´ + CGRect mainscreen = CGDisplayBounds(CGMainDisplayID()); + pt.v = mainscreen.size.height - pt.v; + + return pt; +} + +void SKKSession::DisplayString(const CFStringRef str, int fixlen, int caretpos) { + updateActiveInputArea(str, sizeof(UniChar) * fixlen, sizeof(UniChar) * caretpos); +} + +void SKKSession::FixString(const CFStringRef str) { + long fixlen = CFStringGetLength(str); + + updateActiveInputArea(str, sizeof(UniChar) * fixlen, sizeof(UniChar) * fixlen); + + bufsize_.curr = bufsize_.prev = 0; +} + +void SKKSession::Terminate() { + bufsize_.curr = bufsize_.prev = 0; +} + +IMSessionInputMode& SKKSession::LegacyEngine() { + return legacy_; +} + +// ====================================================================== +// private method +// ====================================================================== + +void SKKSession::updateActiveInputArea(const CFStringRef str, int UniChar_fixlen, int UniChar_caretpos) { + EventRef event = 0; + + bufsize_.curr = CFStringGetLength(str); + + // ã¤ãã³ããä½æ + OSErr error = CreateEvent(0, kEventClassTextInput, kEventTextInputUpdateActiveInputArea, 0, + kEventAttributeUserEvent, &event); + + // ã³ã³ãã¼ãã³ãã¤ã³ã¹ã¿ã³ã¹ + if(error == noErr) { + error = SetEventParameter(event, kEventParamTextInputSendComponentInstance, typeComponentInstance, + sizeof(ComponentInstance), &instance_); + } + + + // ãªãã¡ã³ã¬ã³ã¹ã«ã¦ã³ã¿ + if(error == noErr) { + long refcon = 1; + error = SetEventParameter(event, kEventParamTextInputSendRefCon, typeLongInteger, + sizeof(long), &refcon); + } + + // äºã¤ç®ã®ãã©ã¡ã¿ã¯è¨èªæ å ± + if(error == noErr) { + ScriptLanguageRecord scriptLanguageRecord; + scriptLanguageRecord.fScript = smJapanese; + scriptLanguageRecord.fLanguage = langJapanese; + + error = SetEventParameter(event, kEventParamTextInputSendSLRec, typeIntlWritingCode, + sizeof(ScriptLanguageRecord), &scriptLanguageRecord); + } + + // 確å®ããæåæ°ã®è¨å® + if(error == noErr) { + error = SetEventParameter(event, kEventParamTextInputSendFixLen, typeLongInteger, + sizeof(long), &UniChar_fixlen); + } + + + // æ´æ°ããå 容ï¼UCS-32ã®é åï¼ + if(error == noErr) { + UniChar* buf = new UniChar[bufsize_.curr]; + + CFStringGetCharacters(str, CFRangeMake(0, bufsize_.curr), buf); + + error = SetEventParameter(event, kEventParamTextInputSendText, typeUnicodeText, + sizeof(UniChar) * bufsize_.curr, buf); + + delete[] buf; + } + + // ããã¹ããå¤æ´ããã¦ããªããã°ç©ºã®æ´æ°é åã渡ãããããªãã°å ¨ã¦ã®é åãæ´æ°ãããã + if(error == noErr) { + TextRangeArray* update = (TextRangeArrayPtr)NewPtrClear(sizeof(short) + sizeof(TextRange) * 2); + + update->fNumOfRanges = 2; + + // ååã®ãããã¡ + update->fRange[0].fStart = 0; + update->fRange[0].fEnd = bufsize_.prev; + update->fRange[0].fHiliteStyle = 0; + + // ä»åã®ãããã¡ + update->fRange[1].fStart = 0; + update->fRange[1].fEnd = sizeof(UniChar) * bufsize_.curr - UniChar_fixlen; + update->fRange[1].fHiliteStyle = 0; + + // ãããã¡ãµã¤ãºãããã¯ã¢ãã + bufsize_.prev = update->fRange[1].fEnd; + + if(error == noErr) { + error = SetEventParameter(event, kEventParamTextInputSendUpdateRng, typeTextRangeArray, + sizeof(short) + sizeof(TextRange) * 2, update); + } + + DisposePtr((Ptr)update); + } + + // ãã¤ã©ã¤ãã®ç¯å²ã¨ãã£ã¬ããã®ä½ç½® + if(error == noErr) { + TextRangeArray* highlight = 0; + + if(UniChar_fixlen == 0) { + highlight = (TextRangeArrayPtr)NewPtrClear(sizeof(short) + sizeof(TextRange) * 2); + + highlight->fNumOfRanges = 2; + + highlight->fRange[0].fStart = 0; + highlight->fRange[0].fEnd = sizeof(UniChar) * bufsize_.curr - UniChar_fixlen; + highlight->fRange[1].fStart = UniChar_caretpos; + highlight->fRange[1].fEnd = UniChar_caretpos; + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 + highlight->fRange[0].fHiliteStyle = kTSMHiliteRawText; + highlight->fRange[1].fHiliteStyle = kTSMHiliteCaretPosition; +#else + highlight->fRange[0].fHiliteStyle = kRawText; + highlight->fRange[1].fHiliteStyle = kCaretPosition; +#endif + + error = SetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray, + sizeof(short) + sizeof(TextRange) * 2, highlight); + } else { + highlight = (TextRangeArrayPtr)NewPtrClear(sizeof(short) + sizeof(TextRange) * 1); + + highlight->fNumOfRanges = 1; + + highlight->fRange[0].fStart = UniChar_caretpos; + highlight->fRange[0].fEnd = UniChar_caretpos; + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 + highlight->fRange[0].fHiliteStyle = kTSMHiliteCaretPosition; +#else + highlight->fRange[0].fHiliteStyle = kCaretPosition; +#endif + + error = SetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray, + sizeof(short) + sizeof(TextRange) * 1, highlight); + } + + DisposePtr((Ptr)highlight); + } + + // å ¨ä½ã®å¹ + if(error == noErr) { + TextRange range; + + range.fStart = 0; + range.fEnd = sizeof(UniChar) * bufsize_.curr - UniChar_fixlen; + + error = SetEventParameter(event, kEventParamTextInputSendPinRng, typeTextRange, + sizeof(TextRange), &range); + } + + // éä¿¡ + if(error == noErr) { + error = SendTextInputEvent(event); + ReleaseEvent(event); + } +} + +// æåã®å ¥åã«å¯¾ãã¦ã®å¦çã +bool SKKSession::legacyInput(const SKKEvent& event) { + switch(event.KeyCode()) { + case 0x41: // . + case 0x43: // * + case 0x45: // + + case 0x4b: // / + case 0x4e: // - + case 0x51: // = + case 0x52: // 0 + case 0x53: // 1 + case 0x54: // 2 + case 0x55: // 3 + case 0x56: // 4 + case 0x57: // 5 + case 0x58: // 6 + case 0x59: // 7 + case 0x5b: // 8 + case 0x5c: // 9 + case 0x5f: // , + if(ClientConfiguration::theInstance().isNumericKeypad_HalfWidth()) { + return legacy_.handleNumKey(event.CharCode()); + } else { + return legacy_.handleInput(event); + } + break; + + case 0x66: // è±æ° + if(SKKConfig::UseEisuuToSetHenkanPoint()) { + return legacy_.handleInput(SKKConfig::SetHenkanPointKey()); + } else { + return true; + } + break; + + case 0x68: // ã㪠+ if(SKKConfig::UseKanaToSetHenkanPoint()) { + return legacy_.handleInput(SKKConfig::SetHenkanPointKey()); + } else { + return legacy_.handleInput(SKKConfig::KanaModeKey()); + } + } + + switch(event.CharCode()) { + case kNullCharCode: + return true; + + case kBackspaceCharCode: + return legacy_.handleBackSpace(); + + case kTabCharCode: + return legacy_.handleTab(); + + case kEnterCharCode: + case kReturnCharCode: + return legacy_.handleReturn(); + + case kLeftArrowCharCode: + case kRightArrowCharCode: + case kUpArrowCharCode: + case kDownArrowCharCode: + return legacy_.handleArrow(event); + + default: + if(event == SKKConfig::CancelKey()) { + return legacy_.handleCg(); + } + if(event == SKKConfig::PasteKey()) { + return legacy_.handleCy(); + } + if((0x20 <= event && event <= 0x7e) || SKKConfig::IsMappedKey(event)) { + return legacy_.handleInput(event); + } + } + + return false; +} + +void SKKSession::hideFloatingWindow() const { + EventRef event = 0; + + // kEventClassTextInput/kEventTextInputShowHideBottomWindowã®Carbonã¤ãã³ããä½æ + OSErr error = CreateEvent(0, kEventClassTextInput, kEventTextInputShowHideBottomWindow, 0, + kEventAttributeUserEvent, &event); + + if(error == noErr) { + error = SetEventParameter(event, kEventParamTextInputSendComponentInstance, typeComponentInstance, + sizeof(ComponentInstance), &instance_); + } + + if(error == noErr) { + ScriptLanguageRecord slr = { smJapanese, langJapanese }; + error = SetEventParameter(event, kEventParamTextInputSendSLRec, typeIntlWritingCode, + sizeof(ScriptLanguageRecord), &slr); + } + + if(error == noErr) { + Boolean showBottomWindow = false; + error = SetEventParameter(event, kEventParamTextInputSendShowHide, typeBoolean, + sizeof(Boolean), &showBottomWindow); + } + + if(error == noErr) { + error = SendTextInputEvent(event); + ReleaseEvent(event); + } +} Index: AquaSKK/src/component/SKKSession.h diff -u /dev/null AquaSKK/src/component/SKKSession.h:1.1.2.1 --- /dev/null Sun Aug 19 19:00:32 2007 +++ AquaSKK/src/component/SKKSession.h Sun Aug 19 19:00:32 2007 @@ -0,0 +1,68 @@ +/* -*- C++ -*- + $Id: SKKSession.h,v 1.1.2.1 2007/08/19 10:00:32 t-suwa Exp $ + + MacOS X implementation of the SKK input method. + + Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef INC__SKKSession__ +#define INC__SKKSession__ + +#include <Carbon/Carbon.h> + +#include "SKK.h" +#include "SKKEvent.h" +#include "IMSessionInputMode.h" + +class SKKSession { + ComponentInstance instance_; + IMSessionInputMode legacy_; + + struct buffer_size { + long prev; + long curr; + buffer_size() : prev(0), curr(0) {} + }; + + buffer_size bufsize_; + + void updateActiveInputArea(const CFStringRef str, int fixlen, int caretpos); + bool legacyInput(const SKKEvent& event); + void hideFloatingWindow() const; + +public: + SKKSession(const ComponentInstance instance); + + // ã¤ãã³ããã³ããªã³ã° + bool HandleInput(const EventRef event); + + // å ¥åã¢ã¼ãå¤æ´ + void SelectInputMode(SKK::InputMode mode); + + // å ¥åä½ç½®åº§æ¨åå¾ + Point GetInputPosition(long offset = 0) const; + + // 表示æ´æ° + void DisplayString(const CFStringRef str, int fixlen, int caretpos = -1); + void FixString(const CFStringRef str); + void Terminate(); + + IMSessionInputMode& LegacyEngine(); +}; + +#endif Index: AquaSKK/src/component/WordRegisterMode.cpp diff -u /dev/null AquaSKK/src/component/WordRegisterMode.cpp:1.1.2.1 --- /dev/null Sun Aug 19 19:00:32 2007 +++ AquaSKK/src/component/WordRegisterMode.cpp Sun Aug 19 19:00:32 2007 @@ -0,0 +1,236 @@ +/* + $Id: WordRegisterMode.cpp,v 1.1.2.1 2007/08/19 10:00:32 t-suwa Exp $ + + MacOS X implementation of the SKK input method. + + Copyright (C) 2002 phonohawk + Copyright (C) 2006-2007 Tomotaka SUWA <t.suw****@mac*****> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "BIM.h" +#include "CppCFData.h" +#include "ParentInputMode.h" +#include "IMSessionInputMode.h" +#include "WordRegisterMode.h" + +#include "SKKComponent.h" +#include "SKKSession.h" + +WordRegisterMode::WordRegisterMode(ChildInputMode& src, const CppCFString& word) + : ParentInputMode(), owner(&src), caret(0) { + // [o^:word] + title.append('[').append(0x767b).append(0x9332).append(':').append(word).append(']'); + + imsession_input_mode = &SKKComponent::theInstance().Session().LegacyEngine(); +} + +bool WordRegisterMode::handleBackSpace() { + if(getReallyCurrentInputMode().handleBackSpace()) { + // really current input modeªtrueðÔµ½ç½à¹¸ÉtrueðÔ·B + redisplay(); + return true; + } + + ChildInputMode& input_mode = getReallyCurrentInputMode(); + + if(!input_mode.handleBackSpace()) { + // LbgÌÊuæèOɶª êÎê¶íB³¯êγB + if(caret > 0) { + buffer.eraseCharAt(caret-1); + caret--; + } + } + //redisplay(); + display(CppCFString()); + return true; // Ç¿çÉÅà{¶ÍÁ³¹È¢B +} + +bool WordRegisterMode::handleReturn() { + ChildInputMode& input_mode = getReallyCurrentInputMode(); + + if(!input_mode.handleReturn()) { + fix(input_mode.getStringToFix()); + + if(buffer.length() > 0) { + (dynamic_cast<RegistrationStarter*>(owner))->wordRegistrationFinished(); // Pêo^I¹B + } else { + (dynamic_cast<RegistrationStarter*>(owner))->wordRegistrationCanceled(); // Pêo^fB + } + } + return true; +} + +bool WordRegisterMode::handleArrow(SKKChar skkchar) { + if(getReallyCurrentInputMode().handleArrow(skkchar)) { + return true; + } + + switch(skkchar) { + case kLeftArrowCharCode: // ¶ + if(caret > 0) { + -- caret; + } + break; + case kRightArrowCharCode: // E + if(caret < buffer.length()) { + ++ caret; + } + break; + case kUpArrowCharCode: // æª + caret = 0; + break; + case kDownArrowCharCode: // ö + caret = buffer.length(); + break; + } + + display(CppCFString()); + + return true; +} + +bool WordRegisterMode::handleCg() { + if(getReallyCurrentInputMode().handleCg()) { + // really current input modeªtrueðÔµ½ç½à¹¸ÉtrueðÔ·B + redisplay(); + return true; + } + + getReallyCurrentInputMode().terminate(); + + // bufferðóÉ·éB + buffer.clear(); + caret = 0; + (dynamic_cast<RegistrationStarter*>(owner))->wordRegistrationCanceled(); // Pêo^fB + return true; +} + +bool WordRegisterMode::handleCy() { + if(getReallyCurrentInputMode().handleCy()) { + // really current input modeªtrueðÔµ½ç½à¹¸ÉtrueðÔ·B + return true; + } + + PasteboardRef pasteboard; + + PasteboardCreate(kPasteboardClipboard, &pasteboard); + PasteboardSynchronize(pasteboard); + + ItemCount items; + PasteboardGetItemCount(pasteboard, &items); + for(UInt32 pos = 0; pos < items; ++ pos) { + PasteboardItemID id; + // index Í 1 based + if(PasteboardGetItemIdentifier(pasteboard, pos + 1, &id) < 0) continue; + + CFDataRef data; + CppCFString str; + if(PasteboardCopyItemFlavorData(pasteboard, id, CFSTR("public.utf8-plain-text"), &data) == 0) { + CFStringRef tmp = CFStringCreateWithBytes(NULL, CFDataGetBytePtr(data), CFDataGetLength(data), + kCFStringEncodingUTF8, false); + str = CppCFString(tmp); + CFRelease(tmp); + } else { + if(PasteboardCopyItemFlavorData(pasteboard, id, CFSTR("com.apple.traditional-mac-plain-text"), &data) < 0) { + continue; + } + CFStringRef tmp = CFStringCreateWithBytes(NULL, CFDataGetBytePtr(data), CFDataGetLength(data), + CFStringGetSystemEncoding(), false); + str = CppCFString(tmp); + CFRelease(tmp); + } + CFRelease(data); + + buffer.insert(caret, str); + caret += str.length(); + display(CppCFString()); + + break; + } + CFRelease(pasteboard); + + return true; +} + +bool WordRegisterMode::handleTab() { + ParentInputMode::handleTab(); + return true; // íÉH¤B +} + +bool WordRegisterMode::handleInput(SKKChar skkchar) { + ChildInputMode* input_mode; + if(is_kanji_mode) { + input_mode = &kanji_conversion_mode; + } else if(is_ascii_conv_mode) { + input_mode = &ascii_conversion_mode; + } else { + if(skkchar >= 'A' && skkchar <= 'Z' && skkchar != 'L' && //XXX + !isHanAscInputMode() && !isZenAscInputMode()) { + is_kanji_mode = true; + input_mode = &kanji_conversion_mode; + } else { + input_mode = current_input_mode; + } + } + + bool do_fix = input_mode->handleInput(skkchar); + if(do_fix) { + fixUnlessIgnore(input_mode->getStringToFix()); + } + displayUnlessIgnore(input_mode->getStringToDisplay()); + + return true; +} + +CppCFString WordRegisterMode::getContent() const { + return buffer; +} + +void WordRegisterMode::redisplay() { + ChildInputMode& input_mode = getReallyCurrentInputMode(); + + CppCFString str_to_display = input_mode.getStringToDisplay(); + if(str_to_display.length() == 0 || + (str_to_display.length() > 0 && str_to_display[0] != kIgnoreThis)) // kIgnoreThisÈçXVµÈ¢B + { + display(str_to_display); + } +} + +void WordRegisterMode::fix(const CppCFString& str_to_fix) { + if(str_to_fix.length() > 0 && str_to_fix[0] == kIgnoreThis) return; + + // obt@ÌLbgÌÊuÉ}ü·éB + buffer.insert(caret,str_to_fix); + + // Lbgð}üµ½¶ªAEÉÚ®·éB + caret += str_to_fix.length(); + + imsession_input_mode->display(CppCFString(title).append('[') + .append(buffer.substring(0, caret)).append(kCaret) + .append(buffer.substring(caret)).append(']')); +} + +void WordRegisterMode::display(const CppCFString& str_to_display) { + if(str_to_display.length() > 0 && str_to_display[0] == kIgnoreThis) return; + + // \¦áF + // [¯*·][Á] + imsession_input_mode->display(CppCFString(title).append('[') + .append(buffer.substring(0, caret)).append(str_to_display).append(kCaret) + .append(buffer.substring(caret)).append(']')); +} Index: AquaSKK/src/component/WordRegisterMode.h diff -u /dev/null AquaSKK/src/component/WordRegisterMode.h:1.1.2.1 --- /dev/null Sun Aug 19 19:00:32 2007 +++ AquaSKK/src/component/WordRegisterMode.h Sun Aug 19 19:00:32 2007 @@ -0,0 +1,61 @@ +/* + $Id: WordRegisterMode.h,v 1.1.2.1 2007/08/19 10:00:32 t-suwa Exp $ + + MacOS X implementation of the SKK input method. + + Copyright (C) 2002 phonohawk + Copyright (C) 2006-2007 Tomotaka SUWA <t.suw****@mac*****> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef INC__WordRegisterMode__ +#define INC__WordRegisterMode__ + +#include "ParentInputMode.h" + +class IMSessionInputMode; +class ChildInputMode; +class CppCFString; + +class WordRegisterMode: public ParentInputMode { +protected: + class ChildInputMode* owner; + CppCFString title; + CppCFString buffer; + unsigned caret; + + IMSessionInputMode* imsession_input_mode; + +public: + // titleÌáFuÉ°*évAuÍ°v + // ownerÍRegistrationStarteràp³µÄ¢È¯êÎÈçÈ¢B + WordRegisterMode(class ChildInputMode& owner, const CppCFString& word); + virtual ~WordRegisterMode() {} + + virtual bool handleReturn(); + virtual bool handleBackSpace(); + virtual bool handleArrow(SKKChar skkchar); + virtual bool handleCg(); + virtual bool handleCy(); + virtual bool handleTab(); + virtual bool handleInput(SKKChar skkchar); + virtual void fix(const CppCFString& str_to_fix); + virtual void display(const CppCFString& str_to_display); + virtual void redisplay(); + virtual CppCFString getContent() const; +}; + +#endif // INC__WordRegisterMode__