[aquaskk-changes 400] CVS update: AquaSKK/src/statemachine

アーカイブの一覧に戻る

t-suw****@users***** t-suw****@users*****
2007年 10月 5日 (金) 23:58:30 JST


Index: AquaSKK/src/statemachine/GenericStateMachine.h
diff -u AquaSKK/src/statemachine/GenericStateMachine.h:1.1.2.3 AquaSKK/src/statemachine/GenericStateMachine.h:1.1.2.4
--- AquaSKK/src/statemachine/GenericStateMachine.h:1.1.2.3	Sun Sep 23 23:48:08 2007
+++ AquaSKK/src/statemachine/GenericStateMachine.h	Fri Oct  5 23:58:29 2007
@@ -40,6 +40,7 @@
 #include <cassert>
 #include <vector>
 #include <list>
+#include <queue>
 #include <algorithm>
 #include <functional>
 
@@ -100,7 +101,8 @@
             DEEP_HISTORY,
 	    FORWARD,
 	    DEEP_FORWARD,
-            DEFER_EVENT
+            DEFER_EVENT,
+	    CLEAR_HISTORY
         };
 
         StateType type_;
@@ -123,6 +125,7 @@
         bool IsForward() const		{ return type_ == FORWARD; }
         bool IsDeepForward() const	{ return type_ == DEEP_FORWARD; }
         bool IsDeferEvent() const       { return type_ == DEFER_EVENT; }
+        bool IsClearHistory() const     { return type_ == CLEAR_HISTORY; }
 
         static GenericState Initial(Handler handler)            { return GenericState(INITIAL, handler); }
         static GenericState Transition(Handler handler)         { return GenericState(TRANSITION, handler); }
@@ -132,6 +135,7 @@
         static GenericState Forward(Handler handler)		{ return GenericState(FORWARD, handler); }
         static GenericState DeepForward(Handler handler)	{ return GenericState(DEEP_FORWARD, handler); }
         static GenericState DeferEvent()                        { return GenericState(DEFER_EVENT, 0); }
+        static GenericState ClearHistory()                      { return GenericState(CLEAR_HISTORY, 0); }
     };
 
     // ======================================================================
