[aquaskk-changes 113] CVS update: AquaSKK

Back to archive index

Tomotaka SUWA t-suw****@users*****
2006年 1月 8日 (日) 16:15:31 JST


Index: AquaSKK/BIM.cpp
diff -u AquaSKK/BIM.cpp:1.11.2.1 AquaSKK/BIM.cpp:1.11.2.2
--- AquaSKK/BIM.cpp:1.11.2.1	Sat Jan  7 16:22:28 2006
+++ AquaSKK/BIM.cpp	Sun Jan  8 16:15:30 2006
@@ -1,5 +1,5 @@
 /*
-  $Id: BIM.cpp,v 1.11.2.1 2006/01/07 07:22:28 t-suwa Exp $
+  $Id: BIM.cpp,v 1.11.2.2 2006/01/08 07:15:30 t-suwa Exp $
 
   MacOS X implementation of the SKK input method.
 
@@ -23,8 +23,6 @@
 
 #define TARGET_API_MAC_CARBON 1
 
-#define kMENU_Pencil (kBaseResourceID + 1)
-
 #include <Carbon/Carbon.h>
 #include <vector>
 #include <map>
@@ -33,7 +31,6 @@
 #include "BIM.h"
 #include "BIMInputEvents.h"
 #include "BIMClientServer.h"
-#include "BIMScript.h"
 #include "CppCFString.h"
 #include "CppCFData.h"
 #include "InputMode.h"
Index: AquaSKK/BIM.r
diff -u AquaSKK/BIM.r:1.3 AquaSKK/BIM.r:1.3.4.1
--- AquaSKK/BIM.r:1.3	Tue Sep  6 10:25:12 2005
+++ AquaSKK/BIM.r	Sun Jan  8 16:15:30 2006
@@ -1,105 +1,111 @@
 /*
-	$Id: BIM.r,v 1.3 2005/09/06 01:25:12 t-suwa Exp $
-	---------
-	
-    MacOS X implementation of the SKK input method.
-    Copyright (C) 2002 phonohawk
-
-    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
+  $Id: BIM.r,v 1.3.4.1 2006/01/08 07:15:30 t-suwa Exp $
+
+  MacOS X implementation of the SKK input method.
+
+  Copyright (C) 2002 phonohawk
+  Copyright (C) 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
 */
-#define UseExtendedThingResource 1
 
-#include <Carbon/Carbon.r>
-#include "BIMScript.h"
+#define thng_RezTemplateVersion 1
 
-data 'cbnm' (0) {
-	// "org.ccm-software.AquaSKKInputMethod" ‚Ì pascal •¶Žš—ñ
-	$"236f 7267 2e63 636d 2d73 6f66 7477 6172"
-	$"652e 4171 7561 534b 4b49 6e70 7574 4d65"
-	$"7468 6f64"
-};
+#include <Carbon/Carbon.r>
 
-resource 'thng' (128)
-{
-    'tsvc', // ƒRƒ“ƒ|[ƒlƒ“ƒgƒ^ƒCƒvBTextService‚È‚Ì‚Å'tsvc'
-    'inpm',	// ƒRƒ“ƒ|[ƒlƒ“ƒgƒTƒuƒ^ƒCƒvBInputMethod‚È‚Ì‚Å'inpm'
-    'askk',	// ƒ†ƒj[ƒN‚ȃxƒ“ƒ_[ƒR[ƒhB
-    0x8000 + kBIMScript * 0x100 + kBIMLanguage, // Œ¾ŒêÝ’è
-    kAnyComponentFlagsMask, // kAnyComponentFlagsMask‚Å‚È‚¯‚ê‚΂Ȃç‚È‚¢B
-    'dlle', kBaseResourceID, // ƒGƒ“ƒgƒŠƒ|ƒCƒ“ƒg‚Ì–¼Ì
-    'STR ', kBaseResourceID, // IM‚Ì–¼Ì
-    'STR ', kBaseResourceID, // IM‚Ì–¼Ìi‚Ç‚¿‚炪‚ǂ̂悤‚ÉŽg‚í‚ê‚é‚©‚Í’m‚ç‚È‚¢j
-    'ICON', kBaseResourceID,
-    0x00010000,
-    componentHasMultiplePlatforms,
-    15872 + kBIMScript * 0x200,
-    {
-        0x8000 + kBIMScript * 0x100 + kBIMLanguage, // Œ¾ŒêÝ’è
-        'dlle', kBaseResourceID, 1000
-    }
-};
+#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    1
+  #define Target_PlatformType		platformPowerPCNativeEntryPoint
+  #define Target_SecondPlatformType	platformIA32NativeEntryPoint
+#elif TARGET_REZ_MAC_X86
+  #define Target_PlatformType		platformIA32NativeEntryPoint
+#else
+  #define Target_PlatformType		platformPowerPCNativeEntryPoint
+#endif
 
-resource 'dlle' (kBaseResourceID) {
-	"BIMComponentDispatch"
-};
+#define	kAquaSKKBaseResouceID	16384
+#define kAquaSKKComponentFlags	0x8000 + smJapanese * 0x100 + langJapanese
 
-resource 'MENU' (kBaseResourceID + 1)
-{
-    kBaseResourceID,
-    textMenuProc,
-    allEnabled,
-    enabled,
-    "00000",
-    {
-        "Show Keyboard Palette", noIcon, "K", noMark, plain,
-        "Show Send Event Palette", noIcon, "D", noMark, plain,
-        "-", noIcon, noKey, noMark, plain,
-        "Convert To Lowercase", noIcon, "L", noMark, plain,
-        "Convert To Uppercase", noIcon, "U", noMark, plain
-    }
+// "org.ccm-software.AquaSKKInputMethod" ‚Ì pascal •¶Žš—ñ
+data 'cbnm' (0) {
+    $"236f 7267 2e63 636d 2d73 6f66 7477 6172"
+    $"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
+    0,				// icon type
+    0,				// icon ID
+    0x00010000,			// version
+    componentHasMultiplePlatforms, // registration flags
+    0,				// resource ID of icon family
+    {				// component platform information
+	kAquaSKKComponentFlags,
+	'dlle',
+	kAquaSKKBaseResouceID,
+	Target_PlatformType,
+#if TARGET_REZ_UNIVERSAL_COMPONENTS
+	kAquaSKKComponentFlags,
+	'dlle',
+	kAquaSKKBaseResouceID,
+	Target_SecondPlatformType
+#endif
+    };
 };
 
-resource 'xmnu' (kBaseResourceID + 1)
-{
-    versionZero
-    {
-        {
-            dataItem {'SHKP', kMenuShiftModifier + kMenuControlModifier + kMenuNoCommandModifier,
-                      currScript, 0, 0, noHierID, sysFont, naturalGlyph},
-            dataItem {'SHDP', kMenuShiftModifier + kMenuControlModifier + kMenuNoCommandModifier,
-                      currScript, 0, 0, noHierID, sysFont, naturalGlyph},
-            skipItem {},
-            dataItem {'CLOW', kMenuShiftModifier + kMenuControlModifier + kMenuNoCommandModifier,
-                      currScript, 0, 0, noHierID, sysFont, naturalGlyph},
-            dataItem {'CUPP', kMenuShiftModifier + kMenuControlModifier + kMenuNoCommandModifier,
-                      currScript, 0, 0, noHierID, sysFont, naturalGlyph}
-        }
-    }
+resource 'dlle' (kAquaSKKBaseResouceID) {
+    "BIMComponentDispatch"
 };
 
-resource 'STR ' (kBaseResourceID)
-{
+resource 'STR ' (kAquaSKKBaseResouceID) {
     "AquaSKK"
 };
 
-resource 'STR#' (kBaseResourceID + 1)
-{
-    {
-	"Show Keyboard Palette",
-        "Hide Keyboard Palette",
-	"Show Send Event Palette",
-        "Hide Send Event Palette"
-    }
+resource 'STR ' (kAquaSKKBaseResouceID + 1) {
+    "AquaSKK Input Method for Mac OS X"
 };
Index: AquaSKK/BIMComponent.cpp
diff -u AquaSKK/BIMComponent.cpp:1.4.2.1 AquaSKK/BIMComponent.cpp:1.4.2.2
--- AquaSKK/BIMComponent.cpp:1.4.2.1	Sat Jan  7 16:22:28 2006
+++ AquaSKK/BIMComponent.cpp	Sun Jan  8 16:15:30 2006
@@ -1,23 +1,24 @@
 /*
-	$Id: BIMComponent.cpp,v 1.4.2.1 2006/01/07 07:22:28 t-suwa Exp $
-	---------
-	
-    MacOS X implementation of the SKK input method.
-    Copyright (C) 2002 phonohawk
+  $Id: BIMComponent.cpp,v 1.4.2.2 2006/01/08 07:15:30 t-suwa Exp $
+
+  MacOS X implementation of the SKK input method.
 
-    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
+  Copyright (C) 2002 phonohawk
+  Copyright (C) 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
 */
 #define TARGET_API_MAC_CARBON 1
 
@@ -26,7 +27,6 @@
 #include "BIM.h"
 #include "BIMClientServer.h"
 #include "BIMComponent.h"
-#include "BIMScript.h"
 #include "CppCFString.h"
 #include "CppCFData.h"
 #include "InputMode.h"
@@ -43,116 +43,84 @@
 #include "ParentInputMode.h"
 #include "IMSessionInputMode.h"
 
-extern "C" pascal ComponentResult BIMComponentDispatch( ComponentParameters *inParams, Handle inSessionHandle );
+extern "C" pascal ComponentResult BIMComponentDispatch(ComponentParameters* inParams, Handle inSessionHandle);
 
 static long		gInstanceRefCount = 0;
 static MenuRef		gTextServiceMenu = NULL;
 
-static ComponentResult CallBIMFunction( ComponentParameters *inParams, ProcPtr inProcPtr,
-                                        SInt32 inProcInfo );
-static ComponentResult CallBIMFunctionWithStorage( Handle inStorage,
-                                                   ComponentParameters *inParams,
-                                                   ProcPtr inProcPtr, SInt32 inProcInfo );
+static ComponentResult CallBIMFunction(ComponentParameters* inParams, ProcPtr inProcPtr, SInt32 inProcInfo);
+static ComponentResult CallBIMFunctionWithStorage(Handle inStorage, ComponentParameters* inParams, ProcPtr inProcPtr,
+						  SInt32 inProcInfo);
 
 // ƒRƒ“ƒ|[ƒlƒ“ƒg‚̃Gƒ“ƒgƒŠƒ|ƒCƒ“ƒgBextern "C"‚·‚ׂ«‚©‚Ç‚¤‚©‚Í’è‚©‚Å‚È‚¢‚ªAˆê‰ž‚»‚¤‚µ‚Ä‚¨‚­B
-extern "C" pascal ComponentResult BIMComponentDispatch( ComponentParameters *inParams, Handle inSessionHandle)
-{
+extern "C" pascal ComponentResult BIMComponentDispatch(ComponentParameters* inParams, Handle inSessionHandle) {
     ComponentResult result;
 
     result = noErr;
 
-    switch (inParams->what)
-	{
-		// Component Manager‚©‚ç‚ÌŽw—ß
-        case kComponentOpenSelect:
-            result = CallBIMFunction( inParams, (ProcPtr) BIMOpenComponent,
-                                      uppOpenComponentProcInfo );
-            break;
-
-        case kComponentCloseSelect:
-            result = CallBIMFunctionWithStorage( inSessionHandle, inParams,
-                                                 (ProcPtr) BIMCloseComponent,
-                                                 uppCloseComponentProcInfo );
-            break;
-
-        case kComponentCanDoSelect:            
-            result = CallBIMFunction( inParams, (ProcPtr) BIMCanDo, uppCanDoProcInfo );
-            break;
-
-        case kComponentVersionSelect:
-            result = CallBIMFunction( inParams, (ProcPtr) BIMGetVersion, uppGetVersionProcInfo );
-            break;
-		
-		// TSM‚©‚ç‚ÌŽw—ß
-        case kCMGetScriptLangSupport:
-            result = CallBIMFunctionWithStorage( inSessionHandle, inParams,
-                                                 (ProcPtr) BIMGetScriptLangSupport,
-                                                 uppGetScriptLangSupportProcInfo );
-            break;
-
-        case kCMInitiateTextService:
-            result = CallBIMFunctionWithStorage( inSessionHandle, inParams,
-                                                 (ProcPtr) BIMInitiateTextService,
-                                                 uppInitiateTextServiceProcInfo );
-            break;
-
-        case kCMTerminateTextService:
-            result = CallBIMFunctionWithStorage( inSessionHandle, inParams,
-                                                 (ProcPtr) BIMTerminateTextService,
-                                                 uppTerminateTextServiceProcInfo );
-            break;
-
-        case kCMActivateTextService:
-            result = CallBIMFunctionWithStorage( inSessionHandle, inParams,
-                                                 (ProcPtr) BIMActivateTextService,
-                                                 uppActivateTextServiceProcInfo );
-            break;
-
-        case kCMDeactivateTextService:
-            result = CallBIMFunctionWithStorage( inSessionHandle, inParams,
-                                                 (ProcPtr) BIMDeactivateTextService,
-                                                 uppDeactivateTextServiceProcInfo );
-            break;
-
-        case kCMTextServiceEvent:
-            result = CallBIMFunctionWithStorage( inSessionHandle, inParams,
-                                                 (ProcPtr) BIMTextServiceEventRef,
-                                                 uppTextServiceEventRefProcInfo );
-            break;
-
-        case kCMGetTextServiceMenu:
-            result = CallBIMFunctionWithStorage( inSessionHandle, inParams,
-                                                 (ProcPtr) BIMGetTextServiceMenu,
-                                                 uppGetTextServiceMenuProcInfo );
-            break;
-
-        case kCMFixTextService:
-            result = CallBIMFunctionWithStorage( inSessionHandle, inParams,
-                                                 (ProcPtr) BIMFixTextService,
-                                                 uppFixTextServiceProcInfo );
-            break;
-
-        case kCMHidePaletteWindows:
-            result = CallBIMFunctionWithStorage( inSessionHandle, inParams,
-                                                 (ProcPtr) BIMHidePaletteWindows,
-                                                 uppHidePaletteWindowsProcInfo );
-            break;
-
-	case kCMCopyTextServiceInputModeList:
-            result = CallBIMFunctionWithStorage( inSessionHandle, inParams,
-                                                 (ProcPtr) BIMCopyTextServiceInputModeList,
-                                                 uppCopyTextServiceInputModeListInfo );
-	    break;
-
-	case kCMSetTextServiceProperty:
-	    result = CallBIMFunctionWithStorage( inSessionHandle, inParams,
-						 (ProcPtr) BIMSetTextServiceProperty,
-						 uppSetTextServicePropertyInfo);
-	    break;
-
-        default:
-            result = badComponentSelector;
-            break;
+    switch(inParams->what) {
+	// Component Manager‚©‚ç‚ÌŽw—ß
+    case kComponentOpenSelect:
+	result = CallBIMFunction(inParams, (ProcPtr)BIMOpenComponent, uppOpenComponentProcInfo);
+	break;
+    case kComponentCloseSelect:
+	result = CallBIMFunctionWithStorage(inSessionHandle, inParams, (ProcPtr)BIMCloseComponent,
+					    uppCloseComponentProcInfo);
+	break;
+    case kComponentCanDoSelect:            
+	result = CallBIMFunction(inParams, (ProcPtr)BIMCanDo, uppCanDoProcInfo);
+	break;
+    case kComponentVersionSelect:
+	result = CallBIMFunction(inParams, (ProcPtr)BIMGetVersion, uppGetVersionProcInfo);
+	break;
+	// TSM‚©‚ç‚ÌŽw—ß
+    case kCMGetScriptLangSupport:
+	result = CallBIMFunctionWithStorage(inSessionHandle, inParams, (ProcPtr)BIMGetScriptLangSupport,
+					    uppGetScriptLangSupportProcInfo);
+	break;
+    case kCMInitiateTextService:
+	result = CallBIMFunctionWithStorage(inSessionHandle, inParams, (ProcPtr)BIMInitiateTextService,
+					    uppInitiateTextServiceProcInfo);
+	break;
+    case kCMTerminateTextService:
+	result = CallBIMFunctionWithStorage(inSessionHandle, inParams, (ProcPtr)BIMTerminateTextService,
+					    uppTerminateTextServiceProcInfo);
+	break;
+    case kCMActivateTextService:
+	result = CallBIMFunctionWithStorage(inSessionHandle, inParams, (ProcPtr)BIMActivateTextService,
+					    uppActivateTextServiceProcInfo);
+	break;
+    case kCMDeactivateTextService:
+	result = CallBIMFunctionWithStorage(inSessionHandle, inParams, (ProcPtr)BIMDeactivateTextService,
+					    uppDeactivateTextServiceProcInfo);
+	break;
+    case kCMTextServiceEvent:
+	result = CallBIMFunctionWithStorage(inSessionHandle, inParams, (ProcPtr)BIMTextServiceEventRef,
+					     uppTextServiceEventRefProcInfo);
+	break;
+    case kCMGetTextServiceMenu:
+	result = CallBIMFunctionWithStorage(inSessionHandle, inParams, (ProcPtr)BIMGetTextServiceMenu,
+					    uppGetTextServiceMenuProcInfo);
+	break;
+    case kCMFixTextService:
+	result = CallBIMFunctionWithStorage(inSessionHandle, inParams, (ProcPtr)BIMFixTextService,
+					     uppFixTextServiceProcInfo);
+	break;
+    case kCMHidePaletteWindows:
+	result = CallBIMFunctionWithStorage(inSessionHandle, inParams, (ProcPtr) BIMHidePaletteWindows,
+					    uppHidePaletteWindowsProcInfo);
+	break;
+    case kCMCopyTextServiceInputModeList:
+	result = CallBIMFunctionWithStorage(inSessionHandle, inParams, (ProcPtr)BIMCopyTextServiceInputModeList,
+					     uppCopyTextServiceInputModeListInfo);
+	break;
+    case kCMSetTextServiceProperty:
+	result = CallBIMFunctionWithStorage(inSessionHandle, inParams, (ProcPtr)BIMSetTextServiceProperty,
+					    uppSetTextServicePropertyInfo);
+	break;
+    default:
+	result = badComponentSelector;
+	break;
     }
 
     return result;
@@ -166,8 +134,6 @@
     result = noErr;
     sessionHandle = nil;
 
-    BIMLog("Open Component(%d)\n", inComponentInstance);
-
     // Å‰‚̃Cƒ“ƒXƒ^ƒ“ƒX‚¾‚Á‚½‚çƒOƒ[ƒoƒ‹’l‚à‰Šú‰»B
     if(gInstanceRefCount == 0) {
         result = BIMInitialize(inComponentInstance, &gTextServiceMenu);
@@ -208,81 +174,73 @@
 }
 
 // ƒZƒŒƒNƒ^‚ª—˜—p‰Â”\‚©‚Ç‚¤‚©‚ð•Ô‚·B
-pascal ComponentResult BIMCanDo( SInt16 inSelector )
-{
+pascal ComponentResult BIMCanDo(SInt16 inSelector) {
     Boolean result;
 
-    switch( inSelector )
-	{
-        case kComponentOpenSelect:
-        case kComponentCloseSelect:
-        case kComponentCanDoSelect:
-        case kComponentVersionSelect:
-            result = true;
-            break;
-
-	case kCMGetScriptLangSupport:
-        case kCMInitiateTextService:
-        case kCMTerminateTextService:
-        case kCMActivateTextService:
-        case kCMDeactivateTextService:
-        case kCMTextServiceEvent:
-        case kCMGetTextServiceMenu:
-        case kCMFixTextService:
-        case kCMHidePaletteWindows:
-	case kCMCopyTextServiceInputModeList:
-	case kCMSetTextServiceProperty:
-            result = true;
-            break;
-
-        default:
-            result = false;
-            break;
+    switch(inSelector) {
+    case kComponentOpenSelect:
+    case kComponentCloseSelect:
+    case kComponentCanDoSelect:
+    case kComponentVersionSelect:
+	result = true;
+	break;
+
+    case kCMGetScriptLangSupport:
+    case kCMInitiateTextService:
+    case kCMTerminateTextService:
+    case kCMActivateTextService:
+    case kCMDeactivateTextService:
+    case kCMTextServiceEvent:
+    case kCMGetTextServiceMenu:
+    case kCMFixTextService:
+    case kCMHidePaletteWindows:
+    case kCMCopyTextServiceInputModeList:
+    case kCMSetTextServiceProperty:
+	result = true;
+	break;
+
+    default:
+	result = false;
+	break;
     }
     return result;
 }
 
 // Œ»ÝA‚±‚̊֐”‚ªŒÄ‚΂ê‚邱‚Æ‚Í‚È‚¢B
-pascal ComponentResult BIMGetVersion( void )
-{
+pascal ComponentResult BIMGetVersion() {
     return 0x00010000;
 }
 
 // Œ¾Œê‚ÌŽí—Þ‚ð•Ô‚·B
-pascal ComponentResult BIMGetScriptLangSupport( Handle inSessionHandle,
-                                              ScriptLanguageSupportHandle *outScriptHandle )
-{
-#pragma unused (inSessionHandle)
-
+pascal ComponentResult BIMGetScriptLangSupport(Handle inSessionHandle, ScriptLanguageSupportHandle* outScriptHandle) {
     OSStatus			result = noErr;
     ScriptLanguageRecord	scriptLanguageRecord;
 	
-    if( *outScriptHandle == NULL ) {
-        *outScriptHandle = (ScriptLanguageSupportHandle) NewHandle ( sizeof( SInt16 ) );
-        if( *outScriptHandle == NULL )
+    if(*outScriptHandle == NULL) {
+        *outScriptHandle = (ScriptLanguageSupportHandle)NewHandle(sizeof(SInt16));
+        if(*outScriptHandle == NULL)
             result = memFullErr;
     }
-	
-    if( result == noErr ) {
-        SetHandleSize( (Handle) *outScriptHandle, sizeof( SInt16 ) );
+
+    if(result == noErr) {
+        SetHandleSize((Handle)*outScriptHandle, sizeof(SInt16));
         result = MemError();
-        if( result == noErr )
-            ( **outScriptHandle )->fScriptLanguageCount = 0;        
+        if(result == noErr)
+            (**outScriptHandle)->fScriptLanguageCount = 0;        
     }
 
     // Unicode‚ðŽg‚¤‚±‚Æ‚ðéŒ¾‚·‚éB
-    if( result == noErr ) {
+    if(result == noErr) {
         scriptLanguageRecord.fScript = kTextEncodingUnicodeDefault;
-        scriptLanguageRecord.fLanguage = kBIMLanguage;
-        result = PtrAndHand( &scriptLanguageRecord, (Handle) *outScriptHandle,
-                             sizeof( ScriptLanguageRecord ) );
-        if( result == noErr )
+        scriptLanguageRecord.fLanguage = langJapanese;
+        result = PtrAndHand(&scriptLanguageRecord, (Handle)*outScriptHandle, sizeof(ScriptLanguageRecord));
+        if(result == noErr)
             (**outScriptHandle)->fScriptLanguageCount++;
     }
-	
-    if( result ){
-        if( *outScriptHandle ) {
-            DisposeHandle( (Handle) *outScriptHandle );
+
+    if(result) {
+        if(*outScriptHandle) {
+            DisposeHandle((Handle)*outScriptHandle );
             *outScriptHandle = NULL;
         }
     }
@@ -302,29 +260,23 @@
 }
 
 // ‚±‚̊֐”‚͌Ă΂ê‚È‚¢B
-pascal ComponentResult BIMTerminateTextService( Handle inSessionHandle )
-{
-#pragma unused (inSessionHandle)
-
+pascal ComponentResult BIMTerminateTextService(Handle inSessionHandle) {
     return noErr;
 }
 
 // TextService‚ªƒAƒNƒeƒBƒu‚É‚È‚éB
-pascal ComponentResult BIMActivateTextService( Handle inSessionHandle )
-{
-    return BIMSessionActivate( (BIMSessionHandle) inSessionHandle );
+pascal ComponentResult BIMActivateTextService(Handle inSessionHandle) {
+    return BIMSessionActivate((BIMSessionHandle)inSessionHandle);
 }
 
 // TextService‚ªƒAƒNƒeƒBƒu‚Å‚È‚­‚È‚éB
-pascal ComponentResult BIMDeactivateTextService( Handle inSessionHandle )
-{
-    return BIMSessionDeactivate( (BIMSessionHandle) inSessionHandle );
+pascal ComponentResult BIMDeactivateTextService(Handle inSessionHandle) {
+    return BIMSessionDeactivate((BIMSessionHandle)inSessionHandle);
 }
 
 // ƒRƒ“ƒ|[ƒlƒ“ƒg‚̃Cƒxƒ“ƒgƒnƒ“ƒhƒ‰
-pascal ComponentResult BIMTextServiceEventRef( Handle inSessionHandle, EventRef inEventRef )
-{
-    return BIMSessionEvent( (BIMSessionHandle) inSessionHandle, inEventRef );
+pascal ComponentResult BIMTextServiceEventRef(Handle inSessionHandle, EventRef inEventRef) {
+    return BIMSessionEvent((BIMSessionHandle)inSessionHandle, inEventRef);
 }
 
 // ‰”•Mƒƒjƒ…[‚ð•Ô‚·B
@@ -335,15 +287,13 @@
 }
 
 // Šm’è
-pascal ComponentResult BIMFixTextService( Handle inSessionHandle )
-{
-    return BIMSessionFix( (BIMSessionHandle) inSessionHandle );
+pascal ComponentResult BIMFixTextService(Handle inSessionHandle) {
+    return BIMSessionFix((BIMSessionHandle)inSessionHandle);
 }
 
 // ƒpƒŒƒbƒg‚ð‰B‚·
-pascal ComponentResult BIMHidePaletteWindows( Handle inSessionHandle )
-{
-    return BIMSessionHidePalettes( (BIMSessionHandle) inSessionHandle );
+pascal ComponentResult BIMHidePaletteWindows(Handle inSessionHandle) {
+    return BIMSessionHidePalettes((BIMSessionHandle)inSessionHandle);
 }
 
 // “ü—̓‚[ƒh‚̈ꗗ‚ð•Ô‚·
@@ -371,17 +321,14 @@
     return noErr;
 }
 
-pascal ComponentResult BIMSetTextServiceProperty(
-    Handle inSessionHandle,
-    TextServicePropertyTag tag, TextServicePropertyValue value)
-{
+pascal ComponentResult BIMSetTextServiceProperty(Handle inSessionHandle, TextServicePropertyTag tag,
+						 TextServicePropertyValue value) {
     if(tag != kTextServiceInputModePropertyTag) {
 	BIMLog("Can't SetTextServiceProperty[%d]\n", tag);
 	return tsmComponentPropertyUnsupportedErr;
     }
     CFStringRef newMode = (CFStringRef)value;
-    IMSessionInputMode* inputMode
-	= (*(BIMSessionHandle)inSessionHandle)->imsession_input_mode;
+    IMSessionInputMode* inputMode = (*(BIMSessionHandle)inSessionHandle)->imsession_input_mode;
 
     // ASCII ƒ‚[ƒh‚ŏ‰Šú‰»‚·‚é(BIMInitiateTextService ‚àŽQÆ)
     if((*(BIMSessionHandle)inSessionHandle)->asciimode_startup) {
@@ -396,24 +343,21 @@
 	}
     }
 
-    if(CFStringCompare(newMode,
-		       kTextServiceInputModeJapaneseKatakana, 0) == 0) {
+    if(CFStringCompare(newMode, kTextServiceInputModeJapaneseKatakana, 0) == 0) {
 	if(!inputMode->isZenKataInputMode()) {
 	    inputMode->goZenKataInputMode();
 	    return noErr;
 	}
     }
 
-    if(CFStringCompare(newMode,
-		       kTextServiceInputModeJapaneseHalfWidthKana, 0) == 0) {
+    if(CFStringCompare(newMode, kTextServiceInputModeJapaneseHalfWidthKana, 0) == 0) {
 	if(!inputMode->isHanKataInputMode()) {
 	    inputMode->goHanKataInputMode();
 	    return noErr;
 	}
     }
 
-    if(CFStringCompare(newMode,
-		       kTextServiceInputModeJapaneseFullWidthRoman, 0) == 0) {
+    if(CFStringCompare(newMode, kTextServiceInputModeJapaneseFullWidthRoman, 0) == 0) {
 	if(!inputMode->isZenAscInputMode()) {
 	    inputMode->goZenAscInputMode();
 	    return noErr;
@@ -432,28 +376,25 @@
 
 // UPP‚ðì¬‚µAŒÄ‚ԁB
 // CarbonŠÂ‹«‚ÅUPP‚Á‚Ä–{“–‚É•K—v‚ ‚é‚Ì‚©H
-static ComponentResult CallBIMFunction( ComponentParameters *inParams, ProcPtr inProcPtr,
-                                        SInt32 inProcInfo )
-{
+static ComponentResult CallBIMFunction(ComponentParameters* inParams, ProcPtr inProcPtr, SInt32 inProcInfo) {
     ComponentResult		result;
     ComponentFunctionUPP	componentFunctionUPP;
 
     result = noErr;
-    componentFunctionUPP = NewComponentFunctionUPP( inProcPtr, inProcInfo );
-    result = CallComponentFunction( inParams, componentFunctionUPP );
-    DisposeComponentFunctionUPP( componentFunctionUPP );
+    componentFunctionUPP = NewComponentFunctionUPP(inProcPtr, inProcInfo);
+    result = CallComponentFunction(inParams, componentFunctionUPP);
+    DisposeComponentFunctionUPP(componentFunctionUPP);
     return result;
 }
-static ComponentResult CallBIMFunctionWithStorage( Handle inStorage,
-                                                   ComponentParameters *inParams,
-                                                   ProcPtr inProcPtr, SInt32 inProcInfo )
-{
+
+static ComponentResult CallBIMFunctionWithStorage(Handle inStorage, ComponentParameters* inParams, ProcPtr inProcPtr,
+						  SInt32 inProcInfo) {
     ComponentResult		result;
     ComponentFunctionUPP	componentFunctionUPP;
 
     result = noErr;
-    componentFunctionUPP = NewComponentFunctionUPP( inProcPtr, inProcInfo );
-    result = CallComponentFunctionWithStorage( inStorage, inParams, componentFunctionUPP );
-    DisposeComponentFunctionUPP( componentFunctionUPP );
+    componentFunctionUPP = NewComponentFunctionUPP(inProcPtr, inProcInfo);
+    result = CallComponentFunctionWithStorage(inStorage, inParams, componentFunctionUPP);
+    DisposeComponentFunctionUPP(componentFunctionUPP);
     return result;
 }
Index: AquaSKK/CandidatesWindowController.mm
diff -u AquaSKK/CandidatesWindowController.mm:1.2 AquaSKK/CandidatesWindowController.mm:1.2.2.1
--- AquaSKK/CandidatesWindowController.mm:1.2	Sat Oct  8 00:08:36 2005
+++ AquaSKK/CandidatesWindowController.mm	Sun Jan  8 16:15:30 2006
@@ -1,23 +1,24 @@
 /* -*- objc -*-
-	$Id: CandidatesWindowController.mm,v 1.2 2005/10/07 15:08:36 t-suwa Exp $
-	---------
-	
-    MacOS X implementation of the SKK input method.
-    Copyright (C) 2002 phonohawk
-
-    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
+  $Id: CandidatesWindowController.mm,v 1.2.2.1 2006/01/08 07:15:30 t-suwa Exp $
+
+  MacOS X implementation of the SKK input method.
+
+  Copyright (C) 2002 phonohawk
+  Copyright (C) 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
 */
 
 #import <AppKit/AppKit.h>
@@ -27,62 +28,53 @@
 
 @implementation CandidatesWindowController
 
-- initWithCandidates:(NSArray*)cands
-{
-	self = [super initWithWindowNibName:@"Candidates"];
-	[self window]; // load now
-	
-	self->candidates = [[NSArray alloc] initWithArray:cands];
-	
-	[[self window]
-		setBackgroundColor:
-            [[PreferencesController sharedController] windowColor]];
-    
-    [[self window]
-		setAlphaValue:
-            [[PreferencesController sharedController] windowAlpha]];
-	
-	self->candidates_view = [[CandidatesView alloc] initWithCandidates:cands];
-	[[self window] setContentSize:[candidates_view bounds].size]; // candidates_view‚̃TƒCƒY‚ɐݒèB
-	[[[self window] contentView] addSubview:candidates_view]; // ƒEƒCƒ“ƒhƒE‚É’u‚­B
-	
-	[[self window] setLevel:NSFloatingWindowLevel];
-	
-	return self;
-}
-
-- (NSArray*)getCandidates
-{
-	return candidates;
-}
-
-- (void)dealloc
-{
-	[super dealloc];
-}
-
-- (void)showNextFrame
-{
-	[candidates_view showNextFrame];
-}
-
-- (void)showPrevFrame
-{
-	[candidates_view showPrevFrame];
-}
-
-- (unsigned)getCandidatesPerFrame
-{
-	return [candidates_view getCandidatesPerFrame];
-}
-
-- (unsigned)getNumOfFrames
-{
-	return [candidates_view getNumOfFrames];
+- initWithCandidates:(NSArray*)cands {
+    self = [super initWithWindowNibName:@"Candidates"];
+    [self window]; // load now
+
+    self->candidates = [[NSArray alloc] initWithArray:cands];
+
+    // ”wŒiF
+    [[self window] setBackgroundColor: [[PreferencesController sharedController] windowColor]];
+
+    // •s“§–¾“x
+    [[self window] setAlphaValue: [[PreferencesController sharedController] windowAlpha]];
+
+    self->candidates_view = [[CandidatesView alloc] initWithCandidates:cands];
+    [[self window] setContentSize:[candidates_view bounds].size];
+    [[[self window] contentView] addSubview:candidates_view];
+
+    // ƒEƒBƒ“ƒhƒEƒŒƒxƒ‹
+    [[self window] setLevel:NSFloatingWindowLevel];
+
+    return self;
+}
+
+- (NSArray*)getCandidates {
+    return candidates;
+}
+
+- (void)dealloc {
+    [super dealloc];
+}
+
+- (void)showNextFrame {
+    [candidates_view showNextFrame];
+}
+
+- (void)showPrevFrame {
+    [candidates_view showPrevFrame];
+}
+
+- (unsigned)getCandidatesPerFrame {
+    return [candidates_view getCandidatesPerFrame];
+}
+
+- (unsigned)getNumOfFrames {
+    return [candidates_view getNumOfFrames];
 }
 
-- (void)setCurrentFrame:(unsigned)frame
-{
+- (void)setCurrentFrame:(unsigned)frame {
     [candidates_view setCurrentFrame:frame];
 }
 
Index: AquaSKK/ChangeLog
diff -u AquaSKK/ChangeLog:1.20.2.1 AquaSKK/ChangeLog:1.20.2.2
--- AquaSKK/ChangeLog:1.20.2.1	Sat Jan  7 16:22:28 2006
+++ AquaSKK/ChangeLog	Sun Jan  8 16:15:30 2006
@@ -1,3 +1,18 @@
+2006-01-08  Tomotaka SUWA  <t.suw****@mac*****>
+
+	* BIMScript.h, skkicons.r: íœB
+
+	* Info-AquaSKKInputMethod.plist: ƒAƒCƒRƒ“‚̐ݒè‚ð’ljÁB
+
+	* BIM.r: Universal Binary ‚ɑΉžB
+
+	* SKKDictionary.*: “à•”\‘¢‚ð‘啝‚ɕύXBŽ«‘‚̃[ƒhŽžŠÔ‚ð’ZkB
+	tab ‚É‚æ‚é•âŠ®‚ð–{‰Æ‚Æ“¯‚¶“®ì‚ɉü‘PB
+
+	* Dictionary.h: ŠeŽíƒ†[ƒeƒBƒŠƒeƒBƒNƒ‰ƒX‚ð’ljÁB
+
+	* CppCFString.* (toStdString): V‹K’ljÁB
+
 2006-01-07  Tomotaka SUWA  <t.suw****@mac*****>
 
 	* Japanese.lproj/Preferences.nib/*: ŠeŽíƒIƒvƒVƒ‡ƒ“‚̒ljÁ
Index: AquaSKK/CppCFString.cpp
diff -u AquaSKK/CppCFString.cpp:1.3 AquaSKK/CppCFString.cpp:1.3.2.1
--- AquaSKK/CppCFString.cpp:1.3	Wed Nov  9 00:02:24 2005
+++ AquaSKK/CppCFString.cpp	Sun Jan  8 16:15:30 2006
@@ -1,10 +1,10 @@
 /*
-  $Id: CppCFString.cpp,v 1.3 2005/11/08 15:02:24 t-suwa Exp $
+  $Id: CppCFString.cpp,v 1.3.2.1 2006/01/08 07:15:30 t-suwa Exp $
 	
   MacOS X implementation of the SKK input method.
 
   Copyright (C) 2002-2004 phonohawk
-  Copyright (C) 2005 Tomotaka SUWA <t.suw****@mac*****>
+  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
@@ -30,8 +30,7 @@
 
 CppCFString::CppCFString(const CppCFString& cpp_cf_string_src) {
     // ƒRƒs[ƒRƒ“ƒXƒgƒ‰ƒNƒ^
-    cf_string = CFStringCreateMutableCopy(NULL, 0,
-					  cpp_cf_string_src.getString());
+    cf_string = CFStringCreateMutableCopy(NULL, 0, cpp_cf_string_src.getString());
 }
 
 CppCFString::CppCFString(UniChar c) {
@@ -127,9 +126,7 @@
 
 CppCFString& CppCFString::eraseLast(const unsigned int n_chars) {
     // ’·‚³‚̓`ƒFƒbƒN‚µ‚È‚¢B’ˆÓB
-    CFStringDelete(cf_string,
-		   CFRangeMake(CFStringGetLength(cf_string) - n_chars,
-			       n_chars));
+    CFStringDelete(cf_string, CFRangeMake(CFStringGetLength(cf_string) - n_chars, n_chars));
     return *this;
 }
 
@@ -137,8 +134,7 @@
     return substring(start_pos, length());
 }
 
-CppCFString CppCFString::substring(const unsigned int start_pos,
-				   const unsigned int end_pos) const {
+CppCFString CppCFString::substring(const unsigned int start_pos, const unsigned int end_pos) const {
     // start_pos‚ÍŠÜ‚Þ‚ªend_pos‚ÍŠÜ‚Ü‚È‚¢B
     // ‹«ŠEƒ`ƒFƒbƒN‚Í‚µ‚È‚¢‚Ì‚Å’ˆÓB
     const UniChar* unistr = CFStringGetCharactersPtr(cf_string);
@@ -209,8 +205,7 @@
     return result;
 }
 
-bool CppCFString::startsWith(const CppCFString& str,
-			     int search_start_pos) const {
+bool CppCFString::startsWith(const CppCFString& str, int search_start_pos) const {
     // ’·‚³‚ª‘«‚è‚Ä‚¢‚È‚¢H
     if (length() - static_cast<unsigned>(search_start_pos) < str.length())
 	return false;
@@ -218,8 +213,7 @@
     return substring(search_start_pos, search_start_pos + str.length()) == str;
 }
 
-bool CppCFString::endsWith(const CppCFString& str,
-			   int search_start_pos) const {
+bool CppCFString::endsWith(const CppCFString& str, int search_start_pos) const {
     if(search_start_pos == -1)
 	search_start_pos = length() - 1;
 	
@@ -227,23 +221,16 @@
     if(static_cast<unsigned>(search_start_pos) < str.length() - 1)
 	return false;
 
-    return substring(search_start_pos + 1 - str.length(),
-		     search_start_pos + 1) == str;
+    return substring(search_start_pos + 1 - str.length(), search_start_pos + 1) == str;
 }
 
-CppCFString& CppCFString::replace(const CppCFString& from,
-				  const CppCFString& to) {
-    CFStringFindAndReplace(cf_string,
-			   from.getString(),
-			   to.getString(),
-			   CFRangeMake(0, length()),
-			   0);
+CppCFString& CppCFString::replace(const CppCFString& from, const CppCFString& to) {
+    CFStringFindAndReplace(cf_string, from.getString(), to.getString(), CFRangeMake(0, length()), 0);
 
     return *this;
 }
 
-CppCFString CppCFString::replaceClone(const CppCFString& from,
-				      const CppCFString& to) const {
+CppCFString CppCFString::replaceClone(const CppCFString& from, const CppCFString& to) const {
     return clone().replace(from, to);
 }
 
@@ -319,6 +306,14 @@
     return buf;
 }
 
+std::string CppCFString::toStdString(CFStringEncoding encoding) const {
+    char* tmp = toCString(encoding);
+    std::string str(tmp);
+    delete[] tmp;
+
+    return str;
+}
+
 CppCFString CppCFString::clone() const {
     return CppCFString(*this);
 }
@@ -327,89 +322,76 @@
     const int len = CFStringGetLength(cf_string);
     UniChar* unistr = const_cast<UniChar*>(CFStringGetCharactersPtr(cf_string));
     bool unistr_is_independent = false;
-    if (unistr == NULL)
-    {
+    if(unistr == NULL) {
 	unistr = new UniChar[len];
 	unistr_is_independent = true;
-		
+
 	CFStringGetCharacters(cf_string,CFRangeMake(0,len),unistr);
     }
 	
     std::vector<CppCFString> result;
 	
     int pos = 0;
-    while (pos < len)
-    {
-	if (unistr[pos] == delim) // ƒfƒŠƒ~ƒ^‚¾‚Á‚½B
-	{
+    while(pos < len) {
+	// ƒfƒŠƒ~ƒ^‚¾‚Á‚½
+	if(unistr[pos] == delim) {
 	    pos++;
-	}
-	else // ƒfƒŠƒ~ƒ^‚Å‚È‚¢•¶Žš‚ªŒ©•t‚©‚Á‚½B
-	{
+	} else {
+	    // ƒfƒŠƒ~ƒ^‚Å‚È‚¢•¶Žš‚ªŒ©•t‚©‚Á‚½
 	    int blockstart = pos;
 	    int blockend = -1;
 			
-	    for (int i = blockstart;i < len;i++)
-	    {
+	    for(int i = blockstart;i < len;i++) {
 		// ƒfƒŠƒ~ƒ^‚ð’T‚·B
-		if (unistr[i] == delim)
-		{
+		if(unistr[i] == delim) {
 		    blockend = i;
 		    break;
 		}
 	    }
-			
-	    if (blockend == -1) // ƒfƒŠƒ~ƒ^‚ªŒ©•t‚©‚ç‚È‚©‚Á‚½
-	    {
+
+	    // ƒfƒŠƒ~ƒ^‚ªŒ©•t‚©‚ç‚È‚©‚Á‚½			
+	    if(blockend == -1) {
 		blockend = len; // ÅŒã‚Ü‚Å‚ðƒg[ƒNƒ“‚Æ‚·‚éB
 	    }
-			
+
 	    result.push_back(substring(blockstart,blockend));
 	    pos = blockend;
 	}
     }
 	
-    if (unistr_is_independent)
-    {
+    if(unistr_is_independent) {
 	delete[] unistr;
     }
     return result;
 }
 
 // ”ñƒƒ“ƒoŠÖ”ŒQ
-CppCFString operator+(const CppCFString& l, const CppCFString& r)
-{
+CppCFString operator+(const CppCFString& l, const CppCFString& r) {
     return CppCFString(l).append(r);
 }
 
-CppCFString operator+(const CppCFString& l, const UniChar r)
-{
+CppCFString operator+(const CppCFString& l, const UniChar r) {
     return CppCFString(l).append(r);
 }
 
-CppCFString operator+(const UniChar l, const CppCFString& r)
-{
+CppCFString operator+(const UniChar l, const CppCFString& r) {
     return CppCFString().append(l).append(r);
 }
 
 bool operator==(const CppCFString& l, const CppCFString& r) {
-    return CFStringCompare(l.getString(),
-			   r.getString(), 0) == kCFCompareEqualTo;
+    return CFStringCompare(l.getString(), r.getString(), 0) == kCFCompareEqualTo;
 }
 
 bool operator!=(const CppCFString& l, const CppCFString& r) {
-    return CFStringCompare(l.getString(),
-			   r.getString(), 0) != kCFCompareEqualTo;
+    return CFStringCompare(l.getString(), r.getString(), 0) != kCFCompareEqualTo;
 }
 
 bool operator<(const CppCFString& l, const CppCFString& r) {
-    return CFStringCompare(l.getString(),
-			   r.getString(), 0) == kCFCompareLessThan;
+    return CFStringCompare(l.getString(), r.getString(), 0) == kCFCompareLessThan;
 }
 
 bool operator>(const CppCFString& l, const CppCFString& r) {
-    return CFStringCompare(l.getString(),
-			   r.getString(), 0) == kCFCompareGreaterThan;
+    return CFStringCompare(l.getString(), r.getString(), 0) == kCFCompareGreaterThan;
 }
 
 bool operator<=(const CppCFString& l, const CppCFString& r) {
@@ -424,9 +406,8 @@
 
 CppCFString join(UniChar delim, const std::vector<CppCFString>& vec) {
     CppCFString result;
-	
-    for(std::vector<CppCFString>::const_iterator ite = vec.begin();
-	ite != vec.end(); ++ ite) {
+
+    for(std::vector<CppCFString>::const_iterator ite = vec.begin(); ite != vec.end(); ++ ite) {
 	result += *ite + delim;
     }
 
@@ -453,7 +434,7 @@
     for (;unistr != unistr_end; unistr += sizeof(UniChar)) {
 	result = 5 * result + *unistr;
     }
-	
+
     if(unistr_is_independent) delete[] unistr;
 
     return result;
Index: AquaSKK/CppCFString.h
diff -u AquaSKK/CppCFString.h:1.3 AquaSKK/CppCFString.h:1.3.2.1
--- AquaSKK/CppCFString.h:1.3	Wed Nov  9 00:02:24 2005
+++ AquaSKK/CppCFString.h	Sun Jan  8 16:15:30 2006
@@ -1,28 +1,31 @@
 /*  -*- c++ -*-
-    $Id: CppCFString.h,v 1.3 2005/11/08 15:02:24 t-suwa Exp $
-    ---------
-	
-    MacOS X implementation of the SKK input method.
-    Copyright (C) 2002 phonohawk
-
-    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
+  $Id: CppCFString.h,v 1.3.2.1 2006/01/08 07:15:30 t-suwa Exp $
+
+  MacOS X implementation of the SKK input method.
+
+  Copyright (C) 2002 phonohawk
+  Copyright (C) 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
 */
 
 #pragma once
 
+#include <Carbon/Carbon.h>
 #include <vector>
+#include <string>
 
 // CFString‚̃‰ƒbƒp[B
 // CFMutableStringRef‚ðƒ‰ƒbƒv‚µAstd::string‚âjava.lang.StringBuffer‚̂悤‚Ɉµ‚¦‚é‚悤‚É‚·‚éB
@@ -75,6 +78,7 @@
     virtual UniChar* toUniCharPtr() const;
     virtual CFMutableDataRef toCFData() const;
     virtual char* toCString(CFStringEncoding encoding = kCFStringEncodingMacRomanLatin1) const;
+    virtual std::string toStdString(CFStringEncoding encoding = kCFStringEncodingEUC_JP) const;
     virtual CppCFString clone() const;
     
     virtual std::vector<CppCFString> split(UniChar delim) const;
@@ -93,7 +97,6 @@
 
 CppCFString join(UniChar delim, const std::vector<CppCFString>& vec);
 
-
 class hash_CppCFString {
 public:
     size_t operator() (const CppCFString& str) const;
Index: AquaSKK/Dictionary.h
diff -u AquaSKK/Dictionary.h:1.3 AquaSKK/Dictionary.h:1.3.2.1
--- AquaSKK/Dictionary.h:1.3	Wed Nov  9 00:02:24 2005
+++ AquaSKK/Dictionary.h	Sun Jan  8 16:15:30 2006
@@ -1,10 +1,10 @@
 /*
-  $Id: Dictionary.h,v 1.3 2005/11/08 15:02:24 t-suwa Exp $
+  $Id: Dictionary.h,v 1.3.2.1 2006/01/08 07:15:30 t-suwa Exp $
 
   MacOS X implementation of the SKK input method.
 
   Copyright (C) 2002 phonohawk
-  Copyright (C) 2005 Tomotaka SUWA <t.suw****@mac*****>
+  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
@@ -24,6 +24,8 @@
 #pragma once
 
 #include <vector>
+#include <string>
+#include <numeric>
 
 class OkuriganaEntry;
 class CppCFString;
@@ -66,3 +68,373 @@
     virtual void removeOkuriNasi(const CppCFString& index,
 				 const CppCFString& kanji) = 0;
 };
+
+// ƒIƒuƒWƒFƒNƒg‚ð˜AŒ‹‚·‚éƒtƒ@ƒ“ƒNƒ^
+struct SKKConcatObject {
+    template<typename T>
+    std::string operator()(const std::string& seed, const T& obj) const {
+	return seed + "/" + obj.Description();
+    }
+};
+
+// •”•ª•¶Žš—ñ‚ð•Ô‚µ‚Ä‚¢‚­’Pƒ‚ȃp[ƒT
+class SKKEntryParser {
+    const std::string& target_;
+    const bool isOkuriAri_;	// ‘Ώۂªu‘—‚è‚ ‚èv‚©‚Ç‚¤‚©
+
+    std::string fetch(bool first = false) const {
+	static std::string::size_type pos1;
+	static std::string::size_type pos2;
+
+	if(first) {
+	    pos1 = pos2 = 0;
+	}
+
+	pos1 = target_.find_first_not_of('/', pos2);
+	pos2 = target_.find_first_of('/', pos1);
+
+	// Œ©‚‚©‚Á‚½H
+	if(pos1 != std::string::npos && pos2 != std::string::npos) {
+	    if(!isOkuriAri_ || target_[pos1] != '[') {
+		return target_.substr(pos1, pos2 - pos1);
+	    }
+	}
+	return std::string();
+    }
+
+public:
+    SKKEntryParser(const std::string& str, bool isOkuriAri = false) : target_(str), isOkuriAri_(isOkuriAri) {
+	// empty
+    }
+    std::string First() const {
+	return fetch(true);
+    }
+    std::string Next() const {
+	return fetch();
+    }
+};
+
+// ’Pˆê‚Ì•ÏŠ·Œó•â(/Œó•â;’Žß/ ¨ /word_;annotation_/ ¨ Description())
+class SKKCandidate {
+    std::string word_;
+    std::string annotation_;
+
+    void setup(const std::string& str) {
+	std::string::size_type pos = str.find_first_of(';');
+
+	// ’Žß‚ª‚ ‚éH
+	if(pos != std::string::npos) {
+	    annotation_ = str.substr(pos + 1);
+	}
+	word_ = str.substr(0, pos);
+    }
+
+public:
+    SKKCandidate() : word_(std::string()), annotation_(std::string()) {
+	// empty
+    }
+    SKKCandidate(const std::string& word, const std::string& annotation) : word_(word), annotation_(annotation) {
+	// empty
+    }
+    SKKCandidate(const std::string& candidate) {
+	setup(candidate);
+    }
+    SKKCandidate(const SKKCandidate& src) : word_(src.word_), annotation_(src.annotation_) {
+	// empty
+    }
+
+    bool IsEmpty() const {
+	return word_.empty();
+    }
+    std::string Word() const {
+	return word_;
+    }
+    std::string Annotation() const {
+	return annotation_;
+    }
+    std::string Description() const {
+	return Word() + (annotation_.empty() ? "" : (";" + annotation_));
+    }
+
+    bool operator==(const SKKCandidate& rhs) const {
+	// ’Žß‚Í”äŠr‚µ‚È‚¢
+	return word_ == rhs.word_;
+    }
+};
+
+typedef std::vector<SKKCandidate> SKKCandidateContainer;
+typedef SKKCandidateContainer::iterator SKKCandidateIterator;
+
+// ‘—‚è‚ ‚èƒGƒ“ƒgƒŠ‚̃qƒ“ƒgî•ñ([‚­/‘/‘~/Œ‡/] ‚Ì•”•ª)
+class SKKOkuriHint {
+    std::string kana_;
+    SKKCandidateContainer candidates_;
+
+    void setup(const std::string& str) {
+	std::string ret;
+	SKKEntryParser parser(str);
+
+	kana_ = parser.First();
+	for(ret = parser.Next(); !ret.empty(); ret = parser.Next()) {
+	    candidates_.push_back(ret);
+	}
+    }
+
+    SKKCandidate fetchCandidate(bool first = false) const {
+	static int i;
+	if(first) {
+	    i = 0;
+	}
+
+	if(i < Count()) {
+	    return candidates_[i ++];
+	}
+	return SKKCandidate();
+    }
+
+public:
+    SKKOkuriHint() {
+	// empty
+    }
+    SKKOkuriHint(const std::string& kana, const SKKCandidate& candidate) : kana_(kana) {
+	candidates_.push_back(candidate);
+    }
+    SKKOkuriHint(const std::string& str) {
+	setup(str);
+    }
+    SKKOkuriHint(const SKKOkuriHint& src) : kana_(src.kana_), candidates_(src.candidates_) {
+	// empty
+    }
+
+    bool IsEmpty() const {
+	return kana_.empty();
+    }
+    std::string Kana() const {
+	return kana_;
+    }
+    void SetKana(const std::string& kana) {
+	kana_ = kana;
+    }
+
+    SKKCandidate First() const {
+	return fetchCandidate(true);
+    }
+    SKKCandidate Next() const {
+	return fetchCandidate();
+    }
+    int Count() const {
+	return candidates_.size();
+    }
+
+    void Add(const SKKCandidate& theCandidate) {
+	Remove(theCandidate);
+	candidates_.insert(candidates_.begin(), theCandidate);
+    }
+    void Remove(const SKKCandidate& theCandidate) {
+	candidates_.erase(std::remove(candidates_.begin(), candidates_.end(), theCandidate), candidates_.end());
+    }
+    std::string Description() const {
+	return '[' + std::accumulate(candidates_.begin(), candidates_.end(), Kana(), SKKConcatObject()) + "/]";
+    }
+
+    bool operator==(const SKKOkuriHint& rhs) const {
+	return (kana_ == rhs.kana_ && candidates_ == rhs.candidates_);
+    }
+};
+
+typedef std::vector<SKKOkuriHint> SKKOkuriHintContainer;
+typedef SKKOkuriHintContainer::iterator SKKOkuriHintIterator;
+
+// SKK Ž«‘‚̈ês‚ð•\Œ»‚·‚éƒNƒ‰ƒX
+class SKKEntry {
+    bool isOkuriAri_;		// ‘—‚è‚ ‚è‚©‚Ç‚¤‚©
+    std::string key_;		// Œ©o‚µŒê
+    SKKCandidateContainer candidates_; // •ÏŠ·Œó•â
+    SKKOkuriHintContainer hints_;      // ‘—‚è‚ ‚èƒGƒ“ƒgƒŠ‚̃qƒ“ƒgî•ñ
+    std::string::size_type pos1_;
+    std::string::size_type pos2_;
+
+    std::string firstHint(const std::string& str) {
+	pos1_ = pos2_ = str.find("/[");
+	return nextHint(str);
+    }
+    std::string nextHint(const std::string& str) {
+	pos1_ = str.find_first_not_of("/[", pos2_ + 1);
+	pos2_ = str.find_first_of(']', pos1_);
+
+	// Œ©‚‚©‚Á‚½H
+	if(pos1_ != std::string::npos && pos2_ != std::string::npos) {
+	    return str.substr(pos1_, pos2_ - pos1_);
+	}
+	return std::string();
+    }
+
+    void setup(const std::string& str) {
+	std::string ret;
+	SKKEntryParser parser(str, isOkuriAri_);
+
+	// ‚Ü‚¸’ʏí‚ÌŒó•â‚𔲂«o‚·
+	for(ret = parser.First(); !ret.empty(); ret = parser.Next()) {
+	    candidates_.push_back(ret);
+	}
+
+	if(!isOkuriAri_) return;
+
+	// ŽŸ‚ɁA‘—‚è‚ ‚èƒGƒ“ƒgƒŠ‚̃qƒ“ƒgî•ñ‚𔲂«o‚·
+	for(ret = firstHint(str); !ret.empty(); ret = nextHint(str)) {
+	    hints_.push_back(ret);
+	}
+    }
+
+    SKKCandidate fetchCandidate(bool first = false) const {
+	static int i;
+	if(first) {
+	    i = 0;
+	}
+
+	if(i < Count()) {
+	    return candidates_[i ++];
+	}
+	return SKKCandidate();
+    }
+    SKKOkuriHint fetchHint(bool first = false) const {
+	static int i;
+	if(first) {
+	    i = 0;
+	}
+
+	if(i < HintCount()) {
+	    return hints_[i ++];
+	}
+	return SKKOkuriHint();
+    }
+
+    SKKCandidate updateCandidate(const SKKCandidate& theCandidate) {
+	SKKCandidate target;
+
+	// ’Žß‚ðŠÜ‚ÞŠ®‘S‚ȃGƒ“ƒgƒŠ‚ð’T‚·
+	SKKCandidateIterator i = std::find(candidates_.begin(), candidates_.end(), theCandidate);
+	// Œ©‚‚©‚Á‚½H
+	if(i != candidates_.end()) {
+	    target = *i;
+	    RemoveOkuriNasi(target);
+	} else {
+	    target = theCandidate;
+	}
+
+	// æ“ª‚ɒljÁ
+	candidates_.insert(candidates_.begin(), target);
+
+	return target;
+    }
+
+    SKKEntry() {}
+
+    SKKEntry(bool isOkuriAri, const std::string& key, const std::string& cand) : isOkuriAri_(isOkuriAri), key_(key) {
+	setup(cand);
+    }
+
+    SKKEntry(bool isOkuriAri, const std::string& key) : isOkuriAri_(isOkuriAri), key_(key) {
+	// empry
+    }
+
+public:
+    // Ž«‘‚̃Gƒ“ƒgƒŠ‚ðƒp[ƒX‚µ‚ăGƒ“ƒgƒŠ‚ðì¬‚·‚é
+    static SKKEntry ParseOkuriAri(const std::string& key, const std::string& candidate) {
+	return SKKEntry(true, key, candidate);
+    }
+    static SKKEntry ParseOkuriNasi(const std::string& key, const std::string& candidate) {
+	return SKKEntry(false, key, candidate);
+    }
+
+    // ƒL[‚¾‚¯‚̃Gƒ“ƒgƒŠ‚ðì¬‚·‚é
+    static SKKEntry CreateOkuriAri(const std::string& key) {
+	return SKKEntry(true, key);
+    }
+    static SKKEntry CreateOkuriNasi(const std::string& key) {
+	return SKKEntry(false, key);
+    }
+
+    // ƒRƒs[ƒRƒ“ƒXƒgƒ‰ƒNƒ^
+    SKKEntry(const SKKEntry& src) : isOkuriAri_(src.isOkuriAri_), key_(src.key_),
+	candidates_(src.candidates_), hints_(src.hints_), pos1_(src.pos1_), pos2_(src.pos2_) {
+	// empty
+    }
+
+    // Œó•â‚ÉŠÖ‚·‚é‘€ì
+    SKKCandidate First() const {
+	return fetchCandidate(true);
+    }
+    SKKCandidate Next() const {
+	return fetchCandidate();
+    }
+    int Count() const {
+	return candidates_.size();
+    }
+
+    // ƒqƒ“ƒg‚ÉŠÖ‚·‚é‘€ì
+    SKKOkuriHint FirstHint() const {
+	return fetchHint(true);
+    }
+    SKKOkuriHint NextHint() const {
+	return fetchHint();
+    }
+    int HintCount() const {
+	return hints_.size();
+    }
+
+    // ‘—‚è‚ ‚èŒó•â‚̒ljÁ
+    void AddOkuriAri(const SKKCandidate& theCandidate, const std::string& okuri) {
+	SKKCandidate target = updateCandidate(theCandidate);
+
+	// ƒqƒ“ƒg‚ªŒ©‚‚©‚ê‚΍XV‚·‚é
+	for(SKKOkuriHintIterator i = hints_.begin(); i != hints_.end(); ++ i) {
+	    if(i->Kana() == okuri) {
+		i->Add(target);
+		return;
+	    }
+	}
+
+	// Œ©‚‚©‚ç‚È‚¯‚ê‚ΐV‹K‚̃qƒ“ƒg‚ð’ljÁ
+	hints_.insert(hints_.begin(), SKKOkuriHint(okuri, target));
+    }
+    // ‘—‚è‚È‚µŒó•â‚̒ljÁ
+    void AddOkuriNasi(const SKKCandidate& theCandidate) {
+	updateCandidate(theCandidate);
+    }
+
+    // ‘—‚è‚ ‚èŒó•â‚̍폜
+    void RemoveOkuriAri(const SKKCandidate& theCandidate) {
+	RemoveOkuriNasi(theCandidate);
+
+	// ƒqƒ“ƒg‚àíœ
+	for(SKKOkuriHintIterator i = hints_.begin(); i != hints_.end(); /* empty */) {
+	    i->Remove(theCandidate);
+	    if(i->Count() == 0) {
+		i = hints_.erase(i);
+	    } else {
+		++ i;
+	    }
+	}
+    }
+    // ‘—‚è‚È‚µŒó•â‚̍폜
+    void RemoveOkuriNasi(const SKKCandidate& theCandidate) {
+	candidates_.erase(std::remove(candidates_.begin(), candidates_.end(), theCandidate), candidates_.end());
+    }
+
+    std::string Key() const {
+	return key_;
+    }
+    std::string Candidate() const {
+	std::string ret;
+	ret = std::accumulate(candidates_.begin(), candidates_.end(), ret, SKKConcatObject());
+	if(hints_.empty()) {
+	    return ret + "/";
+	}
+
+	return std::accumulate(hints_.begin(), hints_.end(), ret, SKKConcatObject()) + "/";
+    }
+    std::string Description() const {
+	return Key() + " " + Candidate();
+    }
+};
Index: AquaSKK/Info-AquaSKKInputMethod.plist
diff -u AquaSKK/Info-AquaSKKInputMethod.plist:1.4 AquaSKK/Info-AquaSKKInputMethod.plist:1.4.2.1
--- AquaSKK/Info-AquaSKKInputMethod.plist:1.4	Mon Dec 19 23:46:44 2005
+++ AquaSKK/Info-AquaSKKInputMethod.plist	Sun Jan  8 16:15:30 2006
@@ -26,6 +26,8 @@
 	<string>2005-12-19</string>
 	<key>CSResourcesFileMapped</key>
 	<true/>
+	<key>tsInputMethodIconFileKey</key>
+	<string>AquaSKK-InputMethod.tif</string>
 	<key>ComponentInputModeDict</key>
 	<dict>
 		<key>tsInputModeListKey</key>
Index: AquaSKK/PreferencesController.h
diff -u AquaSKK/PreferencesController.h:1.6.2.1 AquaSKK/PreferencesController.h:1.6.2.2
--- AquaSKK/PreferencesController.h:1.6.2.1	Sat Jan  7 16:22:29 2006
+++ AquaSKK/PreferencesController.h	Sun Jan  8 16:15:30 2006
@@ -1,11 +1,10 @@
 /* -*- objc -*-
-  $Id: PreferencesController.h,v 1.6.2.1 2006/01/07 07:22:29 t-suwa Exp $
-  ---------
-	
+  $Id: PreferencesController.h,v 1.6.2.2 2006/01/08 07:15:30 t-suwa Exp $
+
   MacOS X implementation of the SKK input method.
 
   Copyright (C) 2002 phonohawk
-  Copyright (C) 2005 Tomotaka SUWA <t.suw****@mac*****>
+  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
@@ -76,8 +75,6 @@
 - (NSColor *)windowColor;
 - (float)windowAlpha;
 
-- (NSDictionary*)makeKbdDictionary:(KeyboardLayoutRef)kbd;
-- (void)initKbdLayoutPopUp;
 - (int)kbdLayoutId;
 - (IBAction)changeKbdLayoutId:(id)sender;
 - (BOOL)isSkkEggLikeNewline;
@@ -87,8 +84,6 @@
 - (BOOL)isAsciiModeStartup;
 - (IBAction)asciiModeStartup:(id)sender;
 
-- (void)setState:(SInt32)msgID state:(int)state;
-
 - (NSArray *)path;
 
 - (IBAction)selectMainDic:(id)sender;
Index: AquaSKK/PreferencesController.mm
diff -u AquaSKK/PreferencesController.mm:1.6.2.1 AquaSKK/PreferencesController.mm:1.6.2.2
--- AquaSKK/PreferencesController.mm:1.6.2.1	Sat Jan  7 16:22:29 2006
+++ AquaSKK/PreferencesController.mm	Sun Jan  8 16:15:30 2006
@@ -1,10 +1,10 @@
 /*  -*- objc -*-
-  $Id: PreferencesController.mm,v 1.6.2.1 2006/01/07 07:22:29 t-suwa Exp $
+  $Id: PreferencesController.mm,v 1.6.2.2 2006/01/08 07:15:30 t-suwa Exp $
 
   MacOS X implementation of the SKK input method.
 
   Copyright (C) 2002 phonohawk
-  Copyright (C) 2005 Tomotaka SUWA <t.suw****@mac*****>
+  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
@@ -66,6 +66,82 @@
 
 @implementation PreferencesController
 
+- (NSDictionary*)makeKbdDictionary:(KeyboardLayoutRef)kbd {
+    KeyboardLayoutIdentifier kbdId;
+    CFStringRef name;
+    IconRef icon = NULL;
+    NSImage* image = NULL;
+
+    NSMutableDictionary* kbdDict = [[[NSMutableDictionary alloc] init] autorelease];
+
+    // ƒL[ƒ{[ƒh‚Ì ID ‚Æ–¼‘OAƒAƒCƒRƒ“‚ðŽæ“¾‚·‚é
+    KLGetKeyboardLayoutProperty(kbd, kKLIdentifier, (const void**)&kbdId);
+    KLGetKeyboardLayoutProperty(kbd, kKLLocalizedName, (const void**)&name);
+    KLGetKeyboardLayoutProperty(kbd, kKLIcon, (const void**)&icon);
+
+    // IconRef ¨ NSImage •ÏŠ·
+    if(icon) {
+	IconFamilyHandle iconFamily;
+	NSData* iconData;
+
+	IconRefToIconFamily(icon, kSelectorAllAvailableData, &iconFamily);
+	iconData = [NSData dataWithBytes: *iconFamily length: iconFamily[0]->resourceSize];
+	image = [[[NSImage alloc] initWithData:iconData] autorelease];
+    }
+
+    [kbdDict setObject:[NSNumber numberWithInt:kbdId] forKey:KbdIdKey];
+    [kbdDict setObject:(NSString*)name forKey:KbdNameKey];
+    [kbdDict setObject:image forKey:KbdIconKey];
+
+    return kbdDict;
+}
+
+- (void)initKbdLayoutPopUp {
+    CFIndex count;
+    KeyboardLayoutRef kbd;
+    SInt32 groupId;
+    NSMutableArray* kbdArray = [[[NSMutableArray alloc] init] autorelease];
+
+    // ƒXƒNƒŠƒvƒg‚ª smRoman ‚Å‚ ‚éƒL[ƒ{[ƒhƒŒƒCƒAƒEƒg‚ð‘S‚Ď擾‚·‚é
+    KLGetKeyboardLayoutCount(&count);
+    for(CFIndex i = 0; i < count; ++ i) {
+	KLGetKeyboardLayoutAtIndex(i, &kbd);
+	KLGetKeyboardLayoutProperty(kbd, kKLGroupIdentifier, (const void**)&groupId);
+	if(groupId != smRoman) continue;
+
+	// ID ‚Æ–¼‘O‚ÌŽ«‘‚ð’ljÁ‚·‚é
+	[kbdArray addObject:[self makeKbdDictionary:kbd]];
+    }
+
+    // ƒŒƒCƒAƒEƒg–¼‚Ń\[ƒg‚·‚é
+    NSSortDescriptor* localizedNameDescriptor = [[NSSortDescriptor alloc] initWithKey:KbdNameKey ascending:YES];
+    [localizedNameDescriptor autorelease];
+    NSArray* sortDescriptors = [NSArray arrayWithObject:localizedNameDescriptor];
+    NSArray* sortedArray = [kbdArray sortedArrayUsingDescriptors:sortDescriptors];
+
+    // ƒƒjƒ…[‚ð\’z‚µ‚āAPopUpButton ‚É“\‚è•t‚¯‚é
+    kbdLayoutMenu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
+    NSEnumerator* enumerator = [sortedArray objectEnumerator];
+    NSDictionary* dict;
+    while(dict = [enumerator nextObject]) {
+	[kbdLayoutMenu addItemWithTitle:[dict objectForKey:KbdNameKey] action:nil keyEquivalent:@""];
+	NSMenuItem* item = [kbdLayoutMenu itemWithTitle:[dict objectForKey:KbdNameKey]];
+	[item setTag:[[dict objectForKey:KbdIdKey] intValue]];
+	[item setImage:[dict objectForKey:KbdIconKey]];
+    }
+    [kbdLayoutPopUp setMenu:kbdLayoutMenu];
+}
+
+- (void)setState:(SInt32)msgID state:(int)state {
+    bool boolState = state ? true : false;
+
+    CppCFData data(&boolState, sizeof(bool));
+
+    ClientConnectionFactory::theInstance().newConnection().send(msgID, data);
+
+    [self saveUserDefault:self];
+}
+
 + (PreferencesController*)sharedController {
     static PreferencesController* _shared_instance = nil;
     if(_shared_instance == nil) {
@@ -79,7 +155,7 @@
     [self window];
 
     // ƒŒƒxƒ‹•ÏXFƒtƒ[ƒeƒBƒ“ƒO
-    [[self window] setLevel:NSFloatingWindowLevel];
+    //[[self window] setLevel:NSPopUpMenuWindowLevel];
 
     // o‰×ŽžÝ’è‚̏‰Šú‰»
     NSMutableDictionary* templateDefaults = [NSMutableDictionary dictionary];
@@ -192,72 +268,6 @@
     return [winTransparent doubleValue];
 }
 
-- (NSDictionary*)makeKbdDictionary:(KeyboardLayoutRef)kbd {
-    KeyboardLayoutIdentifier kbdId;
-    CFStringRef name;
-    IconRef icon = NULL;
-    NSImage* image = NULL;
-
-    NSMutableDictionary* kbdDict = [[[NSMutableDictionary alloc] init] autorelease];
-
-    // ƒL[ƒ{[ƒh‚Ì ID ‚Æ–¼‘OAƒAƒCƒRƒ“‚ðŽæ“¾‚·‚é
-    KLGetKeyboardLayoutProperty(kbd, kKLIdentifier, (const void**)&kbdId);
-    KLGetKeyboardLayoutProperty(kbd, kKLLocalizedName, (const void**)&name);
-    KLGetKeyboardLayoutProperty(kbd, kKLIcon, (const void**)&icon);
-
-    // IconRef ¨ NSImage •ÏŠ·
-    if(icon) {
-	IconFamilyHandle iconFamily;
-	NSData* iconData;
-
-	IconRefToIconFamily(icon, kSelectorAllAvailableData, &iconFamily);
-	iconData = [NSData dataWithBytes: *iconFamily length: iconFamily[0]->resourceSize];
-	image = [[[NSImage alloc] initWithData:iconData] autorelease];
-    }
-
-    [kbdDict setObject:[NSNumber numberWithInt:kbdId] forKey:KbdIdKey];
-    [kbdDict setObject:(NSString*)name forKey:KbdNameKey];
-    [kbdDict setObject:image forKey:KbdIconKey];
-
-    return kbdDict;
-}
-
-- (void)initKbdLayoutPopUp {
-    CFIndex count;
-    KeyboardLayoutRef kbd;
-    SInt32 groupId;
-    NSMutableArray* kbdArray = [[[NSMutableArray alloc] init] autorelease];
-
-    // ƒXƒNƒŠƒvƒg‚ª smRoman ‚Å‚ ‚éƒL[ƒ{[ƒhƒŒƒCƒAƒEƒg‚ð‘S‚Ď擾‚·‚é
-    KLGetKeyboardLayoutCount(&count);
-    for(CFIndex i = 0; i < count; ++ i) {
-	KLGetKeyboardLayoutAtIndex(i, &kbd);
-	KLGetKeyboardLayoutProperty(kbd, kKLGroupIdentifier, (const void**)&groupId);
-	if(groupId != smRoman) continue;
-
-	// ID ‚Æ–¼‘O‚ÌŽ«‘‚ð’ljÁ‚·‚é
-	[kbdArray addObject:[self makeKbdDictionary:kbd]];
-    }
-
-    // ƒŒƒCƒAƒEƒg–¼‚Ń\[ƒg‚·‚é
-    NSSortDescriptor* localizedNameDescriptor = [[NSSortDescriptor alloc] initWithKey:KbdNameKey ascending:YES];
-    [localizedNameDescriptor autorelease];
-    NSArray* sortDescriptors = [NSArray arrayWithObject:localizedNameDescriptor];
-    NSArray* sortedArray = [kbdArray sortedArrayUsingDescriptors:sortDescriptors];
-
-    // ƒƒjƒ…[‚ð\’z‚µ‚āAPopUpButton ‚É“\‚è•t‚¯‚é
-    kbdLayoutMenu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
-    NSEnumerator* enumerator = [sortedArray objectEnumerator];
-    NSDictionary* dict;
-    while(dict = [enumerator nextObject]) {
-	[kbdLayoutMenu addItemWithTitle:[dict objectForKey:KbdNameKey] action:nil keyEquivalent:@""];
-	NSMenuItem* item = [kbdLayoutMenu itemWithTitle:[dict objectForKey:KbdNameKey]];
-	[item setTag:[[dict objectForKey:KbdIdKey] intValue]];
-	[item setImage:[dict objectForKey:KbdIconKey]];
-    }
-    [kbdLayoutPopUp setMenu:kbdLayoutMenu];
-}
-
 - (int)kbdLayoutId {
     return [[kbdLayoutPopUp selectedItem] tag];
 }
@@ -295,16 +305,6 @@
     [self setState:kBasicMessageIsAsciiModeStartup state:[sender state]];
 }
 
-- (void)setState:(SInt32)msgID state:(int)state {
-    bool boolState = state ? true : false;
-
-    CppCFData data(&boolState, sizeof(bool));
-
-    ClientConnectionFactory::theInstance().newConnection().send(msgID, data);
-
-    [self saveUserDefault:self];
-}
-
 // SKKŽ«‘
 
 - (NSString*)getPathToMainDic {
Index: AquaSKK/PrivateRunLoop.mm
diff -u AquaSKK/PrivateRunLoop.mm:1.2 AquaSKK/PrivateRunLoop.mm:1.2.2.1
--- AquaSKK/PrivateRunLoop.mm:1.2	Sat Oct  8 00:08:36 2005
+++ AquaSKK/PrivateRunLoop.mm	Sun Jan  8 16:15:30 2006
@@ -1,9 +1,9 @@
 /* -*- objc -*-
-  $Id: PrivateRunLoop.mm,v 1.2 2005/10/07 15:08:36 t-suwa Exp $
+  $Id: PrivateRunLoop.mm,v 1.2.2.1 2006/01/08 07:15:30 t-suwa Exp $
 
   MacOS X implementation of the SKK input method.
 
-  Copyright (C) 2005 Tomotaka SUWA <t.suw****@mac*****>
+  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
@@ -26,10 +26,7 @@
 #include <CoreServices/CoreServices.h>
 #include "PrivateRunLoop.h"
 
-PrivateRunLoop::PrivateRunLoop(
-    const CFStringRef mode, CFRunLoopSourceRef runLoopSource)
-    : mode_(mode), runLoop_(0)
-{
+PrivateRunLoop::PrivateRunLoop(const CFStringRef mode, CFRunLoopSourceRef runLoopSource) : mode_(mode), runLoop_(0) {
     // •ÛŽ
     runLoopSource_ = (CFRunLoopSourceRef)CFRetain(runLoopSource);
 
@@ -37,18 +34,10 @@
     MPCreateQueue(&notifyQueue_);
 
     // ƒ^ƒXƒN‚𑖂点‚é
-    MPCreateTask(PrivateRunLoop::entryPoint,
-		 this,
-		 0,
-		 notifyQueue_,
-		 NULL,
-		 NULL,
-		 0,
-		 &taskID_);
+    MPCreateTask(PrivateRunLoop::entryPoint, this, 0, notifyQueue_, NULL, NULL, 0, &taskID_);
 }
 
-PrivateRunLoop::~PrivateRunLoop()
-{
+PrivateRunLoop::~PrivateRunLoop() {
     // ƒ^ƒXƒN‚ðŽ~‚ß‚é
     CFRunLoopStop(runLoop_);
 
@@ -61,29 +50,24 @@
 }
 
 // ƒ^ƒXƒN–{‘Ì
-OSStatus PrivateRunLoop::entryPoint(void* param)
-{
+OSStatus PrivateRunLoop::entryPoint(void* param) {
     // autorelease pool ‚ð‰Šú‰»‚µ‚È‚¢‚ƁAƒƒ‚ƒŠƒŠ[ƒN‚µ‚Ä‚µ‚Ü‚¤
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 
-    PrivateRunLoop* self = (PrivateRunLoop*)param;
-    self->runLoop_ = CFRunLoopGetCurrent();
+    PrivateRunLoop* me = (PrivateRunLoop*)param;
+    me->runLoop_ = CFRunLoopGetCurrent();
 
     // ŠÄŽ‹‘Ώۂð’ljÁ
-    CFRunLoopAddSource(self->runLoop_,
-		       self->runLoopSource_,
-		       self->mode_);
+    CFRunLoopAddSource(me->runLoop_, me->runLoopSource_, me->mode_);
 
     // CFRunLoopStop() ‚ªŒÄ‚΂ê‚é‚܂ŃCƒxƒ“ƒg‚ðˆ—‚·‚é
     SInt32 result;
     do {
-	result = CFRunLoopRunInMode(self->mode_, 1, true);
+	result = CFRunLoopRunInMode(me->mode_, 1, true);
     } while(result != kCFRunLoopRunStopped);
 
     // ŒãŽn––
-    CFRunLoopRemoveSource(self->runLoop_,
-			  self->runLoopSource_,
-			  self->mode_);
+    CFRunLoopRemoveSource(me->runLoop_, me->runLoopSource_, me->mode_);
 
     [pool release];
 
Index: AquaSKK/SKKDictionary.cpp
diff -u AquaSKK/SKKDictionary.cpp:1.6 AquaSKK/SKKDictionary.cpp:1.6.2.1
--- AquaSKK/SKKDictionary.cpp:1.6	Tue Nov 15 00:37:13 2005
+++ AquaSKK/SKKDictionary.cpp	Sun Jan  8 16:15:30 2006
@@ -1,10 +1,10 @@
 /*
-  $Id: SKKDictionary.cpp,v 1.6 2005/11/14 15:37:13 t-suwa Exp $
+  $Id: SKKDictionary.cpp,v 1.6.2.1 2006/01/08 07:15:30 t-suwa Exp $
 
   MacOS X implementation of the SKK input method.
 
   Copyright (C) 2002 phonohawk
-  Copyright (C) 2005 Tomotaka SUWA <t.suw****@mac*****>
+  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
@@ -21,567 +21,409 @@
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
-#include <CoreFoundation/CoreFoundation.h>
-#include <map>
-#include <vector>
 #include <iostream>
 #include <fstream>
-#include <cerrno>
-#include <cstring>
+#include <algorithm>
+#include <numeric>
 #include <ctime>
-#include <unistd.h>
-#include <pthread.h>
+#include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include "CppCFString.h"
 #include "OkuriganaEntry.h"
 #include "Dictionary.h"
 #include "SKKDictionary.h"
+#include "SKKConfig.h"
 
-// “à•”ŠÖ”
-static void parseOkuriAriEntry(const CppCFString& line, CppCFString& index,
-			       std::vector<OkuriganaEntry>& entries);
-
-static void parseOkuriNasiEntry(const CppCFString& line, CppCFString& index,
-				std::vector<CppCFString>& entries);
-
-SKKDictionary::SKKDictionary(const std::string& fpath) : fpath_(fpath) {
-    load();
-}
-
-SKKDictionary::~SKKDictionary() {
-    close();
-}
-
-void SKKDictionary::changeDictionaryFile(const std::string& fpath) {
-    close();
-    fpath_ = fpath;
-    load();
-}
+#pragma mark --- SKK common functions ---
 
-void SKKDictionary::load() {
-    struct stat st;
-    if(stat(fpath_.c_str(), &st) < 0) {
-	std::cerr << "AquaSKK: stat(" << fpath_ << ") failed: "
-		  << std::strerror(errno) << std::endl;
-	return;
-    }
+// SKKDictionary ‚Æ SKKUserDictionary ‚É‹¤’Ê‚·‚é’萔‚â‘€ì
+namespace skkdic {
+    const std::string OkuriAriMark = ";; okuri-ari entries.";
+    const std::string OkuriNasiMark = ";; okuri-nasi entries.";
+    const int SAVE_LIMIT_COUNT = 50;
+    const int SAVE_TIMEOUT = 10 * 60; // 10 •ª
 
-    // ’ʏí‚̃tƒ@ƒCƒ‹‚Å‚Í‚È‚¢H
-    if(!S_ISREG(st.st_mode)) {
-	std::cerr << "AquaSKK: [" << fpath_ << "] is NOT regular file."
-		  << std::endl;
-	return;
-    }
+    // Ž«‘ƒtƒ@ƒCƒ‹‚ðŠJ‚¢‚āAokuri-ari ‚̐擪‚܂ŃV[ƒN‚·‚é
+    bool OpenAndSeek(const std::string& path, std::ifstream& dic) {
+	// Ž«‘‚̃Xƒe[ƒ^ƒX‚ðŽæ“¾
+	struct stat st;
+	if(stat(path.c_str(), &st) < 0) {
+	    std::cerr << __FUNCTION__ << ": stat() failed" << std::endl;
+	    return false;
+	}
 
-    std::ifstream dic(fpath_.c_str());
-    if(!dic) {
-	return;
-    }
+	// ƒŒƒMƒ…ƒ‰[ƒtƒ@ƒCƒ‹ˆÈŠOH
+	if(!S_ISREG(st.st_mode)) {
+	    std::cerr << __FUNCTION__ << ": [" << path << "] is NOT regular file" << std::endl;
+	    return false;
+	}
 
-    std::string str_line;
-    while(!dic.eof()) {
-	std::getline(dic, str_line);
-	if(str_line == ";; okuri-ari entries.") break;
-    }
+	dic.open(path.c_str());
+	if(!dic) {
+	    std::cerr << __FUNCTION__ << ": [" << path << "] ifstream.open() failed" << std::endl;
+	    return false;
+	}
 
-    // ‘—‚è‚ ‚èƒGƒ“ƒgƒŠ
-    while(!dic.eof()) {
-	std::getline(dic, str_line);
-	if(str_line.length() == 0) continue;
-	if(str_line == ";; okuri-nasi entries.") break;
-	if(str_line[0] == ';') continue;
-		
-	okuri_ari_unparsed.push_back(str_line);
-    }
+	// ‘—‚è‚ ‚èƒGƒ“ƒgƒŠ‚ÌŽn‚Ü‚è‚ð’T‚·
+	std::string line;
+	while(!dic.eof()) {
+	    std::getline(dic, line);
+	    if(skkdic::OkuriAriMark.find(line) == 0) break;
+	}
 
-    // ‘—‚è‚È‚µƒGƒ“ƒgƒŠ
-    while(!dic.eof()) {
-	std::getline(dic, str_line);
-	if(str_line.length() == 0) continue;
-	if(str_line[0] == ';') continue;
-		
-	okuri_nasi_unparsed.push_back(str_line);
+	return true;
     }
 
-    // ƒp[ƒTƒXƒŒƒbƒh‚ð‹N“®‚·‚é
-    pthread_t parser;
-    pthread_create(&parser, NULL, SKKDictionary::parserThreadRoutine, this);
-    pthread_detach(parser);
-}
+    // SKKPair ‚ð”äŠr‚·‚éƒtƒ@ƒ“ƒNƒ^(Effective STL, p.99)
+    class EntryCompare {
+	bool keyLess(const SKKPair::first_type& k1, const SKKPair::first_type& k2) const {
+	    return k1 < k2;
+	}
 
-int SKKDictionary::countOkuriAri() {
-    return okuri_ari_table.size();
-}
+    public:
+	// ƒ\[ƒg—p”äŠrŠÖ”
+	bool operator()(const SKKPair& lhs, const SKKPair& rhs) const {
+	    return keyLess(lhs.first, rhs.first);
+	}
+	// ’Tõ—p”äŠrŠÖ”(‚»‚Ì1)
+	bool operator()(const SKKPair& lhs, const SKKPair::first_type& k) const {
+	    return keyLess(lhs.first, k);
+	}
+	// ’Tõ—p”äŠrŠÖ”(‚»‚Ì2)
+	bool operator()(const SKKPair::first_type& k, const SKKPair& rhs) const {
+	    return keyLess(k, rhs.first);
+	}
+    };
 
-int SKKDictionary::countOkuriNasi() {
-    return okuri_nasi_table.size();
-}
+    // SKKPair ‚Æ•¶Žš—ñ‚ð”äŠr‚·‚éƒtƒ@ƒ“ƒNƒ^
+    class UserEntryCompare: public std::unary_function<SKKPair, bool> {
+	const std::string str_;
 
-std::vector<OkuriganaEntry>
-SKKDictionary::findOkuriAri(const CppCFString& query) {
-    // Œ©‚‚©‚Á‚½H
-    if(okuri_ari_table.find(query) != okuri_ari_table.end()) {
-	return *okuri_ari_table[query];
-    }
+    public:
+	UserEntryCompare(const CppCFString& str) : str_(str.toStdString()) {}
+	bool operator()(const SKKPair& pair) const {
+	    return pair.first == str_;
+	}
+    };
 
-    // ƒGƒ“ƒgƒŠŽ©‘Ì‘¶Ý‚µ‚È‚¢‚©A‚Ü‚¾ƒp[ƒX‚³‚ê‚Ä‚¢‚È‚¢B
-    for(unsigned i = 0; i < okuri_ari_unparsed.size(); ++ i) {
-	CppCFString line(okuri_ari_unparsed[i].c_str(),
-			 kCFStringEncodingEUC_JP); // EUC-JP
+    // Ž«‘‚ð•Û‘¶‚·‚éƒtƒ@ƒ“ƒNƒ^
+    class Store {
+	std::ofstream& ofs_;
 
-	if(line.startsWith(query)) {
-	    CppCFString index;
-	    std::vector<OkuriganaEntry> entries;
+    public:
+	Store(std::ofstream& ofs) : ofs_(ofs) {}
+	void operator()(const SKKPair& pair) {
+	    ofs_ << pair.first << " " << pair.second << std::endl;
+	}
+    };
 
-	    parseOkuriAriEntry(line, index, entries);
+    // SKKEntry ¨ std::vector<OkuriganaEntry> •ÏŠ·
+    std::vector<OkuriganaEntry> ConvertOkuriAri(const SKKEntry& entry) {
+	// ‚Ü‚¸ƒqƒ“ƒgî•ñ‚©‚ç’ljÁ‚·‚é
+	std::vector<OkuriganaEntry> result;
+	for(SKKOkuriHint hint = entry.FirstHint(); !hint.IsEmpty(); hint = entry.NextHint()) {
+	    OkuriganaEntry okuri;
 
-	    return entries;
+	    okuri.setKana(CppCFString(hint.Kana().c_str(), kCFStringEncodingEUC_JP));
+	    for(SKKCandidate candidate = hint.First(); !candidate.IsEmpty(); candidate = hint.Next()) {
+		okuri.add(CppCFString(candidate.Description().c_str(), kCFStringEncodingEUC_JP));
+	    }
+	    result.push_back(okuri);
 	}
-    }
 
-    // ‘¶Ý‚µ‚È‚¯‚ê‚΋ó‚Ì vector ‚ð•Ô‚·
-    return std::vector<OkuriganaEntry>();
-}
+	// ŽŸ‚ɁA•ÏŠ·Œó•â‚ð’ljÁ‚·‚é
+	OkuriganaEntry wild;
+	for(SKKCandidate candidate = entry.First(); !candidate.IsEmpty(); candidate = entry.Next()) {
+	    wild.add(CppCFString(candidate.Description().c_str(), kCFStringEncodingEUC_JP));
+	}
+	result.push_back(wild);
 
-std::vector<CppCFString>
-SKKDictionary::findOkuriNasi(const CppCFString& query) {
-    // Œ©‚‚©‚Á‚½H
-    if(okuri_nasi_table.find(query) != okuri_nasi_table.end()) {
-	return *okuri_nasi_table[query];
+	return result;
     }
 
-    // ƒGƒ“ƒgƒŠŽ©‘Ì‘¶Ý‚µ‚È‚¢‚©A‚Ü‚¾ƒp[ƒX‚³‚ê‚Ä‚¢‚È‚¢
-    for(unsigned i = 0; i < okuri_nasi_unparsed.size() ; ++ i) {
-	CppCFString line(okuri_nasi_unparsed[i].c_str(),
-			 kCFStringEncodingEUC_JP); // EUC-JP
+    // SKKEntry ¨ std::vector<CppCFString> •ÏŠ·
+    std::vector<CppCFString> ConvertOkuriNasi(const SKKEntry& entry) {
+	return CppCFString(entry.Candidate().c_str(), kCFStringEncodingEUC_JP).split('/');
+    }
+};
 
-	if(line.startsWith(query)) {
-	    CppCFString index;
-	    std::vector<CppCFString> entries;
+#pragma mark --- SKKDictionary ---
 
-	    parseOkuriNasiEntry(line, index, entries);
+SKKDictionary::SKKDictionary(const std::string& path) : path_(path) {
+    load();
+}
 
-	    return entries;
-	}
-    }
+SKKDictionary::~SKKDictionary() {
+    // empty
+}
 
-    // ‘¶Ý‚µ‚È‚¯‚ê‚΋ó‚Ì vector ‚ð•Ô‚·
-    return std::vector<CppCFString>();
+int SKKDictionary::countOkuriAri() {
+    return okuriAri_.size();
 }
 
-void SKKDictionary::parseAll() {
-    // @‚±‚̃ƒ\ƒbƒh‚́A‘—‚è—L‚èƒGƒ“ƒgƒŠŒQ‚Æ‘—‚è–³‚µƒGƒ“ƒgƒŠŒQ‚ð
-    // Œã‚ë‚©‚çˆê‚‚¸‚ƒp[ƒX‚µ‚Ä‚¢‚«Aunparsed‚Ìvector‚©‚ç‚͏Á‚µ‚čs‚­B
-    // ‘O‚©‚ç‚Å‚È‚¢——R‚́A‘O‚̍€–Ú‚ðÁ‚µ‚½Žž‚ÉŒã‚ë‚É‚ ‚鍀–Ú‚ð
-    // ‘O‚É‚¸‚炳‚ê‚Ä‚µ‚Ü‚¤‚©‚à’m‚ê‚È‚¢ˆ×‚Å‚ ‚éB‚¸‚ç‚·‚É‚Í—]Œv‚ÈŽžŠÔ‚ª‚©‚©‚éB
-    // @‚È‚¨A‚±‚̃ƒ\ƒbƒh‚Íload()‚ªŠ®—¹‚·‚é‘O‚ɌĂñ‚Å‚Í‚È‚ç‚È‚¢B
-	
-    // ‘—‚è—L‚èƒGƒ“ƒgƒŠ
-    for(std::vector<std::string>::iterator ite = okuri_ari_unparsed.end()-1;
-	okuri_ari_unparsed.size() > 0; ite --) {
-	CppCFString line(ite->c_str(), kCFStringEncodingEUC_JP); // EUC-JP
-	CppCFString index;
-	std::vector<OkuriganaEntry> entries;
+int SKKDictionary::countOkuriNasi() {
+    return okuriNasi_.size();
+}
 
-	parseOkuriAriEntry(line, index, entries);
+std::vector<OkuriganaEntry> SKKDictionary::findOkuriAri(const CppCFString& query) {
+    std::string index = query.toStdString();
 
-	std::vector<OkuriganaEntry>* candidates = okuri_ari_table[index];
-	if(candidates == NULL) {
-	    candidates = new std::vector<OkuriganaEntry>;
-	    okuri_ari_table[index] = candidates;
-	}
-	candidates->insert(candidates->end(), entries.begin(), entries.end());
-	okuri_ari_unparsed.erase(ite);
+    // Œ©•t‚©‚ç‚È‚¢H
+    if(!std::binary_search(okuriAri_.begin(), okuriAri_.end(), index, skkdic::EntryCompare())) {
+	return std::vector<OkuriganaEntry>();
     }
-	
-    // ‘—‚è–³‚µƒGƒ“ƒgƒŠ
-    for(std::vector<std::string>::iterator ite = okuri_nasi_unparsed.end()-1;
-	okuri_nasi_unparsed.size() > 0; ite --) {
-	CppCFString line(ite->c_str(),kCFStringEncodingEUC_JP); // EUC-JP
-	CppCFString index;
-	std::vector<CppCFString> entries;
 
-	parseOkuriNasiEntry(line, index, entries);
+    EntryIterator i = std::lower_bound(okuriAri_.begin(), okuriAri_.end(), index, skkdic::EntryCompare());
 
-	std::vector<CppCFString>* candidates = okuri_nasi_table[index];
-	if(candidates == NULL) {
-	    candidates = new std::vector<CppCFString>;
-	    okuri_nasi_table[index] = candidates;
-	}
-	candidates->insert(candidates->end(), entries.begin(), entries.end());
-	okuri_nasi_unparsed.erase(ite);
-    }
-    std::cerr << "SKK Dictionary(" << fpath_ << ")" << std::endl
-	      << "  okuri-ari: " << countOkuriAri() << " entries."
-	      << std::endl
-	      << "  okuri-nasi: " << countOkuriNasi() << " entries."
-	      << std::endl << std::endl;
+    return skkdic::ConvertOkuriAri(SKKEntry::ParseOkuriAri(i->first, i->second));
 }
 
-void SKKDictionary::close() {
-    std::map<CppCFString, std::vector<OkuriganaEntry>*>::iterator i;
-    for(i = okuri_ari_table.begin(); i != okuri_ari_table.end(); ++ i) {
-	delete i->second;
-    }
-    std::map<CppCFString, std::vector<CppCFString>*>::iterator j;
-    for(j = okuri_nasi_table.begin(); j != okuri_nasi_table.end(); ++ j) {
-	delete j->second;
+std::vector<CppCFString> SKKDictionary::findOkuriNasi(const CppCFString& query) {
+    std::string index = query.toStdString();
+
+    // Œ©‚‚©‚ç‚È‚¢H
+    if(!std::binary_search(okuriNasi_.begin(), okuriNasi_.end(), index, skkdic::EntryCompare())) {
+	return std::vector<CppCFString>();
     }
 
-    std::map<CppCFString, std::vector<OkuriganaEntry>*>().swap(okuri_ari_table);
-    std::map<CppCFString, std::vector<CppCFString>*>().swap(okuri_nasi_table);
-    std::vector<std::string>().swap(okuri_ari_unparsed);
-    std::vector<std::string>().swap(okuri_nasi_unparsed);
-}
+    EntryIterator i = std::lower_bound(okuriNasi_.begin(), okuriNasi_.end(), index, skkdic::EntryCompare());
 
-void* SKKDictionary::parserThreadRoutine(void* dic) {
-    static_cast<SKKDictionary*>(dic)->parseAll();
-    return NULL;
+    return skkdic::ConvertOkuriNasi(SKKEntry::ParseOkuriNasi(i->first, i->second));
 }
 
-// ------------------------------------------------------------------
-
-// ƒ†[ƒU[Ž«‘‚ð•Û‘¶‚·‚ׂ«XV‰ñ”‚Ì臒l
-const int SKK_JISYO_SAVE_COUNT = 50;
+void SKKDictionary::changeDictionaryFile(const std::string& path) {
+    EntryContainer().swap(okuriAri_);
+    EntryContainer().swap(okuriNasi_);
 
-// ƒ†[ƒU[Ž«‘‚ð•Û‘¶‚·‚ׂ«XVŠÔŠu‚Ì臒l(10 •ª)
-const int SKK_JISYO_SAVE_TIMEOUT = 10 * 60;
+    path_ = path;
 
-SKKUserDictionary::SKKUserDictionary(const std::string& fpath) : fpath_(fpath) {
     load();
 }
 
-SKKUserDictionary::~SKKUserDictionary() {
-    // ‹­§“I‚ÉŽ«‘‚ð•Û‘¶‚·‚é
-    save(true);
-
-    std::map<CppCFString, std::vector<OkuriganaEntry>*>::iterator i;
-    for(i = okuri_ari_table.begin(); i != okuri_ari_table.end(); ++ i) {
-	delete i->second;
-    }
-    std::map<CppCFString, std::vector<CppCFString>*>::iterator j;
-    for(j = okuri_nasi_table.begin(); j != okuri_nasi_table.end(); ++ j) {
-	delete j->second;
-    }
-}
+void SKKDictionary::load() {
+    std::string line;
+    std::string index;
+    std::string entry;
+    std::ifstream dic;
 
-void SKKUserDictionary::load() {
-    struct stat st;
-    if(stat(fpath_.c_str(), &st) < 0) {
-	std::cerr << "AquaSKK: stat(" << fpath_ << ") failed: "
-		  << std::strerror(errno) << std::endl;
+    if(!skkdic::OpenAndSeek(path_, dic)) {
 	return;
     }
 
-    // ’ʏí‚̃tƒ@ƒCƒ‹‚Å‚Í‚È‚¢H
-    if(!S_ISREG(st.st_mode)) {
-	std::cerr << "AquaSKK: [" << fpath_ << "] is NOT regular file."
-		  << std::endl;
-	return;
-    }
+    while(1) {
+	dic >> index;
+	if(dic.eof()) break;
+	dic.ignore(1, ' ');
+	std::getline(dic, line);
+	if(skkdic::OkuriNasiMark.find(line) != std::string::npos) break;
 
-    std::ifstream dic(fpath_.c_str());
-    if(!dic) {
-	return;
+	// ‘—‚è‚È‚µƒGƒ“ƒgƒŠ‚͍~‡‚Ń\[ƒg‚³‚ê‚Ä‚¢‚é‚Í‚¸
+	okuriAri_.push_front(SKKPair(index, line));
     }
 
-    std::string str_line;
-    while(!dic.eof()) {
-	std::getline(dic, str_line);
-	if(str_line == ";; okuri-ari entries.") break;
-    }
+    while(1) {
+	dic >> index;
+	if(dic.eof()) break;
+	dic.ignore(1, ' ');
+	std::getline(dic, line);
 
-    // ‘—‚è‚ ‚èƒGƒ“ƒgƒŠ
-    while(!dic.eof()) {
-	std::getline(dic, str_line);
-	if(str_line.length() == 0) continue;
-	if(str_line == ";; okuri-nasi entries.") break;
-	if(str_line[0] == ';') continue;
-		
-	okuri_ari_unparsed.push_back(str_line);
+	// ‘—‚è‚ ‚èƒGƒ“ƒgƒŠ‚͏¸‡‚Ń\[ƒg‚³‚ê‚Ä‚¢‚é‚Í‚¸
+	okuriNasi_.push_back(SKKPair(index, line));
     }
 
-    // ‘—‚è‚È‚µƒGƒ“ƒgƒŠ
-    while(!dic.eof()) {
-	std::getline(dic, str_line);
-	if(str_line.length() == 0) continue;
-	if(str_line[0] == ';') continue;
-		
-	okuri_nasi_unparsed.push_back(str_line);
-    }
+    // ƒGƒ“ƒgƒŠ‚ðƒ\[ƒg‚·‚é
+    std::sort(okuriAri_.begin(), okuriAri_.end(), skkdic::EntryCompare());
+    std::sort(okuriNasi_.begin(), okuriNasi_.end(), skkdic::EntryCompare());
 
-    // ‘S‚ăp[ƒX‚·‚é
-    parseAll();
+    std::cerr << "SKK Dictionary(" << path_ << ")" << std::endl
+	      << "  okuri-ari: " << countOkuriAri() << " entries." << std::endl
+	      << "  okuri-nasi: " << countOkuriNasi() << " entries." << std::endl << std::endl;
 }
 
-int SKKUserDictionary::countOkuriAri() {
-    return okuri_ari_table.size();
-}
+#pragma mark --- SKKUserDictionary ---
 
-int SKKUserDictionary::countOkuriNasi() {
-    return okuri_nasi_table.size();
+SKKUserDictionary::SKKUserDictionary(const std::string& path) : path_(path) {
+    load();
 }
 
-std::vector<OkuriganaEntry>
-SKKUserDictionary::findOkuriAri(const CppCFString& query) {
-    // Œ©‚‚©‚Á‚½H
-    if(okuri_ari_table.find(query) != okuri_ari_table.end()) {
-	return *okuri_ari_table[query];
-    }
+SKKUserDictionary::~SKKUserDictionary() {
+    // ‹­§“I‚ÉŽ«‘‚ð•Û‘¶‚·‚é
+    save(true);
+}
 
-    // ƒGƒ“ƒgƒŠŽ©‘Ì‘¶Ý‚µ‚È‚¢‚©A‚Ü‚¾ƒp[ƒX‚³‚ê‚Ä‚¢‚È‚¢B
-    for(unsigned i = 0; i < okuri_ari_unparsed.size(); ++ i) {
-	CppCFString line(okuri_ari_unparsed[i].c_str(),
-			 kCFStringEncodingEUC_JP); // EUC-JP
+int SKKUserDictionary::countOkuriAri() {
+    return okuriAri_.size();
+}
 
-	if(line.startsWith(query)) {
-	    CppCFString index;
-	    std::vector<OkuriganaEntry> entries;
+int SKKUserDictionary::countOkuriNasi() {
+    return okuriNasi_.size();
+}
 
-	    parseOkuriAriEntry(line, index, entries);
+std::vector<OkuriganaEntry> SKKUserDictionary::findOkuriAri(const CppCFString& query) {
+    EntryIterator i = std::find_if(okuriAri_.begin(), okuriAri_.end(), skkdic::UserEntryCompare(query));
 
-	    return entries;
-	}
+    // Œ©‚‚©‚ç‚È‚¢H
+    if(i == okuriAri_.end()) {
+	return std::vector<OkuriganaEntry>();
     }
 
-    // ‘¶Ý‚µ‚È‚¯‚ê‚΋ó‚Ì vector ‚ð•Ô‚·
-    return std::vector<OkuriganaEntry>();
+    return skkdic::ConvertOkuriAri(SKKEntry::ParseOkuriAri(i->first, i->second));
 }
 
-std::vector<CppCFString>
-SKKUserDictionary::findOkuriNasi(const CppCFString& query) {
-    // Œ©‚‚©‚Á‚½H
-    if(okuri_nasi_table.find(query) != okuri_nasi_table.end()) {
-	return *okuri_nasi_table[query];
-    }
+std::vector<CppCFString> SKKUserDictionary::findOkuriNasi(const CppCFString& query) {
+    EntryIterator i = std::find_if(okuriNasi_.begin(), okuriNasi_.end(), skkdic::UserEntryCompare(query));
 
-    // ƒGƒ“ƒgƒŠŽ©‘Ì‘¶Ý‚µ‚È‚¢‚©A‚Ü‚¾ƒp[ƒX‚³‚ê‚Ä‚¢‚È‚¢
-    for(unsigned i = 0; i < okuri_nasi_unparsed.size() ; ++ i) {
-	CppCFString line(okuri_nasi_unparsed[i].c_str(),
-			 kCFStringEncodingEUC_JP); // EUC-JP
-
-	if(line.startsWith(query)) {
-	    CppCFString index;
-	    std::vector<CppCFString> entries;
-
-	    parseOkuriNasiEntry(line, index, entries);
-
-	    return entries;
-	}
+    // Œ©‚‚©‚ç‚È‚¢H
+    if(i == okuriNasi_.end()) {
+	return std::vector<CppCFString>();
     }
 
-    // ‘¶Ý‚µ‚È‚¯‚ê‚΋ó‚Ì vector ‚ð•Ô‚·
-    return std::vector<CppCFString>();
+    return skkdic::ConvertOkuriNasi(SKKEntry::ParseOkuriNasi(i->first, i->second));
 }
 
-std::vector<CppCFString>
-SKKUserDictionary::findCompletions(const CppCFString& query) {
+std::vector<CppCFString> SKKUserDictionary::findCompletions(const CppCFString& query) {
+    std::string index = query.toStdString();
     std::vector<CppCFString> result;
-    const unsigned query_len = query.length();
-
-    // ˆê‚Â‚à‘¶Ý‚µ‚È‚¯‚ê‚΋ó‚Ìvector‚ð•Ô‚·B
-    for(std::map<CppCFString, std::vector<CppCFString>*>::const_iterator ite
-	    = okuri_nasi_table.begin(); ite != okuri_nasi_table.end(); ite ++) {
-	if(ite->first.length() > query_len && ite->first.startsWith(query)) {
-	    // •âŠ®‚ÌðŒ‚ð–ž‚½‚·B
-	    result.push_back(ite->first);
+		 
+    for(EntryIterator i = okuriNasi_.begin(); i != okuriNasi_.end(); ++ i) {
+	// æ“ª•”•ª‚ªˆê’v‚µ‚Ä‚¢‚é‚©H
+	if(i->first.find(index) == 0) {
+	    result.push_back(CppCFString(i->first.c_str(), kCFStringEncodingEUC_JP));
 	}
     }
 
     return result;
 }
 
-void SKKUserDictionary::parseAll() {
-    // @‚±‚̃ƒ\ƒbƒh‚́A‘—‚è—L‚èƒGƒ“ƒgƒŠŒQ‚Æ‘—‚è–³‚µƒGƒ“ƒgƒŠŒQ‚ð
-    // Œã‚ë‚©‚çˆê‚‚¸‚ƒp[ƒX‚µ‚Ä‚¢‚«Aunparsed‚Ìvector‚©‚ç‚͏Á‚µ‚čs‚­B
-    // ‘O‚©‚ç‚Å‚È‚¢——R‚́A‘O‚̍€–Ú‚ðÁ‚µ‚½Žž‚ÉŒã‚ë‚É‚ ‚鍀–Ú‚ð
-    // ‘O‚É‚¸‚炳‚ê‚Ä‚µ‚Ü‚¤‚©‚à’m‚ê‚È‚¢ˆ×‚Å‚ ‚éB‚¸‚ç‚·‚É‚Í—]Œv‚ÈŽžŠÔ‚ª‚©‚©‚éB
-    // @‚È‚¨A‚±‚̃ƒ\ƒbƒh‚Íload()‚ªŠ®—¹‚·‚é‘O‚ɌĂñ‚Å‚Í‚È‚ç‚È‚¢B
-	
-    // ‘—‚è—L‚èƒGƒ“ƒgƒŠ
-    for(std::vector<std::string>::iterator ite = okuri_ari_unparsed.end()-1;
-	okuri_ari_unparsed.size() > 0; ite --) {
-	CppCFString line(ite->c_str(), kCFStringEncodingEUC_JP); // EUC-JP
-	CppCFString index;
-	std::vector<OkuriganaEntry> entries;
-
-	parseOkuriAriEntry(line, index, entries);
-
-	std::vector<OkuriganaEntry>* candidates = okuri_ari_table[index];
-	if(candidates == NULL) {
-	    candidates = new std::vector<OkuriganaEntry>;
-	    okuri_ari_table[index] = candidates;
-	}
-	candidates->insert(candidates->end(), entries.begin(), entries.end());
-	okuri_ari_unparsed.erase(ite);
-    }
-	
-    // ‘—‚è–³‚µƒGƒ“ƒgƒŠ
-    for(std::vector<std::string>::iterator ite = okuri_nasi_unparsed.end() - 1;
-	okuri_nasi_unparsed.size() > 0; ite --) {
-	CppCFString line(ite->c_str(),kCFStringEncodingEUC_JP); // EUC-JP
-	CppCFString index;
-	std::vector<CppCFString> entries;
-
-	parseOkuriNasiEntry(line, index, entries);
-
-	std::vector<CppCFString>* candidates = okuri_nasi_table[index];
-	if(candidates == NULL) {
-	    candidates = new std::vector<CppCFString>;
-	    okuri_nasi_table[index] = candidates;
-	}
-	candidates->insert(candidates->end(), entries.begin(), entries.end());
-	okuri_nasi_unparsed.erase(ite);
-    }
-    std::cerr << "SKK User Dictionary(" << fpath_ << ")" << std::endl
-	      << "  okuri-ari: " << countOkuriAri() << " entries."
-	      << std::endl
-	      << "  okuri-nasi: " << countOkuriNasi() << " entries."
-	      << std::endl << std::endl;
-}
-
-void SKKUserDictionary::registerOkuriAri(const CppCFString& index,
-					 const CppCFString& okuri,
-					 const CppCFString& kanji) {
-    // ‘—‚艼–¼—L‚èB
-    std::vector<OkuriganaEntry>* candidates;
-    if(okuri_ari_table.find(index) == okuri_ari_table.end()) {
-	candidates = new std::vector<OkuriganaEntry>;
-	okuri_ari_table[index] = candidates;
-
-	// Œó•â‚ª–³‚©‚Á‚½ê‡‚̓ƒCƒ‹ƒhƒJ[ƒh‚ÉŠ¿Žš‚ðˆê‚“ü‚ê‚ďI—¹B
-	OkuriganaEntry entry;
-	entry.add(kanji);
-	candidates->push_back(entry);
-    } else {
-	candidates = okuri_ari_table[index];
+void SKKUserDictionary::registerOkuriAri(const CppCFString& index, const CppCFString& okuri, const CppCFString& kanji) {
+    SKKEntry entry = SKKEntry::CreateOkuriAri(index.toStdString());
+    EntryIterator i = std::find_if(okuriAri_.begin(), okuriAri_.end(), skkdic::UserEntryCompare(index));
 
-	// ƒƒCƒ‹ƒhƒJ[ƒh‚̐擪‚É‚»‚ÌŠ¿Žš‚ð’ljÁ‚·‚éB
-	for(std::vector<OkuriganaEntry>::iterator ite = candidates->begin();
-	    ite != candidates->end(); ite ++) {
-	    if(ite->isWild()) {
-		ite->insert(kanji,0);
-		ite->removeRedundantItems();
-		break;
-	    }
-	}
-
-	// “¯‚¶‘—‚艼–¼‚ðŽ‚ÂOkuriganaEntry‚ª–³‚¯‚ê‚΁AƒGƒ“ƒgƒŠ‚ðì‚Á‚Ä
-	// Š¿Žš‚ðˆê‚“ü‚ê‚ďI—¹BŠù‚É‚ ‚ê‚΂»‚̃Gƒ“ƒgƒŠ‚̐擪‚ÉŠ¿Žš‚ð’Ç
-	// ‰Á‚µ‚½ŒãA‚»‚ê‚ðvector‚̐擪‚É’u‚­B
-
-	bool found = false;
-	for(std::vector<OkuriganaEntry>::iterator ite = candidates->begin();
-	    ite != candidates->end(); ite ++) {
-	    if(ite->getKana() == okuri) {
-		found = true;
-		ite->insert(kanji,0);
-		ite->removeRedundantItems(); // d•¡‚ðíœ
-
-		//candidates.swap(candidates.begin(),ite); // æ“ª‚̍€–Ú‚Æ“ü‚ê‘Ö‚¦‚éB
-		OkuriganaEntry entry = *ite;
-		candidates->erase(ite);
-		candidates->insert(candidates->begin(),entry);
-		break;
-	    }
-	}
-
-	if(!found) {
-	    OkuriganaEntry entry(okuri);
-	    entry.add(kanji);
-	    candidates->insert(candidates->begin(),entry);
-	}
+    // Œ©‚‚©‚Á‚½H
+    if(i != okuriAri_.end()) {
+	entry = SKKEntry::ParseOkuriAri(i->first, i->second);
+	okuriAri_.erase(std::remove(okuriAri_.begin(), okuriAri_.end(), *i), okuriAri_.end());
     }
 
-    // •Û‘¶
+    entry.AddOkuriAri(SKKCandidate(kanji.toStdString()), okuri.toStdString());
+    okuriAri_.push_front(SKKPair(entry.Key(), entry.Candidate()));
+
+    // •Û‘¶‚·‚é
     save();
 }
 
-void SKKUserDictionary::registerOkuriNasi(const CppCFString& index,
-					  const CppCFString& kanji) {
-    std::vector<CppCFString>* candidates;
-    if(okuri_nasi_table.find(index) == okuri_nasi_table.end()) {
-	candidates = new std::vector<CppCFString>;
-	okuri_nasi_table[index] = candidates;
-    } else {
-	candidates = okuri_nasi_table[index];
-    }
+void SKKUserDictionary::registerOkuriNasi(const CppCFString& index, const CppCFString& kanji) {
+    SKKEntry entry = SKKEntry::CreateOkuriNasi(index.toStdString());
+    EntryIterator i = std::find_if(okuriNasi_.begin(), okuriNasi_.end(), skkdic::UserEntryCompare(index));
 
-    // Šù‚É‚±‚ÌŠ¿Žš‚ª“o˜^‚³‚ê‚Ä‚¢‚ê‚΁A‚»‚ê‚ðÁ‚·B
-    for(std::vector<CppCFString>::iterator ite = candidates->begin();
-	ite != candidates->end(); ite ++) {
-	if(*ite == kanji) {
-	    candidates->erase(ite);
-	    break;
-	}
+    // Œ©‚‚©‚Á‚½H
+    if(i != okuriNasi_.end()) {
+	entry = SKKEntry::ParseOkuriNasi(i->first, i->second);
+	okuriNasi_.erase(std::remove(okuriNasi_.begin(), okuriNasi_.end(), *i), okuriNasi_.end());
     }
 
-    // æ“ª‚É“ü‚ê‚éB
-    candidates->insert(candidates->begin(),kanji);
+    entry.AddOkuriNasi(SKKCandidate(kanji.toStdString()));
+    okuriNasi_.push_front(SKKPair(entry.Key(), entry.Candidate()));
 
-    // •Û‘¶
+    // •Û‘¶‚·‚é
     save();
 }
 
-void SKKUserDictionary::removeOkuriAri(const CppCFString& index,
-				       const CppCFString& kanji) {
-    // ‘—‚艼–¼‚ ‚è
-    if(okuri_ari_table.find(index) == okuri_ari_table.end()) {
+void SKKUserDictionary::removeOkuriAri(const CppCFString& index, const CppCFString& kanji) {
+    EntryIterator i = std::find_if(okuriAri_.begin(), okuriAri_.end(), skkdic::UserEntryCompare(index));
+
+    // Œ©‚‚©‚ç‚È‚¢H
+    if(i == okuriAri_.end()) {
 	return;
     }
-    
-    std::vector<OkuriganaEntry>* candidates = okuri_ari_table[index];
 
-    // ‘S‚Ä‚ÌOkuriganaEntry‚©‚çAŠ¿Žš‚ªkanji‚Å‚ ‚é‚à‚Ì‚ð’T‚µ‚Ä‚»‚ê‚ðÁ‚·B
-    for(std::vector<OkuriganaEntry>::iterator entry = candidates->begin();
-	entry != candidates->end(); entry ++) {
-	unsigned n_contents = entry->size();
-	for(unsigned i = 0;i < n_contents;i++) {
-	    if((*entry)[i] == kanji) {
-		entry->remove(i);
-		i--;
-		n_contents--;
-	    }
-	}
+    SKKEntry entry = SKKEntry::ParseOkuriAri(i->first, i->second);
+    entry.RemoveOkuriAri(SKKCandidate(kanji.toStdString()));
+
+    // ‚Ü‚¾Œó•â‚ªŽc‚Á‚Ä‚¢‚éH
+    if(entry.Count() > 0) {
+	// ‚±‚̃Gƒ“ƒgƒŠ‚ðXV‚·‚é
+	*i = SKKPair(entry.Key(), entry.Candidate());
+    } else {
+	// ‚±‚̃Gƒ“ƒgƒŠ‚ðÁ‚µ‚Ä‚µ‚Ü‚¤
+	okuriAri_.erase(std::remove(okuriAri_.begin(), okuriAri_.end(), *i), okuriAri_.end());
     }
 
-    // •Û‘¶
+    // •Û‘¶‚·‚é
     save();
 }
 
-void SKKUserDictionary::removeOkuriNasi(const CppCFString& index,
-					const CppCFString& kanji) {
-    if(okuri_nasi_table.find(index) == okuri_nasi_table.end()) {
+void SKKUserDictionary::removeOkuriNasi(const CppCFString& index, const CppCFString& kanji) {
+    EntryIterator i = std::find_if(okuriNasi_.begin(), okuriNasi_.end(), skkdic::UserEntryCompare(index));
+
+    // Œ©‚‚©‚ç‚È‚¢H
+    if(i == okuriNasi_.end()) {
 	return;
     }
 
-    std::vector<CppCFString>* candidates = okuri_nasi_table[index];
+    SKKEntry entry = SKKEntry::ParseOkuriNasi(i->first, i->second);
+    entry.RemoveOkuriNasi(SKKCandidate(kanji.toStdString()));
 
-    unsigned size = candidates->size();
-    for(unsigned i = 0;i < size;i++) {
-	if((*candidates)[i] == kanji) {
-	    candidates->erase(candidates->begin()+i);
-	    i--;
-	    size--;
-	}
+    // ‚Ü‚¾Œó•â‚ªŽc‚Á‚Ä‚¢‚éH
+    if(entry.Count() > 0) {
+	// ‚±‚̃Gƒ“ƒgƒŠ‚ðXV‚·‚é
+	*i = SKKPair(entry.Key(), entry.Candidate());
+    } else {
+	// ‚±‚̃Gƒ“ƒgƒŠ‚ðÁ‚µ‚Ä‚µ‚Ü‚¤
+	okuriNasi_.erase(std::remove(okuriNasi_.begin(), okuriNasi_.end(), *i), okuriNasi_.end());
     }
 
-    // •Û‘¶
+    // •Û‘¶‚·‚é
     save();
 }
 
+// ------------------------------------------------------------------
+
+void SKKUserDictionary::load() {
+    std::string line;
+    std::string index;
+    std::string entry;
+    std::ifstream dic;
+
+    if(!skkdic::OpenAndSeek(path_, dic)) {
+	return;
+    }
+
+    while(1) {
+	dic >> index;
+	if(dic.eof()) break;
+	dic.ignore(1, ' ');
+	std::getline(dic, line);
+	if(skkdic::OkuriNasiMark.find(line) != std::string::npos) break;
+	okuriAri_.push_back(SKKPair(index, line));
+    }
+
+    while(1) {
+	dic >> index;
+	if(dic.eof()) break;
+	dic.ignore(1, ' ');
+	std::getline(dic, line);
+	okuriNasi_.push_back(SKKPair(index, line));
+    }
+
+    std::cerr << "SKK User Dictionary(" << path_ << ")" << std::endl
+	      << "  okuri-ari: " << countOkuriAri() << " entries." << std::endl
+	      << "  okuri-nasi: " << countOkuriNasi() << " entries." << std::endl << std::endl;
+}
+
 void SKKUserDictionary::save(bool force) {
     static int updateCount = 0;
     static std::time_t startOfUpdate = std::time(0);
 
-    // XVƒJƒEƒ“ƒ^[‚ð‰ñ‚·(SKK_JISYO_SAVE_COUNT ‚Ü‚Å‚¢‚­‚Æ 0 ‚ɃŠƒZƒbƒg)
-    updateCount = (updateCount + 1) % SKK_JISYO_SAVE_COUNT;
+    // XVƒJƒEƒ“ƒ^[‚ð‰ñ‚·(SAVE_LIMIT_COUNT ‚Ü‚Å‚¢‚­‚Æ 0 ‚É–ß‚é)
+    updateCount = (updateCount + 1) % skkdic::SAVE_LIMIT_COUNT;
 
     // XVŠJŽn‚©‚çŒo‰ß‚µ‚½ŽžŠÔ‚ðŽZo
-    std::time_t elapsedTime = std::time(0) - startOfUpdate;
+    std::time_t elaspedTime = std::time(0) - startOfUpdate;
 
-    // •Û‘¶‚·‚éƒ^ƒCƒ~ƒ“ƒO‚Å‚Í‚È‚¢H
-    if(!force && updateCount != 0 && elapsedTime < SKK_JISYO_SAVE_TIMEOUT) {
+    // •Û‘¶‚·‚éƒ^ƒCƒ~ƒ“ƒO‚Å‚Í‚È‚¯‚ê‚΁A‰½‚à‚µ‚È‚¢
+    if(!force && updateCount != 0 && elaspedTime < skkdic::SAVE_TIMEOUT) {
 	return;
     }
 
@@ -589,134 +431,27 @@
     updateCount = 0;
     startOfUpdate = std::time(0);
 
-    std::string dic_tmp_path = fpath_ + ".tmp";
-    std::ofstream ofs(dic_tmp_path.c_str());
-    if(!ofs) {
-	std::cerr << "SKKUserDictionary::save(): can't open ["
-		  << dic_tmp_path << "]" << std::endl;
+    // ˆêŽžƒtƒ@ƒCƒ‹‚ðì¬‚·‚é
+    std::string tmpPath = path_ + ".tmp";
+    std::ofstream dic(tmpPath.c_str());
+
+    if(!dic) {
+	std::cerr << __FUNCTION__ << ": [" << tmpPath << "] can't create." << std::endl;
 	return;
     }
 
-    ofs << ";; okuri-ari entries." << std::endl;
-    if (okuri_ari_table.size() > 0) {
-	for(std::map<CppCFString, std::vector<OkuriganaEntry>*>::const_iterator entry = okuri_ari_table.begin();
-	    entry != okuri_ari_table.end(); entry ++) {
-	    if(entry->second == NULL) continue;
-	    if(entry->second->size() == 0) continue;
-
-	    CppCFString line;
-	    line.append(entry->first).append(" /");
-
-	    // Å‰‚̓ƒCƒ‹ƒhƒJ[ƒh‚ð’u‚­B
-	    for(std::vector<OkuriganaEntry>::const_iterator okuri = entry->second->begin();
-		okuri != entry->second->end(); okuri ++) {
-		// ƒƒCƒ‹ƒhƒJ[ƒh”­Œ©
-		if(okuri->isWild()) {
-		    line.append(join('/',okuri->getCandidates())).append('/');
-		    break;
-		}
-	    }
-
-	    // ŽŸ‚ɃƒCƒ‹ƒhƒJ[ƒhˆÈŠO‚ð’u‚­B
-	    for(std::vector<OkuriganaEntry>::const_iterator okuri = entry->second->begin();
-		okuri != entry->second->end(); okuri ++) {
-		if(okuri->isWild()) continue;
-
-		// ‚¨k /’u/[‚­/’u/]/
-		line.append('[').append(okuri->getKana()).append('/');
-		line.append(join('/',okuri->getCandidates())).append("/]/");
-	    }
-
-	    // EUC-JP‚É•ÏŠ·‚µ‚ď‘‚«ž‚ށB
-	    char* line_c = line.toCString(kCFStringEncodingEUC_JP);
-	    ofs << line_c << std::endl;
-	    delete[] line_c;
-	}
-    }
+    // ‘—‚è‚ ‚èƒGƒ“ƒgƒŠ
+    dic << skkdic::OkuriAriMark << std::endl;
+    std::for_each(okuriAri_.begin(), okuriAri_.end(), skkdic::Store(dic));
 
-    ofs << ";; okuri-nasi entries." << std::endl;
-    if(okuri_nasi_table.size() > 0) {
-	for(std::map<CppCFString, std::vector<CppCFString>*>::const_iterator entry = okuri_nasi_table.begin();
-	    entry != okuri_nasi_table.end(); entry ++) {
-	    if(entry->second == NULL) continue;
-	    if(entry->second->size() == 0) continue;
-
-	    CppCFString line;
-	    line.append(entry->first).append(" /");
-
-	    // ‘S‚Ă̍€–Ú‚ð’u‚­B
-	    line.append(join('/',*(entry->second))).append('/');
-
-	    // EUC-JP‚É•ÏŠ·‚µ‚ď‘‚«ž‚ށB
-	    char* line_c = line.toCString(kCFStringEncodingEUC_JP);
-	    ofs << line_c << std::endl;
-	    delete[] line_c;
-	}
-    }
+    // ‘—‚è‚È‚µƒGƒ“ƒgƒŠ
+    dic << skkdic::OkuriNasiMark << std::endl;
+    std::for_each(okuriNasi_.begin(), okuriNasi_.end(), skkdic::Store(dic));
 
     // ƒŠƒl[ƒ€‚·‚é
-    if(rename(dic_tmp_path.c_str(), fpath_.c_str()) < 0) {
-	std::cerr << "SKKUserDictionary::save(): rename() failed["
-		  << std::strerror(errno) << "]" << std::endl;
+    if(rename(tmpPath.c_str(), path_.c_str()) < 0) {
+	std::cerr << __FUNCTION__ << ": rename() failed[" << std::strerror(errno) << "]" << std::endl;
     } else {
 	std::cerr << "AquaSKK: saved user dictionary." << std::endl;
     }
 }
-
-// ------------------------------------------------------------------
-
-// ”ñƒƒ“ƒoŠÖ”ŒQ
-static void parseOkuriAriEntry(const CppCFString& line, CppCFString& index,
-			       std::vector<OkuriganaEntry>& entries) {
-    // ‚¾s /o/[‚¹/o/]/[‚·/o/]/[‚µ/o/]/
-    int pos_space = line.indexOf(' ');
-    if(pos_space == -1) return; // ˆÙí‚ȃGƒ“ƒgƒŠ
-
-    index = line.substring(0,pos_space);
-    CppCFString candidates_str(line.substring(pos_space + 1, line.length()));
-
-    // [‚ÅŽn‚Ü‚éƒGƒ“ƒgƒŠ‚ðŒ©‚é‚܂ł̓ƒCƒ‹ƒhƒJ[ƒhB
-    OkuriganaEntry wildcard(CppCFString(""));
-    const int len = candidates_str.length();
-    int pos = 1;
-    while(pos < len) {
-	// ƒGƒ“ƒgƒŠ‚ÌŽn‚Ü‚è
-	if(candidates_str[pos] != '[') {
-	    // ƒƒCƒ‹ƒhƒJ[ƒh‚ÌŒó•â
-	    int blockend = candidates_str.indexOf('/', pos);
-	    wildcard.add(candidates_str.substring(pos,blockend));
-	    pos = blockend + 1;
-	} else {
-	    int entry_end_pos = candidates_str.indexOf(']', pos);
-	    OkuriganaEntry entry(CppCFString(""));
-	    // []‚̍ŏ‰‚̍€–Ú‚©‚Ç‚¤‚©BÅ‰‚̍€–Ú‚ªŒ©o‚µ‚Æ‚È‚éB
-	    bool this_is_the_first_element = true;
-	    pos ++; // [‚ÌŽŸ‚©‚çB
-	    while(pos < entry_end_pos) {
-		int blockend = candidates_str.indexOf('/',pos);
-		if(this_is_the_first_element) {
-		    entry.setKana(candidates_str.substring(pos,blockend));
-		    this_is_the_first_element = false;
-		} else {
-		    entry.add(candidates_str.substring(pos,blockend));
-		}
-		pos = blockend + 1;
-	    }
-	    entries.push_back(entry);
-	    pos = entry_end_pos+2;
-	}
-    }
-    entries.push_back(wildcard);
-}
-
-static void parseOkuriNasiEntry(const CppCFString& line, CppCFString& index,
-				std::vector<CppCFString>& entries) {
-    // ‚©‚ª‚­ /‰»Šw/‰ÈŠw/
-    int pos_space = line.indexOf(' ');
-    if (pos_space == -1) return; // ˆÙí‚ȃGƒ“ƒgƒŠ
-	
-    index = line.substring(0,pos_space);
-    CppCFString candidates_str = line.substring(pos_space+1);
-	
-    entries = candidates_str.split('/');
-}
Index: AquaSKK/SKKDictionary.h
diff -u AquaSKK/SKKDictionary.h:1.5 AquaSKK/SKKDictionary.h:1.5.2.1
--- AquaSKK/SKKDictionary.h:1.5	Tue Nov 15 00:37:13 2005
+++ AquaSKK/SKKDictionary.h	Sun Jan  8 16:15:30 2006
@@ -1,11 +1,10 @@
 /*
-  $Id: SKKDictionary.h,v 1.5 2005/11/14 15:37:13 t-suwa Exp $
-  ---------
-	
+  $Id: SKKDictionary.h,v 1.5.2.1 2006/01/08 07:15:30 t-suwa Exp $
+
   MacOS X implementation of the SKK input method.
 
   Copyright (C) 2002 phonohawk
-  Copyright (C) 2005 Tomotaka SUWA <t.suw****@mac*****>
+  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
@@ -27,32 +26,35 @@
 #include <iostream>
 #include <string>
 #include <vector>
-#include <map>
+#include <deque>
 #include "Dictionary.h"
 
 class OkuriganaEntry;
 class CppCFString;
 
+// uŒ©o‚µŒêv‚Ɓu•ÏŠ·Œó•âv‚̃yƒA(•ÏŠ·Œó•â‚Í•ª‰ð‚·‚é‘O‚̏ó‘Ô)
+typedef std::pair<std::string, std::string> SKKPair;
+
+// ƒGƒ“ƒgƒŠ‚̃Rƒ“ƒeƒi
+typedef std::deque<SKKPair> EntryContainer;
+typedef EntryContainer::iterator EntryIterator;
+
 // SKK ‹¤—LŽ«‘
 class SKKDictionary: public Dictionary {
-    std::string fpath_;
-    std::map<CppCFString, std::vector<OkuriganaEntry>*> okuri_ari_table;
-    std::map<CppCFString, std::vector<CppCFString>*> okuri_nasi_table;
-    std::vector<std::string> okuri_ari_unparsed;
-    std::vector<std::string> okuri_nasi_unparsed;
+    std::string path_;
+    EntryContainer okuriAri_;
+    EntryContainer okuriNasi_;
 
     void load();
-    void close();
-    void parseAll();
-    static void* parserThreadRoutine(void* dic);
 
 public:
-    SKKDictionary(const std::string& fpath);
+    SKKDictionary(const std::string& path);
     virtual ~SKKDictionary();
-    
+
     virtual int countOkuriAri();
     virtual int countOkuriNasi();
-    virtual std::vector<OkuriganaEntry> findOkuriAri(const CppCFString& root);
+
+    virtual std::vector<OkuriganaEntry> findOkuriAri(const CppCFString& query);
     virtual std::vector<CppCFString> findOkuriNasi(const CppCFString& query);
 
     void changeDictionaryFile(const std::string& fpath);
@@ -60,34 +62,28 @@
 
 // SKK ƒ†[ƒU[Ž«‘
 class SKKUserDictionary: public UserDictionary {
-    std::string fpath_;
-    std::map<CppCFString, std::vector<OkuriganaEntry>*> okuri_ari_table;
-    std::map<CppCFString, std::vector<CppCFString>*> okuri_nasi_table;
-    std::vector<std::string> okuri_ari_unparsed;
-    std::vector<std::string> okuri_nasi_unparsed;
+    std::string path_;
+    EntryContainer okuriAri_;
+    EntryContainer okuriNasi_;
 
     void load();
     void save(bool force = false);
-    void parseAll();
 
 public:
-    SKKUserDictionary(const std::string& fpath);
+    SKKUserDictionary(const std::string& path);
     virtual ~SKKUserDictionary();
 
     virtual int countOkuriAri();
     virtual int countOkuriNasi();
+
     virtual std::vector<OkuriganaEntry> findOkuriAri(const CppCFString& query);
     virtual std::vector<CppCFString> findOkuriNasi(const CppCFString& query);
+
     virtual std::vector<CppCFString> findCompletions(const CppCFString& query);
 
-    virtual void registerOkuriAri(const CppCFString& index,
-				  const CppCFString& okuri,
-				  const CppCFString& kanji);
-    virtual void registerOkuriNasi(const CppCFString& index,
-				   const CppCFString& kanji);
-
-    virtual void removeOkuriAri(const CppCFString& index,
-				const CppCFString& kanji);
-    virtual void removeOkuriNasi(const CppCFString& index,
-				 const CppCFString& kanji);
+    virtual void registerOkuriAri(const CppCFString& index, const CppCFString& okuri, const CppCFString& kanji);
+    virtual void registerOkuriNasi(const CppCFString& index, const CppCFString& kanji);
+
+    virtual void removeOkuriAri(const CppCFString& index, const CppCFString& kanji);
+    virtual void removeOkuriNasi(const CppCFString& index, const CppCFString& kanji);
 };


aquaskk-changes メーリングリストの案内
Back to archive index