@@ -139,45 +143,65 @@
     // ======================================================================
     template <typename Handler>
     class GenericStateHistory {
-        typedef std::pair<Handler, Handler> History;
-        std::vector<Handler> keys_;
-        std::vector<History> values_;
+        typedef std::pair<Handler, Handler> ShallowDeepPair;
+	typedef std::pair<Handler, ShallowDeepPair> Entry;
+	typedef std::list<Entry> History;
+	typedef typename History::iterator HistoryIterator;
+
+        History history_;
 
 	enum HistoryTypes { SHALLOW, DEEP };
 
-        int lookup(const Handler key) const {
-            typename std::vector<Handler>::const_iterator iter = std::find(keys_.begin(), keys_.end(), key);
+	class Equal : public std::unary_function<Entry, bool> {
+	    Handler key_;
+
+	public:
+	    Equal(const Handler arg) : key_(arg) {}
 
-	    if(iter == keys_.end()) return -1;
+	    bool operator()(const Entry& entry) const {
+		return key_ == entry.first;
+	    }
+	};
 
-	    return iter - keys_.begin();
+        HistoryIterator lookup(const Handler key) {
+	    return std::find_if(history_.begin(), history_.end(), Equal(key));
         }
 
-        const Handler get(Handler key, HistoryTypes type) const {
-            int pos = lookup(key);
+        const Handler get(const Handler key, HistoryTypes type) {
+            HistoryIterator iter = lookup(key);
 
-            if(pos < 0) return 0;
+            if(iter == history_.end()) return 0;
 
-	    return type == SHALLOW ? values_[pos].first : values_[pos].second;
+	    ShallowDeepPair& pair = iter->second;
+
+	    return type == SHALLOW ? pair.first : pair.second;
         }
 
     public:
-        void Save(Handler key, Handler shallow, Handler deep) {
-            int pos = lookup(key);
+        void Save(const Handler key, const Handler shallow, const Handler deep) {
+            HistoryIterator iter = lookup(key);
+	    ShallowDeepPair pair = std::make_pair(shallow, deep);
 
-            if(pos < 0) {
-                keys_.push_back(key);
-                values_.push_back(std::make_pair(shallow, deep));
+            if(iter != history_.end()) {
+                iter->second = pair;
             } else {
-                values_[pos] = std::make_pair(shallow, deep);
+		history_.push_front(std::make_pair(key, pair));
             }
         }
 
-        const Handler Shallow(Handler key) const {
+	void Clear(const Handler key) {
+            HistoryIterator iter = lookup(key);
+
+	    if(iter != history_.end()) {
+		history_.erase(iter);
+	    }
+	}
+
+        const Handler Shallow(const Handler key) {
             return get(key, SHALLOW);
         }
 
-        const Handler Deep(Handler key) const {
+        const Handler Deep(const Handler key) {
             return get(key, DEEP);
         }
     };
@@ -187,34 +211,64 @@
     // ======================================================================
     template <typename Handler, typename Event>
     class GenericDeferEvent {
-        typedef std::pair<Handler, Event> Entry;
-        std::list<Entry> queue_;
+	typedef std::queue<Event> Defer;
+        typedef std::pair<Handler, Defer> Entry;
+	typedef std::list<Entry> Queue;
+	typedef typename Queue::iterator QueueIterator;
+
+        Queue arrival_;
+	Queue departure_;
+
+        class Equal : public std::unary_function<Entry, bool> {
+	    const Handler key_;
+
+	public:
+	    Equal(Handler arg) : key_(arg) {}
 
-        struct NotEqual : public std::unary_function<Entry, bool> {
-	    const Handler key;
-	    NotEqual(Handler arg) : key(arg) {}
             bool operator()(const Entry& entry) const {
-                return key != entry.first;
+		return key_ == entry.first;
             }
         };
 
+	QueueIterator find(const Handler key, Queue& queue) {
+	    return std::find_if(queue.begin(), queue.end(), Equal(key));
+	}
+
     public:
         void Enqueue(const Handler key, const Event& event) {
-            queue_.push_back(std::make_pair(key, event));
+	    QueueIterator iter = find(key, arrival_);
+
+	    if(iter == arrival_.end()) {
+		arrival_.push_front(std::make_pair(key, Defer()));
+		iter = arrival_.begin();
+	    }
+
+	    iter->second.push(event);
         }
 
-        bool Dequeue(const Handler key, Event& event) {
-            if(queue_.empty()) return false;
+	void Transfer(const Handler key) {
+	    QueueIterator iter = find(key, arrival_);
+
+	    if(iter != arrival_.end()) {
+		departure_.push_front(*iter);
+		arrival_.erase(iter);
+	    }
+	}
 
-            typename std::list<Entry>::iterator iter = std::find_if(queue_.begin(), queue_.end(), NotEqual(key));
+        bool Dequeue(const Handler key, Event& event) {
+	    QueueIterator iter = find(key, departure_);
 
-            if(iter != queue_.end()) {
-                event = iter->second;
-                queue_.erase(iter);
-                return true;
-            }
+            if(iter == departure_.end()) return false;
+	    
+	    if(iter->second.empty()) {
+		departure_.erase(iter);
+		return false;
+	    }
+		
+	    event = iter->second.front();
+	    iter->second.pop();
 
-            return false;
+	    return true;
         }
     };
 
@@ -229,7 +283,9 @@
     // ======================================================================
     // state machine
     // ======================================================================
-    template <typename StateContainer, template <typename Handler, typename Event> class Inspector = EmptyInspector>
+    template <typename StateContainer,
+	      template <typename Handler, typename Event>
+	      class Inspector = EmptyInspector>
     class GenericStateMachine {
     public:
 	typedef typename StateContainer::State State;
@@ -244,6 +300,7 @@
         Handler top_;
         Handler active_;
         Handler prior_;
+	int selfTransitionCount_;
 
         GenericStateHistory<Handler> history_;
         GenericDeferEvent<Handler, Event> queue_;
@@ -277,6 +334,8 @@
                 history_.Save(handler, prior_, active_);
             }
 
+	    queue_.Transfer(handler);
+
             prior_ = handler;
 
             return result;
@@ -330,10 +389,12 @@
 
 	    // exit to LCA(Least Common Ancestor) and record the path to the target
 	    do {
+		path_.clear();
 		path_.push_back(target);
 
 		// (a) self transition
 		if(source == target) {
+		    assert(++ selfTransitionCount_ < 3 && "*** Too many self transitions. ***");
 		    exitAction(source);
 		    break;
 		}
@@ -428,9 +489,20 @@
 
             State next;
 
+	    selfTransitionCount_ = 0;
             for(Handler source = active_; source != 0; source = next) {
                 next = invoke(source, event);
 
+		if(next.IsDeferEvent()) {
+		    queue_.Enqueue(source, event);
+		    break;
+		}
+
+		if(next.IsClearHistory()) {
+		    history_.Clear(source);
+		    break;
+		}
+
 		if(next.IsTransition() || next.IsDeepHistory() || next.IsForward() || next.IsDeepForward()) {
 		    if(next.IsDeepHistory() || next.IsDeepForward()) {
 			next = history_.Deep(next);
@@ -442,16 +514,11 @@
 
 		    if(next.IsForward() || next.IsDeepForward()) {
 			continue;
-		    } else {
-			while(queue_.Dequeue(next, defer_)) {
-			    Dispatch(defer_);	// recursion
-			}
 		    }
-		    break;
-		}
 
-		if(next.IsDeferEvent()) {
-		    queue_.Enqueue(next, event);
+		    while(queue_.Dequeue(source, defer_)) {
+			Dispatch(defer_);	// recursion
+		    }
 		    break;
 		}
 
@@ -460,6 +527,10 @@
             }
         }
 
+	const Handler CurrentState() const {
+	    return active_;
+	}
+
         const Output& Result() const {
             return container_.Result();
         }
Index: AquaSKK/src/statemachine/SKKEngine.h
diff -u AquaSKK/src/statemachine/SKKEngine.h:1.1.2.2 AquaSKK/src/statemachine/SKKEngine.h:1.1.2.3
--- AquaSKK/src/statemachine/SKKEngine.h:1.1.2.2	Sun Sep 23 23:48:08 2007
+++ AquaSKK/src/statemachine/SKKEngine.h	Fri Oct  5 23:58:29 2007
@@ -1,5 +1,5 @@
 /* -*- C++ -*-
-   $Id: SKKEngine.h,v 1.1.2.2 2007/09/23 14:48:08 t-suwa Exp $
+   $Id: SKKEngine.h,v 1.1.2.3 2007/10/05 14:58:29 t-suwa Exp $
 
    MacOS X implementation of the SKK input method.
 
@@ -24,17 +24,20 @@
 #define INC__SKKEngine__
 
 #include <iostream>
-#include "SKKEnvironment.h"
+#include "SKKState.h"
 
 template <typename Handler, typename Event>
 struct DebugInspector {
 public:
     void operator()(const Handler handler, const Event& event) {
-#define DEFINE_State(arg)	{ &SKKEnvironment::arg, #arg }
+	if(event == 0) return;
+
 	const static struct {
 	    Handler handler;
 	    const char* name;
 	} states[] = {
+#define DEFINE_State(arg)	{ &SKKState::arg, "SKKState::" #arg }
+	    DEFINE_State(Direct),
 	    DEFINE_State(KanaInput),
 	    DEFINE_State(Hirakana),
 	    DEFINE_State(Katakana),
@@ -44,36 +47,34 @@
 	    DEFINE_State(Jisx0208Latin),
 	    DEFINE_State(Compose),
 	    DEFINE_State(EntryInput),
-	    DEFINE_State(Japanese),
-	    DEFINE_State(Okuri),
-	    DEFINE_State(Abbreviation),
+	    DEFINE_State(KanaEntry),
+	    DEFINE_State(OkuriEntry),
+	    DEFINE_State(AsciiEntry),
 	    DEFINE_State(EntryCompletion),
 	    DEFINE_State(SelectCandidate),
 	    DEFINE_State(Inline),
 	    DEFINE_State(Window),
 	    DEFINE_State(EntryRemove),
+#undef DEFINE_State(arg)
 	    { 0, 0x00 }
 	};
-#undef DEFINE_State(arg)
 
-	static char* system_event[] = { "<<EXIT>>", "<<INIT>>", "<<ENTRY>>" };
+	static char* system_event[] = { "PROBE", "<<ENTRY>>", "<<INIT>>", "<<EXIT>>" };
 
-	if(event != 0) {
-	    for(int i = 0; states[i].handler != 0; ++ i) {
-		if(handler == states[i].handler) {
-		    std::cerr << "SKKEnvironment::" << states[i].name << ": ";
-		    if(event < 0) {
-			std::cerr << system_event[event + 3] << std::endl;
-		    } else {
-			std::cerr << event.Param().dump() << std::endl;
-		    }
-		    break;
+	for(int i = 0; states[i].handler != 0; ++ i) {
+	    if(handler == states[i].handler) {
+		std::cerr << states[i].name << ", ";
+		if(event < 0) {
+		    std::cerr << system_event[abs(event)] << std::endl;
+		} else {
+		    std::cerr << event.Param().dump() << std::endl;
 		}
+		break;
 	    }
 	}
     }
 };
 
-typedef GenericStateMachine<SKKEnvironment, DebugInspector> SKKEngine;
+typedef GenericStateMachine<SKKState, DebugInspector> SKKEngine;
 
 #endif
Index: AquaSKK/src/statemachine/SKKEnvironment.cpp
diff -u AquaSKK/src/statemachine/SKKEnvironment.cpp:1.1.2.3 AquaSKK/src/statemachine/SKKEnvironment.cpp:removed
--- AquaSKK/src/statemachine/SKKEnvironment.cpp:1.1.2.3	Mon Sep 24 18:23:33 2007
+++ AquaSKK/src/statemachine/SKKEnvironment.cpp	Fri Oct  5 23:58:29 2007
@@ -1,452 +0,0 @@
-/* -*- C++ -*-
-   MacOS X implementation of the SKK input method.
-
-   Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****>
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "SKKEnvironment.h"
-#include "SKKController.h"
-
-typedef SKKEnvironment::Event Event;
-typedef SKKEnvironment::State State;
-typedef SKKEnvironment::Output Output;
-
-SKKEnvironment::SKKEnvironment() {
-    controller_ = new SKKController();
-}
-
-SKKEnvironment::~SKKEnvironment() {
-    delete controller_;
-}
-
-// ======================================================================
-// level 1:かな入力
-// ======================================================================
-State SKKEnvironment::KanaInput(const Event& event) {
-    const SKKEventParam& param = event.Param();
-
-    switch(event) {
-    case ENTRY_EVENT:
-	controller_->ChangeState(SKK::DirectInput);
-	return 0;
-
-    case INIT_EVENT:
-	return State::ShallowHistory(&SKKEnvironment::Hirakana);
-
-    case EXIT_EVENT:
-	return State::SaveHistory();
-
-    case SKK_JMODE:
-	return controller_->HandleJmode();
-
-    case SKK_ENTER:
-	return controller_->HandleEnter();
-
-    case SKK_BACKSPACE:
-	return controller_->HandleBackSpace();
-
-    case SKK_DELETE:
-	return controller_->HandleDelete();
-
-    case SKK_CANCEL:
-	return controller_->HandleCancel();
-
-    case SKK_PASTE:
-	return controller_->HandlePaste();
-
-    case SKK_LEFT:
-	return controller_->HandleCursorLeft();
-
-    case SKK_RIGHT:
-	return controller_->HandleCursorRight();
-
-    case SKK_UP:
-	return controller_->HandleCursorUp();
-
-    case SKK_DOWN:
-	return controller_->HandleCursorDown();
-
-    case SKK_ASCII:
-	return State::Transition(&SKKEnvironment::Ascii);
-
-    case SKK_JISX0208LATIN:
-	return State::Transition(&SKKEnvironment::Jisx0208Latin);
-
-    case SKK_CHAR:
-	return controller_->HandleInput(param);
-    }
-
-    return &SKKEnvironment::TopState;
-}
-
-// ======================================================================
-// level 2 (sub of KanaInput):ひらかな
-// ======================================================================
-State SKKEnvironment::Hirakana(const Event& event) {
-    const SKKEventParam& param = event.Param();
-
-    switch(event) {
-    case ENTRY_EVENT:
-	controller_->SelectInputMode(SKK::Hirakana);
-	return 0;
-
-    case SKK_KATAKANA:
-	return State::Transition(&SKKEnvironment::Katakana);
-
-    case SKK_JISX0201KANA:
-	return State::Transition(&SKKEnvironment::Jisx0201Kana);
-
-    case SKK_CHAR:
-	if(param.IsToggleKana()) {
-	    return State::Transition(&SKKEnvironment::Katakana);
-	}
-
-	if(param.IsToggleJisx0201Kana()) {
-	    return State::Transition(&SKKEnvironment::Jisx0201Kana);
-	}
-    }
-
-    return &SKKEnvironment::KanaInput;
-}
-
-// ======================================================================
-// level 2 (sub of KanaInput):カタカナ
-// ======================================================================
-State SKKEnvironment::Katakana(const Event& event) {
-    const SKKEventParam& param = event.Param();
-
-    switch(event) {
-    case ENTRY_EVENT:
-	controller_->SelectInputMode(SKK::Katakana);
-	return 0;
-
-    case SKK_HIRAKANA:
-	return State::Transition(&SKKEnvironment::Hirakana);
-
-    case SKK_JISX0201KANA:
-	return State::Transition(&SKKEnvironment::Jisx0201Kana);
-
-    case SKK_CHAR:
-	if(param.IsToggleKana()) {
-	    return State::Transition(&SKKEnvironment::Hirakana);
-	}
-
-	if(param.IsToggleJisx0201Kana()) {
-	    return State::Transition(&SKKEnvironment::Jisx0201Kana);
-	}
-    }
-
-    return &SKKEnvironment::KanaInput;
-}
-
-// ======================================================================
-// level 2 (sub of KanaInput):半角カタカナ
-// ======================================================================
-State SKKEnvironment::Jisx0201Kana(const Event& event) {
-    const SKKEventParam& param = event.Param();
-
-    switch(event) {
-    case ENTRY_EVENT:
-	controller_->SelectInputMode(SKK::Jisx0201Kana);
-	return 0;
-
-    case SKK_HIRAKANA:
-	return State::Transition(&SKKEnvironment::Hirakana);
-
-    case SKK_CHAR:
-	if(param.IsToggleKana() || param.IsToggleJisx0201Kana()) {
-	    return State::Transition(&SKKEnvironment::Hirakana);
-	}
-    }
-
-    return &SKKEnvironment::KanaInput;
-}
-
-// ======================================================================
-// level 1:Latin 入力
-// ======================================================================
-State SKKEnvironment::LatinInput(const Event& event) {
-    const SKKEventParam& param = event.Param();
-
-    switch(event) {
-    case ENTRY_EVENT:
-	controller_->ChangeState(SKK::DirectInput);
-	return 0;
-
-    case SKK_JMODE:
-    case SKK_HIRAKANA:
-	return State::Transition(&SKKEnvironment::Hirakana);
-
-    case SKK_CHAR:
-	return controller_->HandleInput(param);
-    }
-
-    return &SKKEnvironment::TopState;
-}
-
-// ======================================================================
-// level 2 (sub of LatinInput):ASCII
-// ======================================================================
-State SKKEnvironment::Ascii(const Event& event) {
-    switch(event) {
-    case ENTRY_EVENT:
-	controller_->SelectInputMode(SKK::Ascii);
-	return 0;
-    }
-
-    return &SKKEnvironment::LatinInput;
-}
-
-// ======================================================================
-// level 2 (sub of LatinInput):全角英数
-// ======================================================================
-State SKKEnvironment::Jisx0208Latin(const Event& event) {
-    switch(event) {
-    case ENTRY_EVENT:
-	controller_->SelectInputMode(SKK::Jisx0208Latin);
-	return 0;
-    }
-
-    return &SKKEnvironment::LatinInput;
-}
-
-// ======================================================================
-// level 1:見出し語構築
-// ======================================================================
-State SKKEnvironment::Compose(const Event& event) {
-    switch(event) {
-    case SKK_ENTER:
-	return controller_->HandleEnter();
-
-    case SKK_JMODE:
-	return controller_->HandleJmode();
-
-    case SKK_TAB:
-	return controller_->HandleTab();
-
-    case SKK_BACKSPACE:
-	return controller_->HandleBackSpace();
-
-    case SKK_DELETE:
-	return controller_->HandleDelete();
-
-    case SKK_LEFT:
-	return controller_->HandleCursorLeft();
-
-    case SKK_RIGHT:
-	return controller_->HandleCursorRight();
-
-    case SKK_UP:
-	return controller_->HandleCursorUp();
-
-    case SKK_DOWN:
-	return controller_->HandleCursorDown();
-
-    case SKK_CANCEL:
-	return controller_->HandleCancel();
-    }
-
-    return &SKKEnvironment::TopState;
-}
-
-// ======================================================================
-// level 2 (sub of Compose):見出し語入力
-// ======================================================================
-State SKKEnvironment::EntryInput(const Event& event) {
-    const SKKEventParam& param = event.Param();
-
-    switch(event) {
-    case EXIT_EVENT:
-	return State::SaveHistory();
-
-    case SKK_PASTE:
-	return controller_->HandlePaste();
-
-    case SKK_CHAR:
-	return controller_->HandleInput(param);
-    }
-
-    return &SKKEnvironment::Compose;
-}
-
-// ======================================================================
-// level 3 (sub of EntryInput):日本語
-// ======================================================================
-State SKKEnvironment::Japanese(const Event& event) {
-    switch(event) {
-    case ENTRY_EVENT:
-	controller_->ChangeState(SKK::EntryInput);
-	return 0;
-    }
-
-    return &SKKEnvironment::EntryInput;
-}
-
-// ======================================================================
-// level 3 (sub of EntryInput):送り
-// ======================================================================
-State SKKEnvironment::Okuri(const Event& event) {
-    switch(event) {
-    case ENTRY_EVENT:
-	controller_->ChangeState(SKK::OkuriInput);
-	return 0;
-    }
-
-    return &SKKEnvironment::EntryInput;
-}
-
-// ======================================================================
-// level 3 (sub of EntryInput):省略表記
-// ======================================================================
-State SKKEnvironment::Abbreviation(const Event& event) {
-    switch(event) {
-    case ENTRY_EVENT:
-	controller_->SelectInputMode(SKK::Ascii);
-	controller_->ChangeState(SKK::AbbrevInput);
-	return 0;
-    }
-
-    return &SKKEnvironment::EntryInput;
-}
-
-// ======================================================================
-// level 2 (sub of Compose):見出し語補完
-// ======================================================================
-State SKKEnvironment::EntryCompletion(const Event& event) {
-    const SKKEventParam& param = event.Param();
-
-    switch(event) {
-    case ENTRY_EVENT:
-	controller_->ChangeState(SKK::Completion);
-	return 0;
-    }
-
-    // システムイベントと変換は無視する
-    if(event.IsSystem() ||
-       event == SKK_TAB ||
-       (event == SKK_CHAR && (param.IsNextCandidate() ||
-			      param.IsNextCompletion() ||
-			      param.IsPrevCompletion()))) {
-	return &SKKEnvironment::Compose;
-    }
-
-    // 補完キー以外なら履歴に転送する
-    return State::DeepForward(&SKKEnvironment::EntryInput);
-}
-
-// ======================================================================
-// level 1:候補選択
-// ======================================================================
-State SKKEnvironment::SelectCandidate(const Event& event) {
-    switch(event) {
-    case INIT_EVENT:
-	return State::ShallowHistory(&SKKEnvironment::Inline);
-
-    case EXIT_EVENT:
-	return State::SaveHistory();
-
-    case SKK_ENTER:
-	return controller_->HandleEnter();
-
-    case SKK_JMODE:
-	return controller_->HandleJmode();
-
-    case SKK_CANCEL:
-	return State::DeepHistory(&SKKEnvironment::EntryInput);
-
-    case SKK_CHAR:
-	return State::Forward(&SKKEnvironment::KanaInput);
-    }
-
-    return &SKKEnvironment::TopState;
-}
-
-// ======================================================================
-// level 2 (sub of SelectCandidate):インライン表示
-// ======================================================================
-State SKKEnvironment::Inline(const Event& event) {
-    const SKKEventParam& param = event.Param();
-
-    switch(event) {
-    case ENTRY_EVENT:
-	controller_->ChangeState(SKK::SingleCandidate);
-	return 0;
-
-    case SKK_BACKSPACE:
-	return controller_->HandleBackSpace();
-
-    case SKK_CHAR:
-	return controller_->HandleInput(param);
-    }
-
-    return &SKKEnvironment::SelectCandidate;
-}
-
-// ======================================================================
-// level 2 (sub of SelectCandidate):ウィンドウ表示
-// ======================================================================
-State SKKEnvironment::Window(const Event& event) {
-    const SKKEventParam& param = event.Param();
-
-    switch(event) {
-    case ENTRY_EVENT:
-	controller_->ChangeState(SKK::MultipleCandidate);
-	return 0;
-
-    case EXIT_EVENT:
-	return 0;
-
-    case SKK_BACKSPACE:
-	return controller_->HandleBackSpace();;
-
-    case SKK_CHAR:
-	return controller_->HandleInput(param);
-    }
-
-    return &SKKEnvironment::SelectCandidate;
-}
-
-// ======================================================================
-// level 1:単語削除
-// ======================================================================
-State SKKEnvironment::EntryRemove(const Event& event) {
-    const SKKEventParam& param = event.Param();
-
-    switch(event) {
-    case ENTRY_EVENT:
-	controller_->ChangeState(SKK::EntryRemove);
-	return 0;
-
-    case SKK_YES:
-	return State::Transition(&SKKEnvironment::KanaInput);
-
-    case SKK_CANCEL:
-    case SKK_NO:
-	return State::Transition(&SKKEnvironment::Inline);
-
-    case SKK_ENTER:
-	return controller_->HandleEnter();
-
-    case SKK_BACKSPACE:
-	return controller_->HandleBackSpace();
-
-    case SKK_CHAR:
-	return controller_->HandleInput(param);
-    }
-
-    return &SKKEnvironment::TopState;
-}
Index: AquaSKK/src/statemachine/SKKEnvironment.h
diff -u AquaSKK/src/statemachine/SKKEnvironment.h:1.1.2.2 AquaSKK/src/statemachine/SKKEnvironment.h:removed
--- AquaSKK/src/statemachine/SKKEnvironment.h:1.1.2.2	Sun Sep 23 23:48:08 2007
+++ AquaSKK/src/statemachine/SKKEnvironment.h	Fri Oct  5 23:58:29 2007
@@ -1,81 +0,0 @@
-/* -*- C++ -*-
-   MacOS X implementation of the SKK input method.
-
-   Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****>
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef INC__SKKEnvironment__
-#define INC__SKKEnvironment__
-
-#include "GenericStateMachine.h"
-#include "SKKEventParam.h"
-
-using namespace statemachinecxx_sourceforge_jp;
-
-class SKKController;
-
-// 実行環境
-class SKKEnvironment : public BaseStateContainer<SKKEnvironment, SKKEventParam> {
-    SKKController* controller_;
-
-public:
-    SKKEnvironment();
-    ~SKKEnvironment();
-
-    const Handler InitialState() const { return &SKKEnvironment::KanaInput; }
-
-    // level 1 (initial state)
-    State KanaInput(const Event& event);
-
-	// level 2 (sub of KanaInput)
-    	State Hirakana(const Event& event);
-    	State Katakana(const Event& event);
-    	State Jisx0201Kana(const Event& event);
-
-    // level 1
-    State LatinInput(const Event& event);
-
-    	// level2 (sub of LatinInput)
-    	State Ascii(const Event& event);
-    	State Jisx0208Latin(const Event& event);
-
-    // level 1
-    State Compose(const Event& event);
-
-    	// level 2 (sub of Compose)
-    	State EntryInput(const Event& event);
-
-    	    // lelvel 3 (sub of EntryInput)
-    	    State Japanese(const Event& event);
-    	    State Okuri(const Event& event);
-    	    State Abbreviation(const Event& event);
-
-    	// level 2 (sub of Compose)
-    	State EntryCompletion(const Event& event);
-
-    // level 1
-    State SelectCandidate(const Event& event);
-
-    	// level 2 (sub of SelectCandidate)
-    	State Inline(const Event& event);
-    	State Window(const Event& event);
-
-    // level 1
-    State EntryRemove(const Event& event);
-};
-
-#endif
Index: AquaSKK/src/statemachine/SKKState.cpp
diff -u /dev/null AquaSKK/src/statemachine/SKKState.cpp:1.1.2.1
--- /dev/null	Fri Oct  5 23:58:29 2007
+++ AquaSKK/src/statemachine/SKKState.cpp	Fri Oct  5 23:58:29 2007
@@ -0,0 +1,571 @@
+/* -*- C++ -*-
+   MacOS X implementation of the SKK input method.
+
+   Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "SKKState.h"
+#include "SKKStateDirectHandler.h"
+#include "SKKStateComposeHandler.h"
+#include "SKKStateKanaEntryHandler.h"
+#include "SKKStateOkuriEntryHandler.h"
+#include "SKKStateAsciiEntryHandler.h"
+#include "jconv.h"
+
+typedef SKKState::Event Event;
+typedef SKKState::State State;
+typedef SKKState::Output Output;
+
+SKKState::SKKState() {
+    stack_.push_back(frame(SKKContext(), 0));
+}
+
+// ======================================================================
+// level 1:直接入力
+// ======================================================================
+State SKKState::Direct(const Event& event) {
+    switch(event) {
+    case INIT_EVENT:
+	return State::Initial(&SKKState::KanaInput);
+
+    case SKK_ENTER:
+	return DirectHandler<SKK_ENTER>();
+
+    case SKK_CANCEL:
+	return DirectHandler<SKK_CANCEL>();
+
+    case SKK_BACKSPACE:
+	return DirectHandler<SKK_BACKSPACE>();
+
+    case SKK_DELETE:
+	return DirectHandler<SKK_DELETE>();
+
+    case SKK_PASTE:
+	return DirectHandler<SKK_PASTE>();
+
+    case SKK_LEFT:
+	return DirectHandler<SKK_LEFT>();
+
+    case SKK_RIGHT:
+	return DirectHandler<SKK_RIGHT>();
+
+    case SKK_UP:
+	return DirectHandler<SKK_UP>();
+
+    case SKK_DOWN:
+	return DirectHandler<SKK_DOWN>();
+
+    case SKK_CHAR:
+	return DirectHandler<SKK_CHAR>(event.Param());
+    }
+
+    return &SKKState::TopState;
+}
+
+// ======================================================================
+// level 2 (sub of Direct):かな入力
+// ======================================================================
+State SKKState::KanaInput(const Event& event) {
+    switch(event) {
+    case INIT_EVENT:
+	return State::ShallowHistory(&SKKState::Hirakana);
+
+    case EXIT_EVENT:
+	return State::SaveHistory();
+
+    case SKK_ASCII:
+	return State::Transition(&SKKState::Ascii);
+
+    case SKK_JISX0208LATIN:
+	return State::Transition(&SKKState::Jisx0208Latin);
+    }
+
+    return &SKKState::Direct;
+}
+
+// ======================================================================
+// level 3 (sub of KanaInput):ひらかな
+// ======================================================================
+State SKKState::Hirakana(const Event& event) {
+    const SKKEventParam& param = event.Param();
+
+    switch(event) {
+    case ENTRY_EVENT:
+	selectInputMode(SKK::Hirakana);
+	return 0;
+
+    case SKK_KATAKANA:
+	return State::Transition(&SKKState::Katakana);
+
+    case SKK_JISX0201KANA:
+	return State::Transition(&SKKState::Jisx0201Kana);
+
+    case SKK_CHAR:
+	if(param.IsToggleKana()) {
+	    return State::Transition(&SKKState::Katakana);
+	}
+
+	if(param.IsToggleJisx0201Kana()) {
+	    return State::Transition(&SKKState::Jisx0201Kana);
+	}
+    }
+
+    return &SKKState::KanaInput;
+}
+
+// ======================================================================
+// level 3 (sub of KanaInput):カタカナ
+// ======================================================================
+State SKKState::Katakana(const Event& event) {
+    const SKKEventParam& param = event.Param();
+
+    switch(event) {
+    case ENTRY_EVENT:
+	selectInputMode(SKK::Katakana);
+	return 0;
+
+    case SKK_HIRAKANA:
+	return State::Transition(&SKKState::Hirakana);
+
+    case SKK_JISX0201KANA:
+	return State::Transition(&SKKState::Jisx0201Kana);
+
+    case SKK_CHAR:
+	if(param.IsToggleKana()) {
+	    return State::Transition(&SKKState::Hirakana);
+	}
+
+	if(param.IsToggleJisx0201Kana()) {
+	    return State::Transition(&SKKState::Jisx0201Kana);
+	}
+    }
+
+    return &SKKState::KanaInput;
+}
+
+// ======================================================================
+// level 3 (sub of KanaInput):半角カタカナ
+// ======================================================================
+State SKKState::Jisx0201Kana(const Event& event) {
+    const SKKEventParam& param = event.Param();
+
+    switch(event) {
+    case ENTRY_EVENT:
+	selectInputMode(SKK::Jisx0201Kana);
+	return 0;
+
+    case SKK_HIRAKANA:
+	return State::Transition(&SKKState::Hirakana);
+
+    case SKK_CHAR:
+	if(param.IsToggleKana() || param.IsToggleJisx0201Kana()) {
+	    return State::Transition(&SKKState::Hirakana);
+	}
+    }
+
+    return &SKKState::KanaInput;
+}
+
+// ======================================================================
+// level 2 (sub of Direct):Latin 入力
+// ======================================================================
+State SKKState::LatinInput(const Event& event) {
+    switch(event) {
+    case SKK_JMODE:
+    case SKK_HIRAKANA:
+	return State::Transition(&SKKState::Hirakana);
+    }
+
+    return &SKKState::Direct;
+}
+
+// ======================================================================
+// level 2 (sub of LatinInput):ASCII
+// ======================================================================
+State SKKState::Ascii(const Event& event) {
+    switch(event) {
+    case ENTRY_EVENT:
+	selectInputMode(SKK::Ascii);
+	return 0;
+    }
+
+    return &SKKState::LatinInput;
+}
+
+// ======================================================================
+// level 2 (sub of LatinInput):全角英数
+// ======================================================================
+State SKKState::Jisx0208Latin(const Event& event) {
+    switch(event) {
+    case ENTRY_EVENT:
+	selectInputMode(SKK::Jisx0208Latin);
+	return 0;
+    }
+
+    return &SKKState::LatinInput;
+}
+
+// ======================================================================
+// level 1:見出し語構築
+// ======================================================================
+State SKKState::Compose(const Event& event) {
+    switch(event) {
+    case SKK_ENTER:
+	return ComposeHandler<SKK_ENTER>();
+
+    case SKK_JMODE:
+	return ComposeHandler<SKK_JMODE>();
+
+    case SKK_CANCEL:
+	return ComposeHandler<SKK_CANCEL>();
+
+    case SKK_TAB:
+	return ComposeHandler<SKK_TAB>();
+
+    case SKK_BACKSPACE:
+	return ComposeHandler<SKK_BACKSPACE>();
+
+    case SKK_DELETE:
+	return ComposeHandler<SKK_DELETE>();
+
+    case SKK_LEFT:
+	return ComposeHandler<SKK_LEFT>();
+
+    case SKK_RIGHT:
+	return ComposeHandler<SKK_RIGHT>();
+
+    case SKK_UP:
+	return ComposeHandler<SKK_UP>();
+
+    case SKK_DOWN:
+	return ComposeHandler<SKK_DOWN>();
+    }
+
+    return &SKKState::TopState;
+}
+
+// ======================================================================
+// level 2 (sub of Compose):見出し語入力
+// ======================================================================
+State SKKState::EntryInput(const Event& event) {
+    switch(event) {
+    case EXIT_EVENT:
+	return State::SaveHistory();
+    }
+
+    return &SKKState::Compose;
+}
+
+// ======================================================================
+// level 3 (sub of EntryInput):日本語
+// ======================================================================
+State SKKState::KanaEntry(const Event& event) {
+    switch(event) {
+    case SKK_CHAR:
+	return KanaEntryHandler<SKK_CHAR>(event.Param());
+    }
+
+    return &SKKState::EntryInput;
+}
+
+// ======================================================================
+// level 3 (sub of EntryInput):送り
+// ======================================================================
+State SKKState::OkuriEntry(const Event& event) {
+    switch(event) {
+    case SKK_TAB:
+    case SKK_DELETE:
+    case SKK_LEFT:
+    case SKK_RIGHT:
+    case SKK_UP:
+    case SKK_DOWN:
+	return 0;
+
+    case SKK_BACKSPACE:
+	return OkuriEntryHandler<SKK_BACKSPACE>();
+
+    case SKK_CHAR:
+	return OkuriEntryHandler<SKK_CHAR>(event.Param());
+    }
+
+    return &SKKState::EntryInput;
+}
+
+// ======================================================================
+// level 3 (sub of EntryInput):省略表記
+// ======================================================================
+State SKKState::AsciiEntry(const Event& event) {
+    switch(event) {
+    case ENTRY_EVENT:
+	selectInputMode(SKK::Ascii);
+	return 0;
+
+    case SKK_CHAR:
+	return AsciiEntryHandler<SKK_CHAR>(event.Param());
+    }
+
+    return &SKKState::EntryInput;
+}
+
+// ======================================================================
+// level 2 (sub of Compose):見出し語補完
+// ======================================================================
+State SKKState::EntryCompletion(const Event& event) {
+    const SKKEventParam& param = event.Param();
+
+    switch(event) {
+    case ENTRY_EVENT:
+	//controller_->ChangeState(SKK::Completion);
+	return 0;
+    }
+
+    // システムイベントと変換は無視する
+    if(event.IsSystem() ||
+       event == SKK_TAB ||
+       (event == SKK_CHAR && (param.IsNextCandidate() ||
+			      param.IsNextCompletion() ||
+			      param.IsPrevCompletion()))) {
+	return &SKKState::Compose;
+    }
+
+    // 補完キー以外なら履歴に転送する
+    return State::DeepForward(&SKKState::EntryInput);
+}
+
+// ======================================================================
+// level 1:候補選択
+// ======================================================================
+State SKKState::SelectCandidate(const Event& event) {
+    switch(event) {
+    case INIT_EVENT:
+	return State::ShallowHistory(&SKKState::Inline);
+
+    case EXIT_EVENT:
+	return State::SaveHistory();
+
+    case SKK_ENTER:
+	//return controller_->HandleEnter();
+
+    case SKK_JMODE:
+	//return controller_->HandleJmode();
+
+    case SKK_CANCEL:
+	return State::DeepHistory(&SKKState::EntryInput);
+
+    case SKK_CHAR:
+	return State::Forward(&SKKState::KanaInput);
+    }
+
+    return &SKKState::TopState;
+}
+
+// ======================================================================
+// level 2 (sub of SelectCandidate):インライン表示
+// ======================================================================
+State SKKState::Inline(const Event& event) {
+    switch(event) {
+    case ENTRY_EVENT:
+	return 0;
+
+    case SKK_BACKSPACE:
+
+    case SKK_CHAR:
+	break;
+    }
+
+    return &SKKState::SelectCandidate;
+}
+
+// ======================================================================
+// level 2 (sub of SelectCandidate):ウィンドウ表示
+// ======================================================================
+State SKKState::Window(const Event& event) {
+    switch(event) {
+    case ENTRY_EVENT:
+	return 0;
+
+    case EXIT_EVENT:
+	return 0;
+
+    case SKK_BACKSPACE:
+
+    case SKK_CHAR:
+	break;
+    }
+
+    return &SKKState::SelectCandidate;
+}
+
+// ======================================================================
+// level 1:単語削除
+// ======================================================================
+State SKKState::EntryRemove(const Event& event) {
+    switch(event) {
+    case ENTRY_EVENT:
+	return 0;
+
+    case SKK_YES:
+	return State::Transition(&SKKState::KanaInput);
+
+    case SKK_CANCEL:
+    case SKK_NO:
+	return State::Transition(&SKKState::Inline);
+
+    case SKK_ENTER:
+
+    case SKK_BACKSPACE:
+
+    case SKK_CHAR:
+	break;
+    }
+
+    return &SKKState::TopState;
+}
+
+// ======================================================================
+// private method
+// ======================================================================
+SKKContext& SKKState::context() {
+    return stack_.back().first;
+}
+
+bool SKKState::bottom() const {
+    return stack_.size() == 1;
+}
+
+void SKKState::selectInputMode(SKK::InputMode mode) {
+    SKKInputBuffer& buffer = context().InputBuffer();
+    SKKOkuriBuffer& okuri = context().OkuriBuffer();
+
+    buffer.SelectInputMode(mode);
+    okuri.SelectInputMode(mode);
+}
+
+void SKKState::composeDisplay() {
+    SKKOutputPort& port = context().OutputPort();
+    SKKInputBuffer& input = context().InputBuffer();
+    SKKEditBuffer edit(context().EditBuffer());
+
+    if(!input.IsEmpty()) {
+	edit.Insert(input.InputString());
+    }
+    
+    port.DisplayString("â–½" + edit.EditString(), 1 + edit.CursorPosition());
+}
+
+void SKKState::okuriDisplay() {
+    SKKOutputPort& port = context().OutputPort();
+    SKKOkuriBuffer& okuri = context().OkuriBuffer();
+    SKKEditBuffer edit(context().EditBuffer());
+
+    edit.Insert("*" + okuri.KanaString());
+    
+    port.DisplayString("â–½" + edit.EditString(), 1 + edit.CursorPosition());
+}
+
+void SKKState::toggleKana() {
+    SKKEditBuffer& edit = context().EditBuffer();
+    SKKOutputPort& port = context().OutputPort();
+    std::string to;
+
+    switch(context().InputBuffer().InputMode()) {
+    case SKK::Hirakana:
+	jconv::hirakana_to_katakana(edit.EditString(), to);
+	break;
+
+    case SKK::Katakana:
+	jconv::katakana_to_hirakana(edit.EditString(), to);
+	break;
+		
+    case SKK::Jisx0201Kana:
+	jconv::jisx0201_kana_to_katakana(edit.EditString(), to);
+	break;
+
+    default:
+	break;
+    }
+
+    edit.Clear();
+    port.FixString(to);
+}
+
+void SKKState::toggleJisx0201Kana() {
+    SKKEditBuffer& edit = context().EditBuffer();
+    SKKOutputPort& port = context().OutputPort();
+    std::string to;
+
+    switch(context().InputBuffer().InputMode()) {
+    case SKK::Hirakana:
+	jconv::hirakana_to_jisx0201_kana(edit.EditString(), to);
+	break;
+
+    case SKK::Katakana:
+	jconv::katakana_to_jisx0201_kana(edit.EditString(), to);
+	break;
+		
+    case SKK::Jisx0201Kana:
+	jconv::jisx0201_kana_to_hirakana(edit.EditString(), to);
+	break;
+
+    case SKK::Ascii:
+	jconv::ascii_to_jisx0208_latin(edit.EditString(), to);
+
+    default:
+	break;
+    }
+
+    edit.Clear();
+    port.FixString(to);
+}
+
+void SKKState::beginRegistration(const std::string& prompt, Handler restorePoint) {
+    stack_.push_back(frame(SKKContext(prompt), restorePoint));
+}
+
+State SKKState::endRegistration(bool commit) {
+    if(bottom()) return 0;
+
+    frame current(stack_.back());
+
+    stack_.pop_back();
+
+    std::string result;
+    if(commit) {
+	 result = current.first.Word();
+    }
+
+    context().OutputPort().FixString(result);
+
+    // キャンセルされた場合は復帰場所に戻る
+    if(!commit) {
+	return State::Transition(current.second);
+    }
+
+    // 確定されたら、現在の入力モードに遷移
+    switch(context().InputBuffer().InputMode()) {
+    case SKK::Hirakana:
+	return State::Transition(&SKKState::Hirakana);
+	    
+    case SKK::Katakana:
+	return State::Transition(&SKKState::Katakana);
+	    
+    case SKK::Jisx0201Kana:
+	return State::Transition(&SKKState::Jisx0201Kana);
+    }
+	    
+    return State::Transition(&SKKState::KanaInput);
+}
Index: AquaSKK/src/statemachine/SKKState.h
diff -u /dev/null AquaSKK/src/statemachine/SKKState.h:1.1.2.1
--- /dev/null	Fri Oct  5 23:58:29 2007
+++ AquaSKK/src/statemachine/SKKState.h	Fri Oct  5 23:58:29 2007
@@ -0,0 +1,109 @@
+/* -*- C++ -*-
+   MacOS X implementation of the SKK input method.
+
+   Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef INC__SKKState__
+#define INC__SKKState__
+
+#include "GenericStateMachine.h"
+#include "SKKEventParam.h"
+#include "SKKContext.h"
+
+using namespace statemachinecxx_sourceforge_jp;
+
+// 実行環境
+class SKKState : public BaseStateContainer<SKKState, SKKEventParam> {
+    typedef std::pair<SKKContext, Handler> frame;
+    std::vector<frame> stack_;
+
+    SKKContext& context();
+    bool bottom() const;
+
+    void selectInputMode(SKK::InputMode mode);
+
+    // イベントハンドラ
+    template <int Signal> State DirectHandler();
+    template <int Signal> State DirectHandler(const SKKEventParam& param);
+    template <int Signal> State ComposeHandler();
+    template <int Signal> State KanaEntryHandler(const SKKEventParam& event);
+    template <int Signal> State OkuriEntryHandler();
+    template <int Signal> State OkuriEntryHandler(const SKKEventParam& event);
+    template <int Signal> State AsciiEntryHandler(const SKKEventParam& event);
+
+    // 表示
+    void composeDisplay();
+    void okuriDisplay();
+
+    // トグル変換
+    void toggleKana();
+    void toggleJisx0201Kana();
+
+    // 単語登録
+    void beginRegistration(const std::string& prompt, Handler restorePoint);
+    State endRegistration(bool commit);
+
+public:
+    SKKState();
+
+    const Handler InitialState() const { return &SKKState::Direct; }
+
+    // level 1
+    State Direct(const Event& event);
+
+        // level 2 (initial state)
+        State KanaInput(const Event& event);
+
+	    // level 3 (sub of KanaInput)
+    	    State Hirakana(const Event& event);
+    	    State Katakana(const Event& event);
+    	    State Jisx0201Kana(const Event& event);
+
+        // level 2
+        State LatinInput(const Event& event);
+
+    	    // level 3 (sub of LatinInput)
+    	    State Ascii(const Event& event);
+    	    State Jisx0208Latin(const Event& event);
+
+    // level 1
+    State Compose(const Event& event);
+
+    	// level 2 (sub of Compose)
+    	State EntryInput(const Event& event);
+
+    	    // lelvel 3 (sub of EntryInput)
+    	    State KanaEntry(const Event& event);
+    	    State OkuriEntry(const Event& event);
+    	    State AsciiEntry(const Event& event);
+
+    	// level 2 (sub of Compose)
+    	State EntryCompletion(const Event& event);
+
+    // level 1
+    State SelectCandidate(const Event& event);
+
+    	// level 2 (sub of SelectCandidate)
+    	State Inline(const Event& event);
+    	State Window(const Event& event);
+
+    // level 1
+    State EntryRemove(const Event& event);
+};
+
+#endif
Index: AquaSKK/src/statemachine/SKKStateAsciiEntryHandler.h
diff -u /dev/null AquaSKK/src/statemachine/SKKStateAsciiEntryHandler.h:1.1.2.1
--- /dev/null	Fri Oct  5 23:58:29 2007
+++ AquaSKK/src/statemachine/SKKStateAsciiEntryHandler.h	Fri Oct  5 23:58:29 2007
@@ -0,0 +1,70 @@
+/* -*- C++ -*-
+   MacOS X implementation of the SKK input method.
+
+   Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef INC__SKKStateAsciiEntryHandler__
+#define INC__SKKStateAsciiEntryHandler__
+
+#include "SKKState.h"
+
+typedef SKKState::State State;
+
+// ======================================================================
+// ASCII 見出し語
+// ======================================================================
+
+template <>
+State SKKState::AsciiEntryHandler<SKK_CHAR>(const SKKEventParam& param) {
+    SKKInputBuffer& buffer = context().InputBuffer();
+    SKKEditBuffer& edit = context().EditBuffer();
+    SKKOutputPort& port = context().OutputPort();
+
+    if(!edit.IsEmpty()) {
+	State state = 0;
+
+	do {
+	    // トグル変換 #2
+	    if(param.IsToggleJisx0201Kana()) {
+		toggleJisx0201Kana();
+		state = State::Transition(&SKKState::KanaInput);
+		break;
+	    }
+
+	    // 変換
+	    if(param.IsNextCandidate()) {
+		//std::cerr << "変換開始" << std::endl;
+		break;
+	    }
+	} while(0);
+
+	if(state) {
+	    port.Terminate();
+	    return state;
+	}
+    }
+
+    buffer.Input(std::tolower(param.code));
+    edit.Insert(buffer.FixedString());
+    
+    composeDisplay();
+
+    return 0;
+}
+
+#endif
Index: AquaSKK/src/statemachine/SKKStateComposeHandler.h
diff -u /dev/null AquaSKK/src/statemachine/SKKStateComposeHandler.h:1.1.2.1
--- /dev/null	Fri Oct  5 23:58:29 2007
+++ AquaSKK/src/statemachine/SKKStateComposeHandler.h	Fri Oct  5 23:58:29 2007
@@ -0,0 +1,170 @@
+/* -*- C++ -*-
+   MacOS X implementation of the SKK input method.
+
+   Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef INC__SKKStateComposeHandler__
+#define INC__SKKStateComposeHandler__
+
+#include "SKKState.h"
+
+typedef SKKState::State State;
+
+// ======================================================================
+// 見出し語構築
+// ======================================================================
+
+template <>
+State SKKState::ComposeHandler<SKK_ENTER>() {
+    SKKInputBuffer& buffer = context().InputBuffer();
+    SKKEditBuffer& edit = context().EditBuffer();
+    SKKOutputPort& port = context().OutputPort();
+
+    // 現在の候補で確定
+    port.FixString(edit.EditString());
+
+    edit.Clear();
+    buffer.Clear();
+
+    return State::Transition(&SKKState::KanaInput);
+}
+
+template <>
+State SKKState::ComposeHandler<SKK_JMODE>() {
+    State result = ComposeHandler<SKK_ENTER>();
+
+    // 改行するかどうか?(egg-like-new-line)
+    return result;
+}
+
+template <>
+State SKKState::ComposeHandler<SKK_CANCEL>() {
+    SKKInputBuffer& buffer = context().InputBuffer();
+    SKKEditBuffer& edit = context().EditBuffer();
+    SKKOutputPort& port = context().OutputPort();
+
+    edit.Clear();
+    buffer.Clear();
+
+    // 空にする
+    port.Terminate();
+
+    return State::Transition(&SKKState::KanaInput);
+}
+
+template <>
+State SKKState::ComposeHandler<SKK_BACKSPACE>() {
+    SKKInputBuffer& buffer = context().InputBuffer();
+    SKKEditBuffer& edit = context().EditBuffer();
+    SKKOutputPort& port = context().OutputPort();
+
+    if(!buffer.IsEmpty()) {
+	buffer.BackSpace();
+    } else {
+	if(!edit.IsEmpty()) {
+	    edit.BackSpace();
+	} else {
+	    port.Terminate();
+
+	    return State::Transition(&SKKState::KanaInput);
+	}
+    }
+
+    composeDisplay();
+
+    return 0;
+}
+
+template <>
+State SKKState::ComposeHandler<SKK_DELETE>() {
+    SKKInputBuffer& buffer = context().InputBuffer();
+    SKKEditBuffer& edit = context().EditBuffer();
+
+    if(buffer.IsEmpty() && !edit.IsEmpty()) {
+	edit.Delete();
+    }
+
+    composeDisplay();
+
+    return 0;
+}
+
+template <>
+State SKKState::ComposeHandler<SKK_TAB>() {
+    // 検索できた?
+    if(0) {
+	// 補完モード
+	return State::Transition(&SKKState::EntryCompletion);
+    } else {
+	return 0;
+    }
+}
+
+template <>
+State SKKState::ComposeHandler<SKK_PASTE>() {
+    // テキストがある?
+    if(0) {
+	SKKInputBuffer& buffer = context().InputBuffer();
+	SKKEditBuffer& edit = context().EditBuffer();
+
+	buffer.Clear();
+	edit.Insert("paste string");
+
+	composeDisplay();
+    }
+
+    return 0;
+}
+
+template <>
+State SKKState::ComposeHandler<SKK_LEFT>() {
+    context().InputBuffer().Clear();
+    context().EditBuffer().CursorLeft();
+    composeDisplay();
+
+    return 0;
+}
+
+template <>
+State SKKState::ComposeHandler<SKK_RIGHT>() {
+    context().InputBuffer().Clear();
+    context().EditBuffer().CursorRight();
+    composeDisplay();
+
+    return 0;
+}
+
+template <>
+State SKKState::ComposeHandler<SKK_UP>() {
+    context().InputBuffer().Clear();
+    context().EditBuffer().CursorUp();
+    composeDisplay();
+
+    return 0;
+}
+
+template <>
+State SKKState::ComposeHandler<SKK_DOWN>() {
+    context().InputBuffer().Clear();
+    context().EditBuffer().CursorDown();
+    composeDisplay();
+
+    return 0;
+}
+
+#endif
Index: AquaSKK/src/statemachine/SKKStateDirectHandler.h
diff -u /dev/null AquaSKK/src/statemachine/SKKStateDirectHandler.h:1.1.2.1
--- /dev/null	Fri Oct  5 23:58:29 2007
+++ AquaSKK/src/statemachine/SKKStateDirectHandler.h	Fri Oct  5 23:58:29 2007
@@ -0,0 +1,196 @@
+/* -*- C++ -*-
+   MacOS X implementation of the SKK input method.
+
+   Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef INC__SKKStateDirectHandler__
+#define INC__SKKStateDirectHandler__
+
+#include "SKKState.h"
+
+typedef SKKState::State State;
+
+// ======================================================================
+// 直接入力
+// ======================================================================
+
+template <>
+State SKKState::DirectHandler<SKK_ENTER>() {
+    return endRegistration(true);
+}
+
+template <>
+State SKKState::DirectHandler<SKK_CANCEL>() {
+    return endRegistration(false);
+}
+
+template <>
+State SKKState::DirectHandler<SKK_BACKSPACE>() {
+    SKKInputBuffer& buffer = context().InputBuffer();
+    SKKOutputPort& port = context().OutputPort();
+
+    if(!buffer.IsEmpty()) {
+	buffer.BackSpace();
+    } else {
+	if(!bottom()) {
+	    context().WordBuffer().BackSpace();
+	}
+    }
+
+    port.DisplayString(buffer.InputString());
+
+    return 0;
+}
+
+template <>
+State SKKState::DirectHandler<SKK_DELETE>() {
+    if(bottom()) return 0;
+
+    SKKEditBuffer& word = context().WordBuffer();
+    SKKOutputPort& port = context().OutputPort();
+    
+    word.Delete();
+    port.DisplayString("");
+
+    return 0;
+}
+
+template <>
+State SKKState::DirectHandler<SKK_PASTE>() {
+    if(bottom()) return 0;
+
+    if(0) {
+	// テキストがあればペースト
+    }
+
+    return 0;
+}
+
+template <>
+State SKKState::DirectHandler<SKK_LEFT>() {
+    if(bottom()) return 0;
+
+    SKKEditBuffer& word = context().WordBuffer();
+    SKKOutputPort& port = context().OutputPort();
+    
+    word.CursorLeft();
+    port.DisplayString("");
+
+    return 0;
+}
+
+template <>
+State SKKState::DirectHandler<SKK_RIGHT>() {
+    if(bottom()) return 0;
+
+    SKKEditBuffer& word = context().WordBuffer();
+    SKKOutputPort& port = context().OutputPort();
+    
+    word.CursorRight();
+    port.DisplayString("");
+
+    return 0;
+}
+
+template <>
+State SKKState::DirectHandler<SKK_UP>() {
+    if(bottom()) return 0;
+
+    SKKEditBuffer& word = context().WordBuffer();
+    SKKOutputPort& port = context().OutputPort();
+    
+    word.CursorUp();
+    port.DisplayString("");
+
+    return 0;
+}
+
+template <>
+State SKKState::DirectHandler<SKK_DOWN>() {
+    if(bottom()) return 0;
+
+    SKKEditBuffer& word = context().WordBuffer();
+    SKKOutputPort& port = context().OutputPort();
+    
+    word.CursorDown();
+    port.DisplayString("");
+
+    return 0;
+}
+
+template <>
+State SKKState::DirectHandler<SKK_CHAR>(const SKKEventParam& param) {
+    SKKInputBuffer& buffer = context().InputBuffer();
+    SKKOutputPort& port = context().OutputPort();
+    
+    // 直接入力文字は無視する
+    if(param.IsDirect()) {
+	if(bottom()) return 0;
+
+	port.DisplayString(std::string(1, param.code));
+
+	return 0;
+    }
+
+    if(!buffer.Input(param.code)) {
+	State state = 0;
+	// 確定しないのはかな入力時のみ
+	do {
+	    if(param.IsSwitchToAscii()) {
+		state = State::Transition(&SKKState::Ascii);
+		break;
+	    }
+
+	    if(param.IsSwitchToJisx0208Latin()) {
+		state = State::Transition(&SKKState::Jisx0208Latin);
+		break;
+	    }
+
+	    if(param.IsUpperCases()) {
+		state = State::Forward(&SKKState::KanaEntry);
+		break;
+	    }
+
+	    if(param.IsEnterJapanese()) {
+		state = State::Transition(&SKKState::KanaEntry);
+		break;
+	    }
+
+	    if(param.IsEnterAbbrev()) {
+		state = State::Transition(&SKKState::AsciiEntry);
+		break;
+	    }
+	} while(0);
+
+	if(state) {
+	    buffer.Clear();
+	    port.Terminate();
+	    return state;
+	}
+    }
+
+    if(!buffer.FixedString().empty()) {
+	port.FixString(buffer.FixedString());
+    }
+
+    port.DisplayString(buffer.InputString());
+
+    return 0;
+}
+
+#endif
Index: AquaSKK/src/statemachine/SKKStateKanaEntryHandler.h
diff -u /dev/null AquaSKK/src/statemachine/SKKStateKanaEntryHandler.h:1.1.2.1
--- /dev/null	Fri Oct  5 23:58:29 2007
+++ AquaSKK/src/statemachine/SKKStateKanaEntryHandler.h	Fri Oct  5 23:58:29 2007
@@ -0,0 +1,127 @@
+/* -*- C++ -*-
+   MacOS X implementation of the SKK input method.
+
+   Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef INC__SKKStateKanaEntryHandler__
+#define INC__SKKStateKanaEntryHandler__
+
+#include "SKKState.h"
+
+typedef SKKState::State State;
+
+// ======================================================================
+// かな見出し語
+// ======================================================================
+
+template <>
+State SKKState::KanaEntryHandler<SKK_CHAR>(const SKKEventParam& param) {
+    SKKInputBuffer& buffer = context().InputBuffer();
+    SKKEditBuffer& edit = context().EditBuffer();
+    SKKOutputPort& port = context().OutputPort();
+
+    if(!edit.IsEmpty()) {
+	State state = 0;
+
+	do {
+	    // トグル変換 #1
+	    if(param.IsToggleKana()) {
+		toggleKana();
+		state = State::Transition(&SKKState::KanaInput);
+		break;
+	    }
+
+	    // トグル変換 #2
+	    if(param.IsToggleJisx0201Kana()) {
+		toggleJisx0201Kana();
+		state = State::Transition(&SKKState::KanaInput);
+		break;
+	    }
+
+	    // 送りあり
+	    if(param.IsUpperCases()) {
+		char code = std::tolower(param.code);
+
+		// 入力文字が単独で変換可能でなければ、変換を試みる
+		// KesSite 対応
+		SKKInputBuffer tmp;
+		if(!tmp.Input(code)) {
+		    if(buffer.Input(code)) {
+			edit.Insert(buffer.FixedString());
+		    }
+		}
+
+		// 送りバッファの初期化
+		context().OkuriBuffer().Initialize(code);
+		state = State::Forward(&SKKState::OkuriEntry);
+		break;
+	    }
+
+	    // 変換
+	    if(param.IsNextCandidate()) {
+		//std::cerr << "変換開始" << std::endl;
+		break;
+	    }
+	} while(0);
+
+	if(state) {
+	    port.Terminate();
+	    return state;
+	}
+    }
+
+    if(buffer.Input(std::tolower(param.code))) {
+	edit.Insert(buffer.FixedString());
+    } else {
+	State state = 0;
+
+	do {
+	    if(param.IsSwitchToAscii()) {
+		state = State::Transition(&SKKState::Ascii);
+		break;
+	    }
+
+	    if(param.IsSwitchToJisx0208Latin()) {
+		state = State::Transition(&SKKState::Jisx0208Latin);
+		break;
+	    }
+
+	    if(param.IsEnterJapanese() && !edit.IsEmpty()) {
+		state = State::Transition(&SKKState::KanaEntry);
+		break;
+	    }
+	} while(0);
+
+	if(state) {
+	    port.FixString(edit.EditString());
+	    edit.Clear();
+	    buffer.Clear();
+	    return state;
+	}
+
+	if(!buffer.FixedString().empty()) {
+	    edit.Insert(buffer.FixedString());
+	}
+    }
+    
+    composeDisplay();
+
+    return 0;
+}
+
+#endif
Index: AquaSKK/src/statemachine/SKKStateOkuriEntryHandler.h
diff -u /dev/null AquaSKK/src/statemachine/SKKStateOkuriEntryHandler.h:1.1.2.1
--- /dev/null	Fri Oct  5 23:58:29 2007
+++ AquaSKK/src/statemachine/SKKStateOkuriEntryHandler.h	Fri Oct  5 23:58:29 2007
@@ -0,0 +1,61 @@
+/* -*- C++ -*-
+   MacOS X implementation of the SKK input method.
+
+   Copyright (C) 2007 Tomotaka SUWA <t.suw****@mac*****>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef INC__SKKStateOkuriEntryHandler__
+#define INC__SKKStateOkuriEntryHandler__
+
+#include "SKKState.h"
+
+typedef SKKState::State State;
+
+// ======================================================================
+// 送りあり
+// ======================================================================
+
+template <>
+State SKKState::OkuriEntryHandler<SKK_BACKSPACE>() {
+    SKKOkuriBuffer& okuri = context().OkuriBuffer();
+
+    if(okuri.IsEmpty()) {
+	composeDisplay();
+	return State::Transition(&SKKState::KanaInput);
+    }
+
+    okuri.BackSpace();
+    okuriDisplay();
+
+    return 0;
+}
+
+template <>
+State SKKState::OkuriEntryHandler<SKK_CHAR>(const SKKEventParam& param) {
+    SKKOkuriBuffer& okuri = context().OkuriBuffer();
+    SKKOutputPort& port = context().OutputPort();
+
+    if(okuri.Input(std::tolower(param.code)) && okuri.IsEmpty()) {
+	// 変換開始?
+    }
+
+    okuriDisplay();
+
+    return 0;
+}
+
+#endif


aquaskk-changes メーリングリストの案内
アーカイブの一覧に戻る